From f5e85d5f63cdf0d8f9f635418f58b8998b4f9f83 Mon Sep 17 00:00:00 2001 From: dsyer Date: Thu, 6 Mar 2008 21:59:13 +0000 Subject: [PATCH] Change svn:eol-style to LF --- dist/.project | 22 +- dist/license.txt | 402 +-- dist/notice.txt | 42 +- docs/.project | 17 - .../org.eclipse.mylyn.tasks.ui.prefs | 8 +- docs/src/docbkx/resources/css/html.css | 842 ++--- docs/src/models/domain-classdiagram.dnx | 1694 +++++----- .../models/flat-file-input-source-design.dnx | 1102 +++---- docs/src/models/io-design.dnx | 2784 ++++++++--------- docs/src/models/item-reader-design.dnx | 1966 ++++++------ docs/src/models/item-stream-adapter.dnx | 706 ++--- docs/src/models/repository-classdiagram.dnx | 964 +++--- .../docbook/reference/batch-job-testing.xml | 34 +- .../site/docbook/reference/batch-launch.xml | 34 +- .../reference/batch-performance-testing.xml | 104 +- docs/src/site/docbook/reference/namespace.xml | 22 +- .../reference/partitioned-containers.xml | 20 +- .../site/docbook/reference/spring-tasklet.xml | 60 +- spring-batch-core/.project | 60 +- .../.settings/org.eclipse.jdt.core.prefs | 10 +- .../org.eclipse.mylyn.tasks.ui.prefs | 8 +- spring-batch-core/.springBeans | 62 +- .../batch/core/configuration/JobLocator.java | 82 +- .../batch/core/configuration/JobRegistry.java | 94 +- .../configuration/ListableJobRegistry.java | 70 +- .../core/domain/JobExecutionException.java | 62 +- .../batch/core/domain/Step.java | 128 +- .../repository/DuplicateJobException.java | 88 +- .../batch/core/repository/JobException.java | 88 +- .../JobExecutionAlreadyRunningException.java | 82 +- .../core/repository/JobRestartException.java | 82 +- .../core/repository/NoSuchJobException.java | 92 +- .../ExitStatusExceptionClassifier.java | 88 +- .../batch/core/domain/BatchStatusTests.java | 166 +- .../batch/core/domain/EntityTests.java | 256 +- .../domain/JobExecutionExceptionTests.java | 82 +- .../batch/core/domain/JobExecutionTests.java | 310 +- .../batch/core/domain/JobInstanceTests.java | 104 +- .../domain/JobInterruptedExceptionTests.java | 82 +- .../batch/core/domain/StepExecutionTests.java | 542 ++-- .../batch/core/domain/StepSupport.java | 234 +- .../DuplicateJobExceptionTests.java | 88 +- .../core/repository/JobExceptionTests.java | 88 +- ...ExecutionAlreadyRunningExceptionTests.java | 80 +- .../repository/JobRestartExceptionTests.java | 86 +- .../repository/NoSuchJobExceptionTests.java | 88 +- spring-batch-execution/.project | 62 +- .../.settings/org.eclipse.jdt.core.prefs | 14 +- spring-batch-execution/.springBeans | 88 +- .../JobRegistryBeanPostProcessor.java | 226 +- .../configuration/MapJobRegistry.java | 190 +- .../batch/execution/launch/JobLauncher.java | 108 +- .../launch/support/ExitCodeMapper.java | 60 +- .../launch/support/ExportedJobLauncher.java | 148 +- .../launch/support/JvmSystemExiter.java | 80 +- .../support/SimpleJvmExitCodeMapper.java | 176 +- .../launch/support/SystemExiter.java | 78 +- .../dao/AbstractJdbcBatchMetadataDao.java | 104 +- .../repository/dao/JdbcJobExecutionDao.java | 438 +-- .../repository/dao/JdbcJobInstanceDao.java | 472 +-- .../repository/dao/JdbcStepExecutionDao.java | 850 ++--- .../repository/dao/JobExecutionDao.java | 110 +- .../repository/dao/JobInstanceDao.java | 84 +- .../repository/dao/MapJobExecutionDao.java | 152 +- .../repository/dao/MapJobInstanceDao.java | 88 +- .../repository/dao/StepExecutionDao.java | 96 +- .../batch/execution/step/AbstractStep.java | 186 +- .../batch/execution/step/ItemHandler.java | 156 +- .../execution/step/ItemOrientedStep.java | 1074 +++---- .../step/support/AbstractStepFactoryBean.java | 394 +-- .../support/ItemSkipPolicyItemHandler.java | 204 +- .../RepeatOperationsStepFactoryBean.java | 280 +- .../SimpleExitStatusExceptionClassifier.java | 158 +- .../step/support/SimpleItemHandler.java | 230 +- .../support/StatefulRetryStepFactoryBean.java | 394 +-- .../src/main/sql/db2.properties | 16 +- spring-batch-execution/src/main/sql/db2.vpp | 4 +- .../src/main/sql/derby.properties | 18 +- spring-batch-execution/src/main/sql/derby.vpp | 4 +- .../src/main/sql/hsqldb.properties | 18 +- .../src/main/sql/hsqldb.vpp | 8 +- .../src/main/sql/mysql.properties | 20 +- spring-batch-execution/src/main/sql/mysql.vpp | 6 +- .../src/main/sql/oracle10g.properties | 18 +- .../src/main/sql/oracle10g.vpp | 4 +- .../src/main/sql/postgresql.properties | 18 +- .../src/main/sql/postgresql.vpp | 4 +- .../JobRegistryBeanPostProcessorTests.java | 262 +- .../configuration/MapJobRegistryTests.java | 190 +- .../batch/execution/job/AbstractJobTests.java | 230 +- .../support/SimpleJvmExitCodeMapperTests.java | 180 +- .../launch/support/StubJobLauncher.java | 108 +- .../repository/dao/AbstractStepDaoTests.java | 448 +-- .../repository/dao/JdbcJobDaoQueryTests.java | 164 +- .../repository/dao/JdbcJobDaoTests.java | 64 +- .../dao/JdbcStepDaoPrefixTests.java | 222 +- .../repository/dao/JdbcStepDaoTests.java | 82 +- .../dao/MapJobExecutionDaoTests.java | 188 +- .../dao/MapJobInstanceDaoTests.java | 112 +- ...NoSuchBatchDomainObjectExceptionTests.java | 64 +- .../execution/step/ItemOrientedStepTests.java | 1430 ++++----- .../batch/execution/step/StepSupport.java | 234 +- .../support/DefaultStepFactoryBeanTests.java | 378 +-- .../step/support/JobRepositorySupport.java | 146 +- ...pleExitStatusExceptionClassifierTests.java | 154 +- .../ThreadStepInterruptionPolicyTests.java | 116 +- spring-batch-infrastructure/.project | 58 +- .../.settings/org.eclipse.jdt.core.prefs | 16 +- .../org.eclipse.mylyn.tasks.ui.prefs | 8 +- ...org.springframework.ide.eclipse.core.prefs | 66 +- spring-batch-infrastructure/.springBeans | 30 +- .../common/BinaryExceptionClassifier.java | 154 +- .../common/SubclassExceptionClassifier.java | 226 +- .../io/cursor/HibernateCursorItemReader.java | 484 +-- .../batch/io/cursor/JdbcCursorItemReader.java | 1038 +++--- .../io/driving/DrivingQueryItemReader.java | 408 +-- .../driving/IbatisDrivingQueryItemReader.java | 134 +- .../support/ExecutionContextRowMapper.java | 106 +- .../driving/support/IbatisKeyGenerator.java | 202 +- .../MultipleColumnJdbcKeyGenerator.java | 276 +- .../support/SingleColumnJdbcKeyGenerator.java | 304 +- .../DynamicMethodInvocationException.java | 46 +- .../exception/FlatFileParsingException.java | 128 +- .../batch/io/exception/ParsingException.java | 80 +- .../batch/io/file/FlatFileItemWriter.java | 978 +++--- .../io/file/mapping/DefaultFieldSet.java | 1006 +++--- .../mapping/PassThroughFieldSetMapper.java | 106 +- .../io/file/separator/ResourceLineReader.java | 678 ++-- .../file/transform/AbstractLineTokenizer.java | 168 +- .../transform/DelimitedLineTokenizer.java | 426 +-- .../transform/FixedLengthLineAggregator.java | 360 +-- .../file/transform/FixedLengthTokenizer.java | 160 +- .../batch/io/file/transform/Range.java | 124 +- .../transform/RangeArrayPropertyEditor.java | 262 +- .../io/support/BatchSqlUpdateItemWriter.java | 454 +-- .../batch/io/support/FileUtils.java | 132 +- .../io/support/HibernateAwareItemWriter.java | 420 +-- .../batch/io/xml/EventReaderDeserializer.java | 28 +- .../batch/io/xml/EventWriterSerializer.java | 42 +- .../batch/io/xml/StaxEventItemReader.java | 538 ++-- .../batch/io/xml/StaxEventItemWriter.java | 894 +++--- .../oxm/MarshallingEventWriterSerializer.java | 74 +- .../UnmarshallingEventReaderDeserializer.java | 76 +- .../xml/stax/AbstractEventReaderWrapper.java | 116 +- .../xml/stax/AbstractEventWriterWrapper.java | 116 +- .../xml/stax/DefaultFragmentEventReader.java | 360 +-- .../stax/DefaultTransactionalEventReader.java | 192 +- .../batch/io/xml/stax/EventSequence.java | 184 +- .../io/xml/stax/FragmentEventReader.java | 66 +- .../stax/NoStartEndDocumentStreamWriter.java | 50 +- .../io/xml/stax/TransactionalEventReader.java | 44 +- .../item/ExecutionContextUserSupport.java | 98 +- .../item/reader/AggregateItemReader.java | 226 +- .../item/reader/DelegatingItemReader.java | 184 +- .../batch/item/reader/ItemReaderAdapter.java | 110 +- .../item/reader/ValidatingItemReader.java | 118 +- .../item/writer/CompositeItemWriter.java | 60 +- .../item/writer/DelegatingItemWriter.java | 160 +- .../batch/item/writer/ItemWriterAdapter.java | 108 +- ...ropertyExtractingDelegatingItemWriter.java | 154 +- .../batch/repeat/ExitStatus.java | 446 +-- .../AbstractMethodInvokingDelegator.java | 350 +-- ...rnateCursorItemReaderIntegrationTests.java | 126 +- ...sorItemReaderStatefulIntegrationTests.java | 32 +- .../JdbcCursorItemReaderIntegrationTests.java | 60 +- .../batch/io/driving/CompositeKeyFooDao.java | 116 +- .../batch/io/driving/FooDao.java | 60 +- .../batch/io/driving/FooInputSource.java | 136 +- .../batch/io/driving/FooRowMapper.java | 42 +- .../IbatisItemReaderIntegrationTests.java | 80 +- ...rivingQueryItemReaderIntegrationTests.java | 88 +- ...rivingQueryItemReaderIntegrationTests.java | 52 +- .../batch/io/driving/SingleKeyFooDao.java | 56 +- .../batch/io/file/FieldSetTests.java | 906 +++--- .../io/file/FlatFileItemReaderBasicTests.java | 678 ++-- .../io/file/ResourceLineReaderTests.java | 392 +-- .../batch/io/file/mapping/TestObject.java | 270 +- .../transform/CommonLineTokenizerTests.java | 78 +- .../DelimitedLineTokenizerTests.java | 370 +-- .../FixedLengthLineAggregatorTests.java | 344 +- .../transform/FixedLengthTokenizerTests.java | 256 +- .../RangeArrayPropertyEditorTests.java | 218 +- .../batch/io/sample/domain/Foo.java | 108 +- .../batch/io/sample/domain/FooService.java | 106 +- .../batch/io/sample/domain/Order.java | 166 +- ...bstractJdbcItemReaderIntegrationTests.java | 346 +- ...tDataSourceItemReaderIntegrationTests.java | 506 +-- .../batch/io/support/FileUtilsTests.java | 264 +- .../HibernateAwareItemWriterTests.java | 412 +-- .../batch/io/xml/EventHelper.java | 60 +- .../io/xml/StaxEventItemReaderTests.java | 848 ++--- .../io/xml/StaxEventItemWriterTests.java | 468 +-- ...MarshallingObjectToXmlSerializerTests.java | 264 +- ...nmarshallingFragmentDeserializerTests.java | 184 +- .../stax/AbstractEventReaderWrapperTests.java | 270 +- .../stax/AbstractEventWriterWrapperTests.java | 270 +- .../stax/DefaultFragmentEventReaderTests.java | 288 +- .../DefaultTransactionalEventReaderTests.java | 136 +- .../batch/io/xml/stax/EventSequenceTests.java | 78 +- .../stax/NoStartEndDocumentWriterTests.java | 102 +- .../ExecutionContextUserSupportTests.java | 68 +- .../item/reader/AggregateItemReaderTests.java | 120 +- .../DelegatingItemReaderIntegrationTests.java | 104 +- .../reader/DelegatingItemReaderTests.java | 222 +- .../reader/ValidatingItemReaderTests.java | 232 +- .../writer/CompositeItemTransformerTests.java | 194 +- .../item/writer/CompositeItemWriterTests.java | 110 +- .../ItemTransformerItemWriterTests.java | 144 +- .../item/writer/ItemWriterAdapterTests.java | 112 +- ...egatingItemProccessorIntegrationTests.java | 118 +- .../batch/repeat/ExitStatusTests.java | 420 +-- .../context/RepeatContextSupportTests.java | 186 +- .../batch/support/AbstractDelegatorTests.java | 344 +- .../batch/io/cursor/Foo-write.hbm.xml | 28 +- .../batch/io/cursor/Foo.hbm.xml | 28 +- .../batch/io/driving/ibatis-config.xml | 22 +- .../batch/io/driving/ibatis-foo.xml | 80 +- .../io/sql/destroy-foo-schema-hsqldb.sql | 2 +- .../batch/io/sql/init-foo-schema-hsqldb.sql | 42 +- .../item/reader/delegating-item-provider.xml | 22 +- .../item/writer/delegating-item-writer.xml | 22 +- .../item/writer/pe-delegating-item-writer.xml | 24 +- .../retry/aop/retry-transaction-test.xml | 70 +- spring-batch-integration/.project | 60 +- .../org.eclipse.mylyn.tasks.ui.prefs | 8 +- spring-batch-integration/.springBeans | 74 +- ...bstractStaxEventReaderItemReaderTests.java | 168 +- ...bstractStaxEventWriterItemWriterTests.java | 154 +- .../batch/io/oxm/CastorMarshallingTests.java | 40 +- .../io/oxm/CastorUnmarshallingTests.java | 36 +- .../batch/io/oxm/XStreamMarshallingTests.java | 36 +- .../io/oxm/XStreamUnmarshallingTests.java | 40 +- .../batch/io/oxm/domain/Trade.java | 144 +- .../batch/io/oxm/expected-output.xml | 46 +- .../springframework/batch/io/oxm/input.xml | 42 +- .../batch/io/oxm/mapping-castor.xml | 44 +- spring-batch-samples/.project | 64 +- .../.settings/hsql-manager.launch | 26 +- .../.settings/hsql-server.launch | 26 +- .../.settings/jmxLauncher.launch | 32 +- .../.settings/jobLauncher.launch | 32 +- .../.settings/org.eclipse.jdt.core.prefs | 8 +- .../org.eclipse.wst.validation.prefs | 12 +- .../.settings/quartzLauncher.launch | 30 +- spring-batch-samples/.springBeans | 526 ++-- spring-batch-samples/pom.xml | 738 ++--- spring-batch-samples/server.properties | 10 +- .../batch/sample/dao/HibernateCreditDao.java | 224 +- .../sample/dao/IbatisCustomerCreditDao.java | 110 +- .../batch/sample/dao/JdbcGameDao.java | 90 +- .../batch/sample/dao/JdbcPlayerDao.java | 54 +- .../sample/dao/JdbcPlayerSummaryDao.java | 84 +- .../batch/sample/dao/PlayerDao.java | 16 +- .../batch/sample/domain/CustomerCredit.java | 140 +- .../batch/sample/domain/Game.java | 430 +-- .../batch/sample/domain/PersonService.java | 158 +- .../batch/sample/domain/Player.java | 128 +- .../batch/sample/domain/PlayerSummary.java | 216 +- .../handler/FootballExceptionHandler.java | 48 +- .../item/reader/GeneratingItemReader.java | 146 +- .../sample/item/reader/StagingItemReader.java | 492 +-- .../BatchSqlCustomerCreditIncreaseWriter.java | 138 +- .../writer/CustomerCreditIncreaseWriter.java | 74 +- .../sample/item/writer/PlayerItemWriter.java | 42 +- .../item/writer/RetrySampleItemWriter.java | 58 +- .../sample/item/writer/StagingItemWriter.java | 234 +- .../sample/launch/TaskExecutorLauncher.java | 222 +- .../mapping/CustomerCreditRowMapper.java | 50 +- .../batch/sample/mapping/GameMapper.java | 70 +- .../batch/sample/mapping/PlayerMapper.java | 54 +- .../sample/mapping/PlayerSummaryMapper.java | 110 +- .../src/main/resources/CustomerCredit.hbm.xml | 32 +- ...070122.teststream.ImportPersonDataStep.txt | 4 +- ...0070122.teststream.ImportTradeDataStep.txt | 8 +- ...0070122.teststream.ImportTradeDataStep.txt | 8 +- .../20070122.teststream.multilineStep.txt | 18 +- .../data/multilineJob/input/problematic.txt | 40 +- ...20070122.teststream.multilineOrderStep.txt | 44 +- .../data/multilineOrderJob/order_sample.txt | 102 +- ...0070122.teststream.ImportTradeDataStep.txt | 10 +- ...0070122.teststream.ImportTradeDataStep.txt | 8 +- ...0070122.teststream.ImportTradeDataStep.txt | 8 +- ...0070207.testStream.ImportTradeDataStep.txt | 10 +- .../input/20070918.testStream.xmlFileStep.xml | 114 +- .../resources/data/staxJob/input/trade.xsd | 34 +- .../data/staxJob/output/expected-output.xml | 112 +- ...0070122.teststream.ImportTradeDataStep.txt | 8 +- .../src/main/resources/ibatis-config.xml | 16 +- .../main/resources/ibatis-customer-credit.xml | 46 +- .../jobs/multilineOrderInputDescriptors.xml | 140 +- .../main/resources/jobs/multilineOrderJob.xml | 350 +-- .../jobs/multilineOrderOutputDescriptors.xml | 76 +- .../src/main/sql/business-schema.sql.vpp | 4 +- .../src/main/sql/db2.properties | 14 +- spring-batch-samples/src/main/sql/db2.vpp | 4 +- .../src/main/sql/derby.properties | 16 +- spring-batch-samples/src/main/sql/derby.vpp | 4 +- .../src/main/sql/hsqldb.properties | 16 +- spring-batch-samples/src/main/sql/hsqldb.vpp | 8 +- .../src/main/sql/mysql.properties | 18 +- spring-batch-samples/src/main/sql/mysql.vpp | 6 +- .../src/main/sql/oracle10g.properties | 16 +- .../src/main/sql/oracle10g.vpp | 4 +- .../src/main/sql/postgresql.properties | 16 +- .../src/main/sql/postgresql.vpp | 4 +- .../AbstractCustomerCreditIncreaseTests.java | 282 +- .../BatchSqlUpdateJobFunctionalTests.java | 20 +- ...mpositeProcessorSampleFunctionalTests.java | 182 +- .../batch/sample/DefaultJobLoader.java | 192 +- .../sample/DelegatingJobFunctionalTests.java | 42 +- .../batch/sample/ExportedJobLoader.java | 74 +- .../sample/FootballJobFunctionalTests.java | 44 +- .../HibernateFailureJobFunctionalTests.java | 178 +- .../sample/HibernateJobFunctionalTests.java | 20 +- .../sample/IbatisJobFunctionalTests.java | 22 +- .../batch/sample/JobLoader.java | 74 +- .../sample/MultilineJobFunctionalTests.java | 74 +- .../sample/ParallelJobFunctionalTests.java | 64 +- .../sample/RetrySampleFunctionalTests.java | 60 +- .../sample/RollbackJobFunctionalTests.java | 64 +- .../batch/sample/TradeJobFunctionalTests.java | 402 +-- .../sample/XmlStaxJobFunctionalTests.java | 76 +- ...obExecutionNotificationPublisherTests.java | 98 +- .../dao/FlatFileCustomerCreditDaoTests.java | 164 +- .../sample/dao/FlatFileOrderWriterTests.java | 168 +- .../sample/dao/JdbcCustomerDebitDaoTests.java | 84 +- .../dao/JdbcGameDaoIntegrationTests.java | 198 +- .../sample/dao/JdbcJobRepositoryTests.java | 408 +-- .../dao/JdbcPlayerDaoIntegrationTests.java | 118 +- .../JdbcPlayerSummaryDaoIntegrationTests.java | 140 +- .../sample/dao/JdbcTradeWriterTests.java | 88 +- .../sample/dao/OrderTransformerTests.java | 124 +- .../reader/GeneratingItemReaderTests.java | 62 +- .../item/reader/OrderItemReaderTests.java | 302 +- .../item/reader/StagingItemReaderTests.java | 308 +- .../CustomerCreditIncreaseProcessorTests.java | 106 +- .../CustomerCreditUpdateProcessorTests.java | 114 +- .../writer/CustomerUpdateProcessorTests.java | 72 +- .../sample/item/writer/OrderWriterTests.java | 108 +- .../writer/RetrySampleItemWriterTests.java | 70 +- .../item/writer/TradeProcessorTests.java | 96 +- .../mapping/AbstractFieldSetMapperTests.java | 82 +- .../mapping/AbstractRowMapperTests.java | 102 +- .../mapping/AddressFieldSetMapperTests.java | 106 +- .../mapping/BillingFieldSetMapperTests.java | 68 +- .../mapping/CustomerCreditRowMapperTests.java | 84 +- .../mapping/CustomerFieldSetMapperTests.java | 114 +- .../mapping/HeaderFieldSetMapperTests.java | 82 +- .../mapping/OrderItemFieldSetMapperTests.java | 124 +- .../mapping/ShippingFieldSetMapperTests.java | 74 +- .../mapping/TradeFieldSetMapperTests.java | 100 +- .../sample/mapping/TradeRowMapperTests.java | 92 +- ...ExceptionThrowingItemReaderProxyTests.java | 98 +- .../tasklet/SimpleTradeTaskletTests.java | 114 +- .../batch/sample/tasklet/StepSupport.java | 234 +- .../custom/FutureDateFunctionTests.java | 122 +- .../custom/TotalOrderItemsFunctionTests.java | 164 +- .../ValidateDiscountsFunctionTests.java | 332 +- .../ValidateHandlingPricesFunctionTests.java | 162 +- .../custom/ValidateIdsFunctionTests.java | 160 +- .../custom/ValidatePricesFunctionTests.java | 164 +- .../ValidateQuantitiesFunctionTests.java | 160 +- .../ValidateShippingPricesFunctionTests.java | 162 +- .../ValidateTotalPricesFunctionTests.java | 266 +- src/.project | 38 +- .../org.eclipse.mylyn.tasks.ui.prefs | 8 +- src/main/xsl/emma.xsl | 34 +- src/site/apt/building.apt | 15 + src/site/apt/migration/1.0-m2-m3.apt | 134 +- src/site/apt/migration/1.0-m3-m4.apt | 118 +- src/site/apt/migration/1.0-m4-m5.apt | 98 +- src/site/apt/migration/index.apt | 14 + 372 files changed, 33472 insertions(+), 33470 deletions(-) create mode 100644 src/site/apt/migration/index.apt diff --git a/dist/.project b/dist/.project index 78f38838c0..b88c2220f6 100644 --- a/dist/.project +++ b/dist/.project @@ -1,11 +1,11 @@ - - - dist - - - - - - - - + + + dist + + + + + + + + diff --git a/dist/license.txt b/dist/license.txt index 29f81d812f..261eeb9e9f 100644 --- a/dist/license.txt +++ b/dist/license.txt @@ -1,201 +1,201 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/dist/notice.txt b/dist/notice.txt index 2cd3e11224..b45a527d0b 100644 --- a/dist/notice.txt +++ b/dist/notice.txt @@ -1,21 +1,21 @@ - ====================================================================== - == NOTICE file corresponding to section 4 d of the Apache License, == - == Version 2.0, in this case for the Spring Framework distribution. == - ====================================================================== - - This product includes software developed by - the Apache Software Foundation (http://www.apache.org). - - The end-user documentation included with a redistribution, if any, - must include the following acknowledgement: - - "This product includes software developed by the Spring Framework - Project (http://www.springframework.org)." - - Alternatively, this acknowledgement may appear in the software itself, - if and wherever such third-party acknowledgements normally appear. - - The names "Spring" and "Spring Framework" must not be used to - endorse or promote products derived from this software without - prior written permission. For written permission, please contact - rod.johnson@interface21.com or juergen.hoeller@interface21.com. + ====================================================================== + == NOTICE file corresponding to section 4 d of the Apache License, == + == Version 2.0, in this case for the Spring Framework distribution. == + ====================================================================== + + This product includes software developed by + the Apache Software Foundation (http://www.apache.org). + + The end-user documentation included with a redistribution, if any, + must include the following acknowledgement: + + "This product includes software developed by the Spring Framework + Project (http://www.springframework.org)." + + Alternatively, this acknowledgement may appear in the software itself, + if and wherever such third-party acknowledgements normally appear. + + The names "Spring" and "Spring Framework" must not be used to + endorse or promote products derived from this software without + prior written permission. For written permission, please contact + rod.johnson@interface21.com or juergen.hoeller@interface21.com. diff --git a/docs/.project b/docs/.project index 4862ed9a3d..2f343be4a0 100644 --- a/docs/.project +++ b/docs/.project @@ -4,21 +4,4 @@ - - - org.eclipse.jdt.core.javabuilder - - - - - org.devzuz.q.maven.jdt.core.mavenIncrementalBuilder - - - - - - org.eclipse.jdt.core.javanature - org.devzuz.q.maven.jdt.core.mavenNature - - diff --git a/docs/.settings/org.eclipse.mylyn.tasks.ui.prefs b/docs/.settings/org.eclipse.mylyn.tasks.ui.prefs index 7110cefbaf..214fc66046 100644 --- a/docs/.settings/org.eclipse.mylyn.tasks.ui.prefs +++ b/docs/.settings/org.eclipse.mylyn.tasks.ui.prefs @@ -1,4 +1,4 @@ -#Sun Jul 08 09:33:19 BST 2007 -eclipse.preferences.version=1 -project.repository.kind=jira -project.repository.url=http\://opensource.atlassian.com/projects/spring +#Sun Jul 08 09:33:19 BST 2007 +eclipse.preferences.version=1 +project.repository.kind=jira +project.repository.url=http\://opensource.atlassian.com/projects/spring diff --git a/docs/src/docbkx/resources/css/html.css b/docs/src/docbkx/resources/css/html.css index 36297ac36d..10936f3370 100644 --- a/docs/src/docbkx/resources/css/html.css +++ b/docs/src/docbkx/resources/css/html.css @@ -1,421 +1,421 @@ -body { - text-align: justify; - margin-right: 2em; - margin-left: 2em; -} - -a, - a[accesskey^ - -= -"h" -] -, -a[accesskey^ - -= -"n" -] -, -a[accesskey^ - -= -"u" -] -, -a[accesskey^ - -= -"p" -] -{ -font-family: Verdana, Arial, helvetica, sans-serif - -; -font-size: - -12 -px - -; -color: #003399 - -; -} - -a:active { - color: #003399; -} - -a:visited { - color: #888888; -} - -p { - font-family: Verdana, Arial, sans-serif; -} - -dt { - font-family: Verdana, Arial, sans-serif; - font-size: 12px; -} - -p, dl, dt, dd, blockquote { - color: #000000; - margin-bottom: 3px; - margin-top: 3px; - padding-top: 0px; -} - -ol, ul, p { - margin-top: 6px; - margin-bottom: 6px; -} - -p, blockquote { - font-size: 90%; -} - -p.releaseinfo { - font-size: 100%; - font-weight: bold; - font-family: Verdana, Arial, helvetica, sans-serif; - padding-top: 10px; -} - -p.pubdate { - font-size: 120%; - font-weight: bold; - font-family: Verdana, Arial, helvetica, sans-serif; -} - -td { - font-size: 80%; -} - -td, th, span { - color: #000000; -} - -td[width^ - -= -"40%" -] -{ -font-family: Verdana, Arial, helvetica, sans-serif - -; -font-size: - -12 -px - -; -color: #003399 - -; -} - -table[summary^ - -= -"Navigation header" -] -tbody tr th[colspan^ - -= -"3" -] -{ -font-family: Verdana, Arial, helvetica, sans-serif - -; -} - -blockquote { - margin-right: 0px; -} - -h1, h2, h3, h4, h6, H6 { - color: #000000; - font-weight: 500; - margin-top: 0px; - padding-top: 14px; - font-family: Verdana, Arial, helvetica, sans-serif; - margin-bottom: 0px; -} - -h2.title { - font-weight: 800; - margin-bottom: 8px; -} - -h2.subtitle { - font-weight: 800; - margin-bottom: 20px; -} - -.firstname, .surname { - font-size: 12px; - font-family: Verdana, Arial, helvetica, sans-serif; -} - -table { - border-collapse: collapse; - border-spacing: 0; - border: 1px black; - empty-cells: hide; - margin: 10px 0px 30px 50px; - width: 90%; -} - -div.table { - margin: 30px 0px 30px 0px; - border: 1px dashed gray; - padding: 10px; -} - -div .table-contents table { - border: 1px solid black; -} - -div.table > p.title { - padding-left: 10px; -} - -table[summary^ - -= -"Navigation footer" -] -{ -border-collapse: collapse - -; -border-spacing: - -0 -; -border: - -1 -px black - -; -empty-cells: hide - -; -margin: - -0 -px - -; -width: - -100 -% -; -} - -table[summary^ - -= -"Note" -] -, -table[summary^ - -= -"Warning" -] -, -table[summary^ - -= -"Tip" -] -{ -border-collapse: collapse - -; -border-spacing: - -0 -; -border: - -1 -px black - -; -empty-cells: hide - -; -margin: - -10 -px - -0 -px - -10 -px - -- -20 -px - -; -width: - -100 -% -; -} - -td { - padding: 4pt; - font-family: Verdana, Arial, helvetica, sans-serif; -} - -div.warning TD { - text-align: justify; -} - -h1 { - font-size: 150%; -} - -h2 { - font-size: 110%; -} - -h3 { - font-size: 100%; - font-weight: bold; -} - -h4 { - font-size: 90%; - font-weight: bold; -} - -h5 { - font-size: 90%; - font-style: italic; -} - -h6 { - font-size: 100%; - font-style: italic; -} - -tt { - font-size: 110%; - font-family: "Courier New", Courier, monospace; - color: #000000; -} - -.navheader, .navfooter { - border: none; -} - -div.navfooter table { - border: dashed gray; - border-width: 1px 1px 1px 1px; - background-color: #cde48d; -} - -pre { - font-size: 110%; - padding: 5px; - border-style: solid; - border-width: 1px; - border-color: #CCCCCC; - background-color: #f3f5e9; -} - -ul, ol, li { - list-style: disc; -} - -hr { - width: 100%; - height: 1px; - background-color: #CCCCCC; - border-width: 0px; - padding: 0px; -} - -.variablelist { - padding-top: 10px; - padding-bottom: 10px; - margin: 0; -} - -.term { - font-weight: bold; -} - -.mediaobject { - padding-top: 30px; - padding-bottom: 30px; -} - -.legalnotice { - font-family: Verdana, Arial, helvetica, sans-serif; - font-size: 12px; - font-style: italic; -} - -.sidebar { - float: right; - margin: 10px 0px 10px 30px; - padding: 10px 20px 20px 20px; - width: 33%; - border: 1px solid black; - background-color: #F4F4F4; - font-size: 14px; -} - -.property { - font-family: "Courier New", Courier, monospace; -} - -a code { - font-family: Verdana, Arial, monospace; - font-size: 12px; -} - -td code { - font-size: 110%; -} - -div.note * td, - div.tip * td, - div.warning * td, - div.calloutlist * td { - text-align: justify; - font-size: 100%; -} - -.programlisting .interfacename, - .programlisting .literal, - .programlisting .classname { - font-size: 95%; -} - -.title .interfacename, - .title .literal, - .title .classname { - font-size: 130%; -} - -/* everything in a is displayed in a coloured, comment-like font */ -.programlisting * .lineannotation, - .programlisting * .lineannotation * { - color: green; -} +body { + text-align: justify; + margin-right: 2em; + margin-left: 2em; +} + +a, + a[accesskey^ + += +"h" +] +, +a[accesskey^ + += +"n" +] +, +a[accesskey^ + += +"u" +] +, +a[accesskey^ + += +"p" +] +{ +font-family: Verdana, Arial, helvetica, sans-serif + +; +font-size: + +12 +px + +; +color: #003399 + +; +} + +a:active { + color: #003399; +} + +a:visited { + color: #888888; +} + +p { + font-family: Verdana, Arial, sans-serif; +} + +dt { + font-family: Verdana, Arial, sans-serif; + font-size: 12px; +} + +p, dl, dt, dd, blockquote { + color: #000000; + margin-bottom: 3px; + margin-top: 3px; + padding-top: 0px; +} + +ol, ul, p { + margin-top: 6px; + margin-bottom: 6px; +} + +p, blockquote { + font-size: 90%; +} + +p.releaseinfo { + font-size: 100%; + font-weight: bold; + font-family: Verdana, Arial, helvetica, sans-serif; + padding-top: 10px; +} + +p.pubdate { + font-size: 120%; + font-weight: bold; + font-family: Verdana, Arial, helvetica, sans-serif; +} + +td { + font-size: 80%; +} + +td, th, span { + color: #000000; +} + +td[width^ + += +"40%" +] +{ +font-family: Verdana, Arial, helvetica, sans-serif + +; +font-size: + +12 +px + +; +color: #003399 + +; +} + +table[summary^ + += +"Navigation header" +] +tbody tr th[colspan^ + += +"3" +] +{ +font-family: Verdana, Arial, helvetica, sans-serif + +; +} + +blockquote { + margin-right: 0px; +} + +h1, h2, h3, h4, h6, H6 { + color: #000000; + font-weight: 500; + margin-top: 0px; + padding-top: 14px; + font-family: Verdana, Arial, helvetica, sans-serif; + margin-bottom: 0px; +} + +h2.title { + font-weight: 800; + margin-bottom: 8px; +} + +h2.subtitle { + font-weight: 800; + margin-bottom: 20px; +} + +.firstname, .surname { + font-size: 12px; + font-family: Verdana, Arial, helvetica, sans-serif; +} + +table { + border-collapse: collapse; + border-spacing: 0; + border: 1px black; + empty-cells: hide; + margin: 10px 0px 30px 50px; + width: 90%; +} + +div.table { + margin: 30px 0px 30px 0px; + border: 1px dashed gray; + padding: 10px; +} + +div .table-contents table { + border: 1px solid black; +} + +div.table > p.title { + padding-left: 10px; +} + +table[summary^ + += +"Navigation footer" +] +{ +border-collapse: collapse + +; +border-spacing: + +0 +; +border: + +1 +px black + +; +empty-cells: hide + +; +margin: + +0 +px + +; +width: + +100 +% +; +} + +table[summary^ + += +"Note" +] +, +table[summary^ + += +"Warning" +] +, +table[summary^ + += +"Tip" +] +{ +border-collapse: collapse + +; +border-spacing: + +0 +; +border: + +1 +px black + +; +empty-cells: hide + +; +margin: + +10 +px + +0 +px + +10 +px + +- +20 +px + +; +width: + +100 +% +; +} + +td { + padding: 4pt; + font-family: Verdana, Arial, helvetica, sans-serif; +} + +div.warning TD { + text-align: justify; +} + +h1 { + font-size: 150%; +} + +h2 { + font-size: 110%; +} + +h3 { + font-size: 100%; + font-weight: bold; +} + +h4 { + font-size: 90%; + font-weight: bold; +} + +h5 { + font-size: 90%; + font-style: italic; +} + +h6 { + font-size: 100%; + font-style: italic; +} + +tt { + font-size: 110%; + font-family: "Courier New", Courier, monospace; + color: #000000; +} + +.navheader, .navfooter { + border: none; +} + +div.navfooter table { + border: dashed gray; + border-width: 1px 1px 1px 1px; + background-color: #cde48d; +} + +pre { + font-size: 110%; + padding: 5px; + border-style: solid; + border-width: 1px; + border-color: #CCCCCC; + background-color: #f3f5e9; +} + +ul, ol, li { + list-style: disc; +} + +hr { + width: 100%; + height: 1px; + background-color: #CCCCCC; + border-width: 0px; + padding: 0px; +} + +.variablelist { + padding-top: 10px; + padding-bottom: 10px; + margin: 0; +} + +.term { + font-weight: bold; +} + +.mediaobject { + padding-top: 30px; + padding-bottom: 30px; +} + +.legalnotice { + font-family: Verdana, Arial, helvetica, sans-serif; + font-size: 12px; + font-style: italic; +} + +.sidebar { + float: right; + margin: 10px 0px 10px 30px; + padding: 10px 20px 20px 20px; + width: 33%; + border: 1px solid black; + background-color: #F4F4F4; + font-size: 14px; +} + +.property { + font-family: "Courier New", Courier, monospace; +} + +a code { + font-family: Verdana, Arial, monospace; + font-size: 12px; +} + +td code { + font-size: 110%; +} + +div.note * td, + div.tip * td, + div.warning * td, + div.calloutlist * td { + text-align: justify; + font-size: 100%; +} + +.programlisting .interfacename, + .programlisting .literal, + .programlisting .classname { + font-size: 95%; +} + +.title .interfacename, + .title .literal, + .title .classname { + font-size: 130%; +} + +/* everything in a is displayed in a coloured, comment-like font */ +.programlisting * .lineannotation, + .programlisting * .lineannotation * { + color: green; +} diff --git a/docs/src/models/domain-classdiagram.dnx b/docs/src/models/domain-classdiagram.dnx index 63e015cef7..8a3a3af866 100644 --- a/docs/src/models/domain-classdiagram.dnx +++ b/docs/src/models/domain-classdiagram.dnx @@ -1,847 +1,847 @@ - - -?> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + +?> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/src/models/flat-file-input-source-design.dnx b/docs/src/models/flat-file-input-source-design.dnx index 50290d4451..a9e1567566 100644 --- a/docs/src/models/flat-file-input-source-design.dnx +++ b/docs/src/models/flat-file-input-source-design.dnx @@ -1,551 +1,551 @@ - - -?> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + +?> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/src/models/io-design.dnx b/docs/src/models/io-design.dnx index 24b2afafa4..5d77f21030 100644 --- a/docs/src/models/io-design.dnx +++ b/docs/src/models/io-design.dnx @@ -1,1392 +1,1392 @@ - - -?> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + +?> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/src/models/item-reader-design.dnx b/docs/src/models/item-reader-design.dnx index c44de98d49..70fbf68b7f 100644 --- a/docs/src/models/item-reader-design.dnx +++ b/docs/src/models/item-reader-design.dnx @@ -1,983 +1,983 @@ - - -?> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + +?> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/src/models/item-stream-adapter.dnx b/docs/src/models/item-stream-adapter.dnx index d6f46d7d79..0294802429 100644 --- a/docs/src/models/item-stream-adapter.dnx +++ b/docs/src/models/item-stream-adapter.dnx @@ -1,353 +1,353 @@ - - -?> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + +?> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/src/models/repository-classdiagram.dnx b/docs/src/models/repository-classdiagram.dnx index 93d8056f61..4677d6176f 100644 --- a/docs/src/models/repository-classdiagram.dnx +++ b/docs/src/models/repository-classdiagram.dnx @@ -1,482 +1,482 @@ - - -?> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + +?> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/src/site/docbook/reference/batch-job-testing.xml b/docs/src/site/docbook/reference/batch-job-testing.xml index b5d6633088..ec54f8f815 100644 --- a/docs/src/site/docbook/reference/batch-job-testing.xml +++ b/docs/src/site/docbook/reference/batch-job-testing.xml @@ -1,17 +1,17 @@ - - - Batch Unit and Integration Tests - -
- Unit Testing - Document Batch Job Unit Testing features. This includes the use of Mock Objects, - embedded database (HSQLDB), etc. -
- -
- Integration Testing - Document how to test against the targeted database, applications, etc. -
- -
+ + + Batch Unit and Integration Tests + +
+ Unit Testing + Document Batch Job Unit Testing features. This includes the use of Mock Objects, + embedded database (HSQLDB), etc. +
+ +
+ Integration Testing + Document how to test against the targeted database, applications, etc. +
+ +
diff --git a/docs/src/site/docbook/reference/batch-launch.xml b/docs/src/site/docbook/reference/batch-launch.xml index 6895fa5db2..6795bcbc8f 100644 --- a/docs/src/site/docbook/reference/batch-launch.xml +++ b/docs/src/site/docbook/reference/batch-launch.xml @@ -1,17 +1,17 @@ - - - Run Tier - Launching Batch Jobs -
- Mapping Batch Error Codes to Launch Client Error Codes - Mapping Batch Error Codes to Launch Client Error Codes -
-
- Launch Batch from Command Line - Document Command Line Launching -
-
- Launch Batch On Demand - Document Launching Batch Jobs on Demand -
-
+ + + Run Tier - Launching Batch Jobs +
+ Mapping Batch Error Codes to Launch Client Error Codes + Mapping Batch Error Codes to Launch Client Error Codes +
+
+ Launch Batch from Command Line + Document Command Line Launching +
+
+ Launch Batch On Demand + Document Launching Batch Jobs on Demand +
+
diff --git a/docs/src/site/docbook/reference/batch-performance-testing.xml b/docs/src/site/docbook/reference/batch-performance-testing.xml index 8049673dec..8e2b30fdc5 100644 --- a/docs/src/site/docbook/reference/batch-performance-testing.xml +++ b/docs/src/site/docbook/reference/batch-performance-testing.xml @@ -1,52 +1,52 @@ - - - Batch Performance Testing -
- Performance Testing Overview - A batch performance test team needs to have the following at their disposal: - - - - - Define performance Targets - - - - Establishing the requirements for a performance testing environment - - - - Performance Data - generating adequate volumes of realistic data for performance testing - - - Performance Tools - - - - Performance Team Roles - Tool SME's, performance DBA. - - - -
- -
- Defining Performance Targets - -
- -
- Establishing Performance requirements and installing the environment. - Establishing the requirements for the performance environment. -
- -
- Performance Data - Generating adequate volumes of realistic data for performance testing. -
-
- Performance Tools - -
-
- Performance Team Roles - Tool SME's, performance dba's, environment experts (OS, JVM, etc.) -
-
+ + + Batch Performance Testing +
+ Performance Testing Overview + A batch performance test team needs to have the following at their disposal: + + + + + Define performance Targets - + + + Establishing the requirements for a performance testing environment - + + + Performance Data - generating adequate volumes of realistic data for performance testing + + + Performance Tools - + + + Performance Team Roles - Tool SME's, performance DBA. + + + +
+ +
+ Defining Performance Targets + +
+ +
+ Establishing Performance requirements and installing the environment. + Establishing the requirements for the performance environment. +
+ +
+ Performance Data + Generating adequate volumes of realistic data for performance testing. +
+
+ Performance Tools + +
+
+ Performance Team Roles + Tool SME's, performance dba's, environment experts (OS, JVM, etc.) +
+
diff --git a/docs/src/site/docbook/reference/namespace.xml b/docs/src/site/docbook/reference/namespace.xml index 176bc0f1f4..02b35d94b2 100644 --- a/docs/src/site/docbook/reference/namespace.xml +++ b/docs/src/site/docbook/reference/namespace.xml @@ -1,11 +1,11 @@ - - - Namespace Support - -
- Namespace Support - Document Namespace support here. -
- -
+ + + Namespace Support + +
+ Namespace Support + Document Namespace support here. +
+ +
diff --git a/docs/src/site/docbook/reference/partitioned-containers.xml b/docs/src/site/docbook/reference/partitioned-containers.xml index 7f9599cc00..2f245b529e 100644 --- a/docs/src/site/docbook/reference/partitioned-containers.xml +++ b/docs/src/site/docbook/reference/partitioned-containers.xml @@ -1,10 +1,10 @@ - - - Batch IO Support -
- Partitioned Containers - Much stuff goes here. -
- -
+ + + Batch IO Support +
+ Partitioned Containers + Much stuff goes here. +
+ +
diff --git a/docs/src/site/docbook/reference/spring-tasklet.xml b/docs/src/site/docbook/reference/spring-tasklet.xml index 19e0e896f0..a9575e95d4 100644 --- a/docs/src/site/docbook/reference/spring-tasklet.xml +++ b/docs/src/site/docbook/reference/spring-tasklet.xml @@ -1,30 +1,30 @@ - - - Tasklet and the Repeat Template - -
- What is a Tasklet? - Document what a Tasklet is. Include the diagram of showing its place in the batch domain world. -
- -
- Item Providers - Document Item Providers. Discuss some default item providers -
- -
- Item Processor - Talk about default Item Processor -
- -
- Item Provider Process Tasklet - Don't worry about how all the pieces work but focus on Talk about default Item Processor -
- -
- The role of the Repeat Template - The two repeat templates used by ItemProcessor. -
-
+ + + Tasklet and the Repeat Template + +
+ What is a Tasklet? + Document what a Tasklet is. Include the diagram of showing its place in the batch domain world. +
+ +
+ Item Providers + Document Item Providers. Discuss some default item providers +
+ +
+ Item Processor + Talk about default Item Processor +
+ +
+ Item Provider Process Tasklet + Don't worry about how all the pieces work but focus on Talk about default Item Processor +
+ +
+ The role of the Repeat Template + The two repeat templates used by ItemProcessor. +
+
diff --git a/spring-batch-core/.project b/spring-batch-core/.project index 0dfc18b4e0..aee1455837 100644 --- a/spring-batch-core/.project +++ b/spring-batch-core/.project @@ -1,30 +1,30 @@ - - - spring-batch-core - Core domain for batch processing, expressing a domain of Jobs, Steps, Chunks, etc. - - spring-batch-infrastructure - - - - org.eclipse.jdt.core.javabuilder - - - - - org.springframework.ide.eclipse.core.springbuilder - - - - - org.devzuz.q.maven.jdt.core.mavenIncrementalBuilder - - - - - - org.springframework.ide.eclipse.core.springnature - org.eclipse.jdt.core.javanature - org.devzuz.q.maven.jdt.core.mavenNature - - + + + spring-batch-core + Core domain for batch processing, expressing a domain of Jobs, Steps, Chunks, etc. + + spring-batch-infrastructure + + + + org.eclipse.jdt.core.javabuilder + + + + + org.springframework.ide.eclipse.core.springbuilder + + + + + org.devzuz.q.maven.jdt.core.mavenIncrementalBuilder + + + + + + org.springframework.ide.eclipse.core.springnature + org.eclipse.jdt.core.javanature + org.devzuz.q.maven.jdt.core.mavenNature + + diff --git a/spring-batch-core/.settings/org.eclipse.jdt.core.prefs b/spring-batch-core/.settings/org.eclipse.jdt.core.prefs index 4a9695004a..b685925ece 100644 --- a/spring-batch-core/.settings/org.eclipse.jdt.core.prefs +++ b/spring-batch-core/.settings/org.eclipse.jdt.core.prefs @@ -1,5 +1,5 @@ -#Mon Dec 10 14:44:35 EST 2007 -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.4 -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.source=1.4 -org.eclipse.jdt.core.compiler.compliance=1.4 +#Mon Dec 10 14:44:35 EST 2007 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.4 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.source=1.4 +org.eclipse.jdt.core.compiler.compliance=1.4 diff --git a/spring-batch-core/.settings/org.eclipse.mylyn.tasks.ui.prefs b/spring-batch-core/.settings/org.eclipse.mylyn.tasks.ui.prefs index 65978018dc..a646b51257 100644 --- a/spring-batch-core/.settings/org.eclipse.mylyn.tasks.ui.prefs +++ b/spring-batch-core/.settings/org.eclipse.mylyn.tasks.ui.prefs @@ -1,4 +1,4 @@ -#Thu Aug 23 07:01:16 BST 2007 -eclipse.preferences.version=1 -project.repository.kind=jira -project.repository.url=http\://opensource.atlassian.com/projects/spring +#Thu Aug 23 07:01:16 BST 2007 +eclipse.preferences.version=1 +project.repository.kind=jira +project.repository.url=http\://opensource.atlassian.com/projects/spring diff --git a/spring-batch-core/.springBeans b/spring-batch-core/.springBeans index 0fd874a822..2ec86ee182 100644 --- a/spring-batch-core/.springBeans +++ b/spring-batch-core/.springBeans @@ -1,31 +1,31 @@ - - - - xml - - - - - - - true - false - - - - - - true - false - - - - - - true - false - - - - - + + + + xml + + + + + + + true + false + + + + + + true + false + + + + + + true + false + + + + + diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/JobLocator.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/JobLocator.java index 263c828609..86e6386147 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/JobLocator.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/JobLocator.java @@ -1,41 +1,41 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.configuration; - -import org.springframework.batch.core.domain.Job; -import org.springframework.batch.core.repository.NoSuchJobException; - -/** - * A runtime service locator interface for retrieving job configurations by - * name. - * - * @author Dave Syer - * - */ -public interface JobLocator { - - /** - * Locates a {@link Job} at runtime. - * - * @param name the name of the {@link Job} which should be - * unique - * @return a {@link Job} identified by the given name - * - * @throws NoSuchJobException if the required configuration can - * not be found. - */ - Job getJob(String name) throws NoSuchJobException; -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.configuration; + +import org.springframework.batch.core.domain.Job; +import org.springframework.batch.core.repository.NoSuchJobException; + +/** + * A runtime service locator interface for retrieving job configurations by + * name. + * + * @author Dave Syer + * + */ +public interface JobLocator { + + /** + * Locates a {@link Job} at runtime. + * + * @param name the name of the {@link Job} which should be + * unique + * @return a {@link Job} identified by the given name + * + * @throws NoSuchJobException if the required configuration can + * not be found. + */ + Job getJob(String name) throws NoSuchJobException; +} diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/JobRegistry.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/JobRegistry.java index e8bd41c1f2..1b2c454d54 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/JobRegistry.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/JobRegistry.java @@ -1,47 +1,47 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.configuration; - -import org.springframework.batch.core.domain.Job; -import org.springframework.batch.core.repository.DuplicateJobException; - -/** - * A runtime service registry interface for registering job configurations by - * name. - * - * @author Dave Syer - * - */ -public interface JobRegistry extends JobLocator { - - /** - * Registers a {@link Job} at runtime. - * - * @param jobFactory the {@link Job} to be registered - * - * @throws DuplicateJobException if a factory with the same job name has - * already been registered. - */ - void register(JobFactory jobFactory) throws DuplicateJobException; - - /** - * Unregisters a previously registered {@link Job}. If it was not - * previously registered there is no error. - * - * @param jobName the {@link Job} to unregister. - */ - void unregister(String jobName); -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.configuration; + +import org.springframework.batch.core.domain.Job; +import org.springframework.batch.core.repository.DuplicateJobException; + +/** + * A runtime service registry interface for registering job configurations by + * name. + * + * @author Dave Syer + * + */ +public interface JobRegistry extends JobLocator { + + /** + * Registers a {@link Job} at runtime. + * + * @param jobFactory the {@link Job} to be registered + * + * @throws DuplicateJobException if a factory with the same job name has + * already been registered. + */ + void register(JobFactory jobFactory) throws DuplicateJobException; + + /** + * Unregisters a previously registered {@link Job}. If it was not + * previously registered there is no error. + * + * @param jobName the {@link Job} to unregister. + */ + void unregister(String jobName); +} diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/ListableJobRegistry.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/ListableJobRegistry.java index 6b28911c03..b2251a7458 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/ListableJobRegistry.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/ListableJobRegistry.java @@ -1,35 +1,35 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.configuration; - -import java.util.Collection; - -/** - * A listable extension of {@link JobRegistry}. - * - * @author Dave Syer - * - */ -public interface ListableJobRegistry extends JobRegistry { - - /** - * Provides the currently registered job names. The return value is - * unmodifiable and disconnected from the underlying registry storage. - * - * @return a collection of String. Empty if none are registered. - */ - Collection getJobNames(); -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.configuration; + +import java.util.Collection; + +/** + * A listable extension of {@link JobRegistry}. + * + * @author Dave Syer + * + */ +public interface ListableJobRegistry extends JobRegistry { + + /** + * Provides the currently registered job names. The return value is + * unmodifiable and disconnected from the underlying registry storage. + * + * @return a collection of String. Empty if none are registered. + */ + Collection getJobNames(); +} diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/domain/JobExecutionException.java b/spring-batch-core/src/main/java/org/springframework/batch/core/domain/JobExecutionException.java index edacb45704..11205e9807 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/domain/JobExecutionException.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/domain/JobExecutionException.java @@ -1,31 +1,31 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.domain; - -/** - * @author Dave Syer - * - */ -public class JobExecutionException extends Exception { - - public JobExecutionException(String msg) { - super(msg); - } - - public JobExecutionException(String msg, Throwable cause) { - super(msg, cause); - } -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.domain; + +/** + * @author Dave Syer + * + */ +public class JobExecutionException extends Exception { + + public JobExecutionException(String msg) { + super(msg); + } + + public JobExecutionException(String msg, Throwable cause) { + super(msg, cause); + } +} diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/domain/Step.java b/spring-batch-core/src/main/java/org/springframework/batch/core/domain/Step.java index 3c4a370990..20cf92b25b 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/domain/Step.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/domain/Step.java @@ -1,65 +1,65 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.domain; - -import org.springframework.batch.io.exception.InfrastructureException; - -/** - * Batch domain interface representing the configuration of a step. As with the - * (@link Job), a {@link Step} is meant to explicitly represent a the - * configuration of a step by a developer, but also the ability to execute the - * step. - * - * @author Dave Syer - * - */ -public interface Step { - - /** - * @return the name of this step. - */ - String getName(); - - /** - * @return true if a step that is already marked as complete can be started - * again. - */ - boolean isAllowStartIfComplete(); - - /** - * @return the number of times a job can be started with the same - * identifier. - */ - int getStartLimit(); - - /** - * Process the step and assign progress and status meta information to the - * {@link StepExecution} provided. The {@link Step} is responsible for - * setting the meta information and also saving it if required by the - * implementation.
- * - * It is not safe to re-use an instance of {@link Step} to process multiple - * concurrent executions. - * - * @param stepExecution an entity representing the step to be executed - * - * @throws JobInterruptedException if the step is interrupted externally - * @throws InfrastructureException if there is a problem that needs to be - * signalled to the caller - */ - void execute(StepExecution stepExecution) throws JobInterruptedException, InfrastructureException; - +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.domain; + +import org.springframework.batch.io.exception.InfrastructureException; + +/** + * Batch domain interface representing the configuration of a step. As with the + * (@link Job), a {@link Step} is meant to explicitly represent a the + * configuration of a step by a developer, but also the ability to execute the + * step. + * + * @author Dave Syer + * + */ +public interface Step { + + /** + * @return the name of this step. + */ + String getName(); + + /** + * @return true if a step that is already marked as complete can be started + * again. + */ + boolean isAllowStartIfComplete(); + + /** + * @return the number of times a job can be started with the same + * identifier. + */ + int getStartLimit(); + + /** + * Process the step and assign progress and status meta information to the + * {@link StepExecution} provided. The {@link Step} is responsible for + * setting the meta information and also saving it if required by the + * implementation.
+ * + * It is not safe to re-use an instance of {@link Step} to process multiple + * concurrent executions. + * + * @param stepExecution an entity representing the step to be executed + * + * @throws JobInterruptedException if the step is interrupted externally + * @throws InfrastructureException if there is a problem that needs to be + * signalled to the caller + */ + void execute(StepExecution stepExecution) throws JobInterruptedException, InfrastructureException; + } \ No newline at end of file diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/DuplicateJobException.java b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/DuplicateJobException.java index 75db95b330..75680e360b 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/DuplicateJobException.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/DuplicateJobException.java @@ -1,44 +1,44 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.repository; - -import org.springframework.batch.core.domain.Job; - -/** - * Checked exception that indicates a name clash when registering - * {@link Job} instances. - * - * @author Dave Syer - * - */ -public class DuplicateJobException extends JobException { - - /** - * Create an exception with the given message. - */ - public DuplicateJobException(String msg) { - super(msg); - } - - /** - * @param msg The message to send to caller - * @param e the cause of the exception - */ - public DuplicateJobException(String msg, Throwable e) { - super(msg, e); - } - -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.repository; + +import org.springframework.batch.core.domain.Job; + +/** + * Checked exception that indicates a name clash when registering + * {@link Job} instances. + * + * @author Dave Syer + * + */ +public class DuplicateJobException extends JobException { + + /** + * Create an exception with the given message. + */ + public DuplicateJobException(String msg) { + super(msg); + } + + /** + * @param msg The message to send to caller + * @param e the cause of the exception + */ + public DuplicateJobException(String msg, Throwable e) { + super(msg, e); + } + +} diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/JobException.java b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/JobException.java index 7cf809797c..bfbbc62342 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/JobException.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/JobException.java @@ -1,44 +1,44 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.repository; - -import org.springframework.batch.core.domain.Job; - -/** - * Base class for checked exceptions related to {@link Job} - * creation, registration or use. - * - * @author Dave Syer - * - */ -public class JobException extends Exception { - - /** - * Create an exception with the given message. - */ - public JobException(String msg) { - super(msg); - } - - /** - * @param msg The message to send to caller - * @param e the cause of the exception - */ - public JobException(String msg, Throwable e) { - super(msg, e); - } - -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.repository; + +import org.springframework.batch.core.domain.Job; + +/** + * Base class for checked exceptions related to {@link Job} + * creation, registration or use. + * + * @author Dave Syer + * + */ +public class JobException extends Exception { + + /** + * Create an exception with the given message. + */ + public JobException(String msg) { + super(msg); + } + + /** + * @param msg The message to send to caller + * @param e the cause of the exception + */ + public JobException(String msg, Throwable e) { + super(msg, e); + } + +} diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/JobExecutionAlreadyRunningException.java b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/JobExecutionAlreadyRunningException.java index 399dc40153..acd8ac93c2 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/JobExecutionAlreadyRunningException.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/JobExecutionAlreadyRunningException.java @@ -1,41 +1,41 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.repository; - -import org.springframework.batch.core.domain.JobExecutionException; - -/** - * @author Dave Syer - * - */ -public class JobExecutionAlreadyRunningException extends JobExecutionException { - - /** - * @param msg - */ - public JobExecutionAlreadyRunningException(String msg) { - super(msg); - } - - /** - * @param msg - * @param cause - */ - public JobExecutionAlreadyRunningException(String msg, Throwable cause) { - super(msg, cause); - } - -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.repository; + +import org.springframework.batch.core.domain.JobExecutionException; + +/** + * @author Dave Syer + * + */ +public class JobExecutionAlreadyRunningException extends JobExecutionException { + + /** + * @param msg + */ + public JobExecutionAlreadyRunningException(String msg) { + super(msg); + } + + /** + * @param msg + * @param cause + */ + public JobExecutionAlreadyRunningException(String msg, Throwable cause) { + super(msg, cause); + } + +} diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/JobRestartException.java b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/JobRestartException.java index 60d03e2eb0..8301df98f4 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/JobRestartException.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/JobRestartException.java @@ -1,41 +1,41 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.repository; - -/** - * An exception indicating an illegal attempt to restart a job. - * - * @author Dave Syer - * - */ -public class JobRestartException extends JobException { - - /** - * @param string the message - */ - public JobRestartException(String string) { - super(string); - } - - /** - * @param msg the cause - * @param t the message - */ - public JobRestartException(String msg, Throwable t) { - super(msg, t); - } - -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.repository; + +/** + * An exception indicating an illegal attempt to restart a job. + * + * @author Dave Syer + * + */ +public class JobRestartException extends JobException { + + /** + * @param string the message + */ + public JobRestartException(String string) { + super(string); + } + + /** + * @param msg the cause + * @param t the message + */ + public JobRestartException(String msg, Throwable t) { + super(msg, t); + } + +} diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/NoSuchJobException.java b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/NoSuchJobException.java index a3c135c4a2..7c1e1a2733 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/NoSuchJobException.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/NoSuchJobException.java @@ -1,46 +1,46 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.repository; - -import org.springframework.batch.core.domain.Job; - - -/** - * Checked exception to indicate that a required {@link Job} is not - * available. - * - * @author Dave Syer - * - */ -public class NoSuchJobException extends JobException { - - private static final long serialVersionUID = -8044082897778706564L; - - /** - * Create an exception with the given message. - */ - public NoSuchJobException(String msg) { - super(msg); - } - - /** - * @param msg The message to send to caller - * @param e the cause of the exception - */ - public NoSuchJobException(String msg, Throwable e) { - super(msg, e); - } -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.repository; + +import org.springframework.batch.core.domain.Job; + + +/** + * Checked exception to indicate that a required {@link Job} is not + * available. + * + * @author Dave Syer + * + */ +public class NoSuchJobException extends JobException { + + private static final long serialVersionUID = -8044082897778706564L; + + /** + * Create an exception with the given message. + */ + public NoSuchJobException(String msg) { + super(msg); + } + + /** + * @param msg The message to send to caller + * @param e the cause of the exception + */ + public NoSuchJobException(String msg, Throwable e) { + super(msg, e); + } +} diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/runtime/ExitStatusExceptionClassifier.java b/spring-batch-core/src/main/java/org/springframework/batch/core/runtime/ExitStatusExceptionClassifier.java index 15a1517a96..2b141b34ef 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/runtime/ExitStatusExceptionClassifier.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/runtime/ExitStatusExceptionClassifier.java @@ -1,44 +1,44 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.runtime; - -import org.springframework.batch.common.ExceptionClassifier; -import org.springframework.batch.repeat.ExitStatus; - -/** - * Extension of the {@link ExceptionClassifier} that explicitly deals with - * returns an {@link ExitStatus}. This is useful for mapping from an exception - * type to an exit status with a customised code or detailed message. - * - * @author Lucas Ward - * - */ -public interface ExitStatusExceptionClassifier extends ExceptionClassifier { - - public static final String FATAL_EXCEPTION = "FATAL_EXCEPTION"; - - public static final String JOB_INTERRUPTED = "JOB_INTERRUPTED"; - - /** - * Typesafe version of classify that explicitly returns an - * {@link ExitStatus} object. - * - * @param throwable - * @return ExitStatus representing the ExitCode and Message for the given - * exception. - */ - public ExitStatus classifyForExitCode(Throwable throwable); -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.runtime; + +import org.springframework.batch.common.ExceptionClassifier; +import org.springframework.batch.repeat.ExitStatus; + +/** + * Extension of the {@link ExceptionClassifier} that explicitly deals with + * returns an {@link ExitStatus}. This is useful for mapping from an exception + * type to an exit status with a customised code or detailed message. + * + * @author Lucas Ward + * + */ +public interface ExitStatusExceptionClassifier extends ExceptionClassifier { + + public static final String FATAL_EXCEPTION = "FATAL_EXCEPTION"; + + public static final String JOB_INTERRUPTED = "JOB_INTERRUPTED"; + + /** + * Typesafe version of classify that explicitly returns an + * {@link ExitStatus} object. + * + * @param throwable + * @return ExitStatus representing the ExitCode and Message for the given + * exception. + */ + public ExitStatus classifyForExitCode(Throwable throwable); +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/domain/BatchStatusTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/domain/BatchStatusTests.java index 0041aa97d3..c50e077829 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/domain/BatchStatusTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/domain/BatchStatusTests.java @@ -1,83 +1,83 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.domain; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; - -import junit.framework.TestCase; - -/** - * @author Dave Syer - * - */ -public class BatchStatusTests extends TestCase { - - /** - * Test method for - * {@link org.springframework.batch.core.domain.BatchStatus#toString()}. - */ - public void testToString() { - assertEquals("FAILED", BatchStatus.FAILED.toString()); - } - - /** - * Test method for - * {@link org.springframework.batch.core.domain.BatchStatus#getStatus(java.lang.String)}. - */ - public void testGetStatus() { - assertEquals(BatchStatus.FAILED, BatchStatus.getStatus(BatchStatus.FAILED.toString())); - } - - /** - * Test method for - * {@link org.springframework.batch.core.domain.BatchStatus#getStatus(java.lang.String)}. - */ - public void testGetStatusWrongCode() { - try { - BatchStatus.getStatus("foo"); - fail(); - } - catch (IllegalArgumentException ex) { - // expected - } - } - - /** - * Test method for - * {@link org.springframework.batch.core.domain.BatchStatus#getStatus(java.lang.String)}. - */ - public void testGetStatusNullCode() { - assertNull(BatchStatus.getStatus(null)); - } - - public void testSerialization() throws Exception { - - ByteArrayOutputStream bout = new ByteArrayOutputStream(); - ObjectOutputStream out = new ObjectOutputStream(bout); - - out.writeObject(BatchStatus.COMPLETED); - out.flush(); - - ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray()); - ObjectInputStream in = new ObjectInputStream(bin); - - BatchStatus status = (BatchStatus) in.readObject(); - assertEquals(BatchStatus.COMPLETED, status); - } -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.domain; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; + +import junit.framework.TestCase; + +/** + * @author Dave Syer + * + */ +public class BatchStatusTests extends TestCase { + + /** + * Test method for + * {@link org.springframework.batch.core.domain.BatchStatus#toString()}. + */ + public void testToString() { + assertEquals("FAILED", BatchStatus.FAILED.toString()); + } + + /** + * Test method for + * {@link org.springframework.batch.core.domain.BatchStatus#getStatus(java.lang.String)}. + */ + public void testGetStatus() { + assertEquals(BatchStatus.FAILED, BatchStatus.getStatus(BatchStatus.FAILED.toString())); + } + + /** + * Test method for + * {@link org.springframework.batch.core.domain.BatchStatus#getStatus(java.lang.String)}. + */ + public void testGetStatusWrongCode() { + try { + BatchStatus.getStatus("foo"); + fail(); + } + catch (IllegalArgumentException ex) { + // expected + } + } + + /** + * Test method for + * {@link org.springframework.batch.core.domain.BatchStatus#getStatus(java.lang.String)}. + */ + public void testGetStatusNullCode() { + assertNull(BatchStatus.getStatus(null)); + } + + public void testSerialization() throws Exception { + + ByteArrayOutputStream bout = new ByteArrayOutputStream(); + ObjectOutputStream out = new ObjectOutputStream(bout); + + out.writeObject(BatchStatus.COMPLETED); + out.flush(); + + ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray()); + ObjectInputStream in = new ObjectInputStream(bin); + + BatchStatus status = (BatchStatus) in.readObject(); + assertEquals(BatchStatus.COMPLETED, status); + } +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/domain/EntityTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/domain/EntityTests.java index 2ba5dbd2dc..2570360f8e 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/domain/EntityTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/domain/EntityTests.java @@ -1,128 +1,128 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.domain; - -import junit.framework.TestCase; - -/** - * @author Dave Syer - * - */ -public class EntityTests extends TestCase { - - Entity entity = new Entity(new Long(11)); - - /** - * Test method for {@link org.springframework.batch.core.domain.Entity#hashCode()}. - */ - public void testHashCode() { - assertEquals(entity.hashCode(), new Entity(entity.getId()).hashCode()); - } - - /** - * Test method for {@link org.springframework.batch.core.domain.Entity#hashCode()}. - */ - public void testHashCodeNullId() { - int withoutNull = entity.hashCode(); - entity.setId(null); - int withNull = entity.hashCode(); - assertTrue(withoutNull!=withNull); - } - - /** - * Test method for {@link org.springframework.batch.core.domain.Entity#getVersion()}. - */ - public void testGetVersion() { - assertEquals(null, entity.getVersion()); - } - - /** - * Test method for {@link org.springframework.batch.core.domain.Entity#getVersion()}. - */ - public void testIncrementVersion() { - entity.incrementVersion(); - assertEquals(new Integer(0), entity.getVersion()); - } - - /** - * Test method for {@link org.springframework.batch.core.domain.Entity#getVersion()}. - */ - public void testIncrementVersionTwice() { - entity.incrementVersion(); - entity.incrementVersion(); - assertEquals(new Integer(1), entity.getVersion()); - } - - /** - * @throws Exception - */ - public void testToString() throws Exception { - Entity job = new Entity(); - assertTrue(job.toString().indexOf("id=null") >= 0); - } - - /** - * Test method for {@link org.springframework.batch.core.domain.Entity#equals(java.lang.Object)}. - */ - public void testEqualsSelf() { - assertEquals(entity, entity); - } - - /** - * Test method for {@link org.springframework.batch.core.domain.Entity#equals(java.lang.Object)}. - */ - public void testEqualsSelfWithNullId() { - entity = new Entity(null); - assertEquals(entity, entity); - } - - /** - * Test method for {@link org.springframework.batch.core.domain.Entity#equals(java.lang.Object)}. - */ - public void testEqualsEntityWithNullId() { - entity = new Entity(null); - assertNotSame(entity, new Entity(null)); - } - - /** - * Test method for {@link org.springframework.batch.core.domain.Entity#equals(java.lang.Object)}. - */ - public void testEqualsEntity() { - assertEquals(entity, new Entity(entity.getId())); - } - - /** - * Test method for {@link org.springframework.batch.core.domain.Entity#equals(java.lang.Object)}. - */ - public void testEqualsEntityWrongId() { - assertFalse(entity.equals(new Entity())); - } - - /** - * Test method for {@link org.springframework.batch.core.domain.Entity#equals(java.lang.Object)}. - */ - public void testEqualsObject() { - assertFalse(entity.equals(new Object())); - } - - /** - * Test method for {@link org.springframework.batch.core.domain.Entity#equals(java.lang.Object)}. - */ - public void testEqualsNull() { - assertFalse(entity.equals(null)); - } - -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.domain; + +import junit.framework.TestCase; + +/** + * @author Dave Syer + * + */ +public class EntityTests extends TestCase { + + Entity entity = new Entity(new Long(11)); + + /** + * Test method for {@link org.springframework.batch.core.domain.Entity#hashCode()}. + */ + public void testHashCode() { + assertEquals(entity.hashCode(), new Entity(entity.getId()).hashCode()); + } + + /** + * Test method for {@link org.springframework.batch.core.domain.Entity#hashCode()}. + */ + public void testHashCodeNullId() { + int withoutNull = entity.hashCode(); + entity.setId(null); + int withNull = entity.hashCode(); + assertTrue(withoutNull!=withNull); + } + + /** + * Test method for {@link org.springframework.batch.core.domain.Entity#getVersion()}. + */ + public void testGetVersion() { + assertEquals(null, entity.getVersion()); + } + + /** + * Test method for {@link org.springframework.batch.core.domain.Entity#getVersion()}. + */ + public void testIncrementVersion() { + entity.incrementVersion(); + assertEquals(new Integer(0), entity.getVersion()); + } + + /** + * Test method for {@link org.springframework.batch.core.domain.Entity#getVersion()}. + */ + public void testIncrementVersionTwice() { + entity.incrementVersion(); + entity.incrementVersion(); + assertEquals(new Integer(1), entity.getVersion()); + } + + /** + * @throws Exception + */ + public void testToString() throws Exception { + Entity job = new Entity(); + assertTrue(job.toString().indexOf("id=null") >= 0); + } + + /** + * Test method for {@link org.springframework.batch.core.domain.Entity#equals(java.lang.Object)}. + */ + public void testEqualsSelf() { + assertEquals(entity, entity); + } + + /** + * Test method for {@link org.springframework.batch.core.domain.Entity#equals(java.lang.Object)}. + */ + public void testEqualsSelfWithNullId() { + entity = new Entity(null); + assertEquals(entity, entity); + } + + /** + * Test method for {@link org.springframework.batch.core.domain.Entity#equals(java.lang.Object)}. + */ + public void testEqualsEntityWithNullId() { + entity = new Entity(null); + assertNotSame(entity, new Entity(null)); + } + + /** + * Test method for {@link org.springframework.batch.core.domain.Entity#equals(java.lang.Object)}. + */ + public void testEqualsEntity() { + assertEquals(entity, new Entity(entity.getId())); + } + + /** + * Test method for {@link org.springframework.batch.core.domain.Entity#equals(java.lang.Object)}. + */ + public void testEqualsEntityWrongId() { + assertFalse(entity.equals(new Entity())); + } + + /** + * Test method for {@link org.springframework.batch.core.domain.Entity#equals(java.lang.Object)}. + */ + public void testEqualsObject() { + assertFalse(entity.equals(new Object())); + } + + /** + * Test method for {@link org.springframework.batch.core.domain.Entity#equals(java.lang.Object)}. + */ + public void testEqualsNull() { + assertFalse(entity.equals(null)); + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/domain/JobExecutionExceptionTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/domain/JobExecutionExceptionTests.java index 166b344fe0..f06c9af08c 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/domain/JobExecutionExceptionTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/domain/JobExecutionExceptionTests.java @@ -1,41 +1,41 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.domain; - -import org.springframework.batch.core.AbstractExceptionTests; -import org.springframework.batch.core.domain.JobExecutionException; - -/** - * @author Dave Syer - * - */ -public class JobExecutionExceptionTests extends AbstractExceptionTests { - - /* (non-Javadoc) - * @see org.springframework.batch.io.exception.AbstractExceptionTests#getException(java.lang.String) - */ - public Exception getException(String msg) throws Exception { - return new JobExecutionException(msg); - } - - /* (non-Javadoc) - * @see org.springframework.batch.io.exception.AbstractExceptionTests#getException(java.lang.String, java.lang.Throwable) - */ - public Exception getException(String msg, Throwable t) throws Exception { - return new JobExecutionException(msg, t); - } - -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.domain; + +import org.springframework.batch.core.AbstractExceptionTests; +import org.springframework.batch.core.domain.JobExecutionException; + +/** + * @author Dave Syer + * + */ +public class JobExecutionExceptionTests extends AbstractExceptionTests { + + /* (non-Javadoc) + * @see org.springframework.batch.io.exception.AbstractExceptionTests#getException(java.lang.String) + */ + public Exception getException(String msg) throws Exception { + return new JobExecutionException(msg); + } + + /* (non-Javadoc) + * @see org.springframework.batch.io.exception.AbstractExceptionTests#getException(java.lang.String, java.lang.Throwable) + */ + public Exception getException(String msg, Throwable t) throws Exception { + return new JobExecutionException(msg, t); + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/domain/JobExecutionTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/domain/JobExecutionTests.java index 16b8f87db1..5076db9f49 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/domain/JobExecutionTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/domain/JobExecutionTests.java @@ -1,155 +1,155 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.domain; - -import java.util.Date; - -import junit.framework.TestCase; - -import org.springframework.batch.repeat.ExitStatus; - -/** - * @author Dave Syer - * - */ -public class JobExecutionTests extends TestCase { - - private JobExecution execution = new JobExecution(new JobInstance(new Long(11), new JobParameters(), new JobSupport("foo")), new Long(12)); - - /** - * Test method for - * {@link org.springframework.batch.core.domain.JobExecution#JobExecution()}. - */ - public void testJobExecution() { - assertNull(new JobExecution().getId()); - } - - /** - * Test method for - * {@link org.springframework.batch.core.domain.JobExecution#getEndTime()}. - */ - public void testGetEndTime() { - assertNull(execution.getEndTime()); - execution.setEndTime(new Date(100L)); - assertEquals(100L, execution.getEndTime().getTime()); - } - - /** - * Test method for - * {@link org.springframework.batch.core.domain.JobExecution#getEndTime()}. - */ - public void testIsRunning() { - assertTrue(execution.isRunning()); - execution.setEndTime(new Date(100L)); - assertFalse(execution.isRunning()); - } - - /** - * Test method for - * {@link org.springframework.batch.core.domain.JobExecution#getEndTime()}. - */ - public void testIsRunningWithStoppedExecution() { - assertTrue(execution.isRunning()); - execution.stop(); - assertTrue(execution.isRunning()); - assertTrue(execution.isStopping()); - } - - /** - * Test method for - * {@link org.springframework.batch.core.domain.JobExecution#getStartTime()}. - */ - public void testGetStartTime() { - assertNull(execution.getStartTime()); - execution.setStartTime(new Date(0L)); - assertEquals(0L, execution.getStartTime().getTime()); - } - - /** - * Test method for - * {@link org.springframework.batch.core.domain.JobExecution#getStatus()}. - */ - public void testGetStatus() { - assertEquals(BatchStatus.STARTING, execution.getStatus()); - execution.setStatus(BatchStatus.COMPLETED); - assertEquals(BatchStatus.COMPLETED, execution.getStatus()); - } - - /** - * Test method for - * {@link org.springframework.batch.core.domain.JobExecution#getJobId()}. - */ - public void testGetJobId() { - assertEquals(11, execution.getJobId().longValue()); - execution = new JobExecution(new JobInstance(new Long(23), new JobParameters(), new JobSupport("testJob")), null); - assertEquals(23, execution.getJobId().longValue()); - } - - /** - * Test method for - * {@link org.springframework.batch.core.domain.JobExecution#getJobId()}. - */ - public void testGetJobIdForNullJob() { - execution = new JobExecution(null); - assertEquals(null, execution.getJobId()); - } - - /** - * Test method for - * {@link org.springframework.batch.core.domain.JobExecution#getJobId()}. - */ - public void testGetJob() { - assertNotNull(execution.getJobInstance()); - } - - /** - * Test method for - * {@link org.springframework.batch.core.domain.JobExecution#getExitStatus()}. - */ - public void testGetExitCode() { - assertEquals(ExitStatus.UNKNOWN, execution.getExitStatus()); - execution.setExitStatus(new ExitStatus(true, "23")); - assertEquals("23", execution.getExitStatus().getExitCode()); - } - - public void testContextContainsInfo() throws Exception { - assertEquals("foo", execution.getJobInstance().getJobName()); - } - - public void testAddAndRemoveStepExecution() throws Exception { - assertEquals(0, execution.getStepExecutions().size()); - execution.createStepExecution(new StepSupport("stepName")); - assertEquals(1, execution.getStepExecutions().size()); - } - - public void testStop() throws Exception { - StepExecution stepExecution = execution.createStepExecution(new StepSupport("stepName")); - assertFalse(stepExecution.isTerminateOnly()); - execution.stop(); - assertTrue(stepExecution.isTerminateOnly()); - } - - public void testToString() throws Exception { - assertTrue("JobExecution string does not contain id", execution.toString().indexOf("id=") >= 0); - assertTrue("JobExecution string does not contain name: " + execution, execution.toString().indexOf("foo") >= 0); - } - - public void testToStringWithNullJob() throws Exception { - execution = new JobExecution(); - assertTrue("JobExecution string does not contain id", execution.toString().indexOf("id=") >= 0); - assertTrue("JobExecution string does not contain job: " + execution, execution.toString().indexOf("job=") >= 0); - } -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.domain; + +import java.util.Date; + +import junit.framework.TestCase; + +import org.springframework.batch.repeat.ExitStatus; + +/** + * @author Dave Syer + * + */ +public class JobExecutionTests extends TestCase { + + private JobExecution execution = new JobExecution(new JobInstance(new Long(11), new JobParameters(), new JobSupport("foo")), new Long(12)); + + /** + * Test method for + * {@link org.springframework.batch.core.domain.JobExecution#JobExecution()}. + */ + public void testJobExecution() { + assertNull(new JobExecution().getId()); + } + + /** + * Test method for + * {@link org.springframework.batch.core.domain.JobExecution#getEndTime()}. + */ + public void testGetEndTime() { + assertNull(execution.getEndTime()); + execution.setEndTime(new Date(100L)); + assertEquals(100L, execution.getEndTime().getTime()); + } + + /** + * Test method for + * {@link org.springframework.batch.core.domain.JobExecution#getEndTime()}. + */ + public void testIsRunning() { + assertTrue(execution.isRunning()); + execution.setEndTime(new Date(100L)); + assertFalse(execution.isRunning()); + } + + /** + * Test method for + * {@link org.springframework.batch.core.domain.JobExecution#getEndTime()}. + */ + public void testIsRunningWithStoppedExecution() { + assertTrue(execution.isRunning()); + execution.stop(); + assertTrue(execution.isRunning()); + assertTrue(execution.isStopping()); + } + + /** + * Test method for + * {@link org.springframework.batch.core.domain.JobExecution#getStartTime()}. + */ + public void testGetStartTime() { + assertNull(execution.getStartTime()); + execution.setStartTime(new Date(0L)); + assertEquals(0L, execution.getStartTime().getTime()); + } + + /** + * Test method for + * {@link org.springframework.batch.core.domain.JobExecution#getStatus()}. + */ + public void testGetStatus() { + assertEquals(BatchStatus.STARTING, execution.getStatus()); + execution.setStatus(BatchStatus.COMPLETED); + assertEquals(BatchStatus.COMPLETED, execution.getStatus()); + } + + /** + * Test method for + * {@link org.springframework.batch.core.domain.JobExecution#getJobId()}. + */ + public void testGetJobId() { + assertEquals(11, execution.getJobId().longValue()); + execution = new JobExecution(new JobInstance(new Long(23), new JobParameters(), new JobSupport("testJob")), null); + assertEquals(23, execution.getJobId().longValue()); + } + + /** + * Test method for + * {@link org.springframework.batch.core.domain.JobExecution#getJobId()}. + */ + public void testGetJobIdForNullJob() { + execution = new JobExecution(null); + assertEquals(null, execution.getJobId()); + } + + /** + * Test method for + * {@link org.springframework.batch.core.domain.JobExecution#getJobId()}. + */ + public void testGetJob() { + assertNotNull(execution.getJobInstance()); + } + + /** + * Test method for + * {@link org.springframework.batch.core.domain.JobExecution#getExitStatus()}. + */ + public void testGetExitCode() { + assertEquals(ExitStatus.UNKNOWN, execution.getExitStatus()); + execution.setExitStatus(new ExitStatus(true, "23")); + assertEquals("23", execution.getExitStatus().getExitCode()); + } + + public void testContextContainsInfo() throws Exception { + assertEquals("foo", execution.getJobInstance().getJobName()); + } + + public void testAddAndRemoveStepExecution() throws Exception { + assertEquals(0, execution.getStepExecutions().size()); + execution.createStepExecution(new StepSupport("stepName")); + assertEquals(1, execution.getStepExecutions().size()); + } + + public void testStop() throws Exception { + StepExecution stepExecution = execution.createStepExecution(new StepSupport("stepName")); + assertFalse(stepExecution.isTerminateOnly()); + execution.stop(); + assertTrue(stepExecution.isTerminateOnly()); + } + + public void testToString() throws Exception { + assertTrue("JobExecution string does not contain id", execution.toString().indexOf("id=") >= 0); + assertTrue("JobExecution string does not contain name: " + execution, execution.toString().indexOf("foo") >= 0); + } + + public void testToStringWithNullJob() throws Exception { + execution = new JobExecution(); + assertTrue("JobExecution string does not contain id", execution.toString().indexOf("id=") >= 0); + assertTrue("JobExecution string does not contain job: " + execution, execution.toString().indexOf("job=") >= 0); + } +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/domain/JobInstanceTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/domain/JobInstanceTests.java index c39cc42eed..3f73e9485c 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/domain/JobInstanceTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/domain/JobInstanceTests.java @@ -1,52 +1,52 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.domain; - -import junit.framework.TestCase; - -/** - * @author dsyer - * - */ -public class JobInstanceTests extends TestCase { - - private JobInstance instance = new JobInstance(new Long(11), new JobParameters(), new JobSupport("job")); - - /** - * Test method for {@link org.springframework.batch.core.domain.JobInstance#getIdentifier()}. - */ - public void testGetName() { - instance = new JobInstance(new Long(1), new JobParameters(), new JobSupport("foo")); - assertEquals("foo", instance.getJobName()); - } - - public void testGetJob(){ - assertEquals("job", instance.getJob().getName()); - } - - public void testCreateWithNulls(){ - try { - new JobInstance(null, null, null); - fail("job instance can't exist without job specified"); - } - catch (IllegalArgumentException e) { - // expected - } - instance = new JobInstance(null, null, new JobSupport("testJob")); - assertEquals("testJob", instance.getJobName()); - assertEquals(0, instance.getJobParameters().getParameters().size()); - } -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.domain; + +import junit.framework.TestCase; + +/** + * @author dsyer + * + */ +public class JobInstanceTests extends TestCase { + + private JobInstance instance = new JobInstance(new Long(11), new JobParameters(), new JobSupport("job")); + + /** + * Test method for {@link org.springframework.batch.core.domain.JobInstance#getIdentifier()}. + */ + public void testGetName() { + instance = new JobInstance(new Long(1), new JobParameters(), new JobSupport("foo")); + assertEquals("foo", instance.getJobName()); + } + + public void testGetJob(){ + assertEquals("job", instance.getJob().getName()); + } + + public void testCreateWithNulls(){ + try { + new JobInstance(null, null, null); + fail("job instance can't exist without job specified"); + } + catch (IllegalArgumentException e) { + // expected + } + instance = new JobInstance(null, null, new JobSupport("testJob")); + assertEquals("testJob", instance.getJobName()); + assertEquals(0, instance.getJobParameters().getParameters().size()); + } +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/domain/JobInterruptedExceptionTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/domain/JobInterruptedExceptionTests.java index 1fdc49a15e..e53e7a19af 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/domain/JobInterruptedExceptionTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/domain/JobInterruptedExceptionTests.java @@ -1,41 +1,41 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.domain; - -import org.springframework.batch.core.AbstractExceptionTests; -import org.springframework.batch.core.domain.JobInterruptedException; - -/** - * @author Dave Syer - * - */ -public class JobInterruptedExceptionTests extends AbstractExceptionTests { - - /* (non-Javadoc) - * @see org.springframework.batch.io.exception.AbstractExceptionTests#getException(java.lang.String) - */ - public Exception getException(String msg) throws Exception { - return new JobInterruptedException(msg); - } - - /* (non-Javadoc) - * @see org.springframework.batch.io.exception.AbstractExceptionTests#getException(java.lang.String, java.lang.Throwable) - */ - public Exception getException(String msg, Throwable t) throws Exception { - return new RuntimeException(msg, t); - } - -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.domain; + +import org.springframework.batch.core.AbstractExceptionTests; +import org.springframework.batch.core.domain.JobInterruptedException; + +/** + * @author Dave Syer + * + */ +public class JobInterruptedExceptionTests extends AbstractExceptionTests { + + /* (non-Javadoc) + * @see org.springframework.batch.io.exception.AbstractExceptionTests#getException(java.lang.String) + */ + public Exception getException(String msg) throws Exception { + return new JobInterruptedException(msg); + } + + /* (non-Javadoc) + * @see org.springframework.batch.io.exception.AbstractExceptionTests#getException(java.lang.String, java.lang.Throwable) + */ + public Exception getException(String msg, Throwable t) throws Exception { + return new RuntimeException(msg, t); + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/domain/StepExecutionTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/domain/StepExecutionTests.java index 486b7e031a..aabf77f9d1 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/domain/StepExecutionTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/domain/StepExecutionTests.java @@ -1,271 +1,271 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.domain; - -import java.util.Date; -import java.util.HashSet; -import java.util.Set; - -import junit.framework.TestCase; - -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.repeat.ExitStatus; -import org.springframework.batch.support.PropertiesConverter; - -/** - * @author Dave Syer - * - */ -public class StepExecutionTests extends TestCase { - - private StepExecution execution = newStepExecution(new StepSupport("stepName"), - new Long(23)); - - private StepExecution blankExecution = new StepExecution(new StepSupport("blank"), new JobExecution()); - /** - * Test method for - * {@link org.springframework.batch.core.domain.JobExecution#JobExecution()}. - */ - public void testStepExecution() { - assertNull(new StepExecution().getId()); - } - - /** - * Test method for - * {@link org.springframework.batch.core.domain.JobExecution#JobExecution()}. - */ - public void testStepExecutionWithNullId() { - assertNull(new StepExecution(new StepSupport("stepName"), new JobExecution()).getId()); - } - - /** - * Test method for - * {@link org.springframework.batch.core.domain.JobExecution#getEndTime()}. - */ - public void testGetEndTime() { - assertNull(execution.getEndTime()); - execution.setEndTime(new Date(0L)); - assertEquals(0L, execution.getEndTime().getTime()); - } - - /** - * Test method for - * {@link org.springframework.batch.core.domain.JobExecution#getStartTime()}. - */ - public void testGetStartTime() { - assertNotNull(execution.getStartTime()); - execution.setStartTime(new Date(10L)); - assertEquals(10L, execution.getStartTime().getTime()); - } - - /** - * Test method for - * {@link org.springframework.batch.core.domain.JobExecution#getStatus()}. - */ - public void testGetStatus() { - assertEquals(BatchStatus.STARTING, execution.getStatus()); - execution.setStatus(BatchStatus.COMPLETED); - assertEquals(BatchStatus.COMPLETED, execution.getStatus()); - } - - /** - * Test method for - * {@link org.springframework.batch.core.domain.JobExecution#getJobId()}. - */ - public void testGetJobId() { - assertEquals(23, execution.getJobExecutionId().longValue()); - } - - /** - * Test method for - * {@link org.springframework.batch.core.domain.JobExecution#getExitStatus()}. - */ - public void testGetExitCode() { - assertEquals(ExitStatus.UNKNOWN, execution.getExitStatus()); - execution.setExitStatus(ExitStatus.FINISHED); - assertEquals(ExitStatus.FINISHED, execution.getExitStatus()); - } - - /** - * Test method for - * {@link org.springframework.batch.core.domain.StepExecution#incrementCommitCount()}. - */ - public void testIncrementCommitCount() { - int before = execution.getCommitCount().intValue(); - execution.incrementCommitCount(); - int after = execution.getCommitCount().intValue(); - assertEquals(before + 1, after); - } - - /** - * Test method for - * {@link org.springframework.batch.core.domain.StepExecution#incrementTaskCount()}. - */ - public void testIncrementLuwCount() { - int before = execution.getTaskCount().intValue(); - execution.incrementTaskCount(); - int after = execution.getTaskCount().intValue(); - assertEquals(before + 1, after); - } - - /** - * Test method for - * {@link org.springframework.batch.core.domain.StepExecution#rollback()}. - */ - public void testIncrementRollbackCount() { - int before = execution.getRollbackCount().intValue(); - execution.rollback(); - int after = execution.getRollbackCount().intValue(); - assertEquals(before + 1, after); - } - - /** - * Test method for - * {@link org.springframework.batch.core.domain.StepExecution#getCommitCount()}. - */ - public void testGetCommitCount() { - execution.setCommitCount(123); - assertEquals(123, execution.getCommitCount().intValue()); - } - - /** - * Test method for - * {@link org.springframework.batch.core.domain.StepExecution#getTaskCount()}. - */ - public void testGetTaskCount() { - execution.setTaskCount(123); - assertEquals(123, execution.getTaskCount().intValue()); - } - - /** - * Test method for - * {@link org.springframework.batch.core.domain.StepExecution#getRollbackCount()}. - */ - public void testGetRollbackCount() { - execution.setRollbackCount(123); - assertEquals(123, execution.getRollbackCount().intValue()); - } - - public void testGetJobExecution() throws Exception { - assertNotNull(execution.getJobExecution()); - } - - public void testApplyContribution() throws Exception { - StepContribution contribution = execution.createStepContribution(); - contribution.incrementCommitCount(); - execution.apply(contribution); - assertEquals(new Integer(1), execution.getCommitCount()); - } - - public void testTerminateOnly() throws Exception { - assertFalse(execution.isTerminateOnly()); - execution.setTerminateOnly(); - assertTrue(execution.isTerminateOnly()); - } - - public void testToStringWithNullName() throws Exception { - String value = new StepExecution(new StepSupport(null), new JobExecution()).toString(); - assertTrue("Should contain name=null: "+value, value.indexOf("name=null")>=0); - } - - public void testToString() throws Exception { - assertTrue("Should contain task count: " + execution.toString(), - execution.toString().indexOf("task") >= 0); - assertTrue("Should contain commit count: " + execution.toString(), - execution.toString().indexOf("commit") >= 0); - assertTrue("Should contain rollback count: " + execution.toString(), - execution.toString().indexOf("rollback") >= 0); - } - - public void testExecutionContext() throws Exception { - assertNotNull(execution.getExecutionContext()); - ExecutionContext context = new ExecutionContext(); - context.putString("foo", "bar"); - execution.setExecutionContext(context ); - assertEquals("bar", execution.getExecutionContext().getString("foo")); - } - - public void testEqualsWithSameIdentifier() throws Exception { - Step step = new StepSupport("stepName"); - Entity stepExecution1 = newStepExecution(step, new Long(11)); - Entity stepExecution2 = newStepExecution(step, new Long(11)); - assertEquals(stepExecution1, stepExecution2); - } - - public void testEqualsWithNull() throws Exception { - Entity stepExecution = newStepExecution(new StepSupport("stepName"), new Long(11)); - assertFalse(stepExecution.equals(null)); - } - - public void testEqualsWithNullIdentifiers() throws Exception { - Entity stepExecution = newStepExecution(new StepSupport("stepName"), new Long(11)); - assertFalse(stepExecution.equals(blankExecution)); - } - - public void testEqualsWithNullJob() throws Exception { - Entity stepExecution = newStepExecution(new StepSupport("stepName"), new Long(11)); - assertFalse(stepExecution.equals(blankExecution)); - } - - public void testEqualsWithNullStep() throws Exception { - Entity stepExecution = newStepExecution(new StepSupport("stepName"), null); - assertFalse(stepExecution.equals(blankExecution)); - } - - public void testEqualsWithSelf() throws Exception { - assertTrue(execution.equals(execution)); - } - - public void testEqualsWithDifferent() throws Exception { - Entity stepExecution = newStepExecution(new StepSupport("foo"), new Long(13)); - assertFalse(execution.equals(stepExecution)); - } - - public void testEqualsWithNullStepId() throws Exception { - Step step = new StepSupport("name"); - execution = newStepExecution(step, new Long(31)); - assertEquals("name", execution.getStepName()); - StepExecution stepExecution = newStepExecution(step, new Long(31)); - assertEquals(stepExecution.getJobExecutionId(), execution.getJobExecutionId()); - assertTrue(execution.equals(stepExecution)); - } - - public void testHashCode() throws Exception { - assertTrue("Hash code same as parent", new Entity(execution.getId()) - .hashCode() != execution.hashCode()); - } - - public void testHashCodeWithNullIds() throws Exception { - assertTrue("Hash code not same as parent", - new Entity(execution.getId()).hashCode() != blankExecution - .hashCode()); - } - - public void testHashCodeViaHashSet() throws Exception { - Set set = new HashSet(); - set.add(execution); - assertTrue(set.contains(execution)); - execution.setExecutionContext(new ExecutionContext(PropertiesConverter.stringToProperties("foo=bar"))); - assertTrue(set.contains(execution)); - } - - private StepExecution newStepExecution(Step step, Long long2) { - JobInstance job = new JobInstance(new Long(3), new JobParameters(), new JobSupport("testJob")); - StepExecution execution = new StepExecution(step, new JobExecution(job, long2), new Long(4)); - return execution; - } - -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.domain; + +import java.util.Date; +import java.util.HashSet; +import java.util.Set; + +import junit.framework.TestCase; + +import org.springframework.batch.item.ExecutionContext; +import org.springframework.batch.repeat.ExitStatus; +import org.springframework.batch.support.PropertiesConverter; + +/** + * @author Dave Syer + * + */ +public class StepExecutionTests extends TestCase { + + private StepExecution execution = newStepExecution(new StepSupport("stepName"), + new Long(23)); + + private StepExecution blankExecution = new StepExecution(new StepSupport("blank"), new JobExecution()); + /** + * Test method for + * {@link org.springframework.batch.core.domain.JobExecution#JobExecution()}. + */ + public void testStepExecution() { + assertNull(new StepExecution().getId()); + } + + /** + * Test method for + * {@link org.springframework.batch.core.domain.JobExecution#JobExecution()}. + */ + public void testStepExecutionWithNullId() { + assertNull(new StepExecution(new StepSupport("stepName"), new JobExecution()).getId()); + } + + /** + * Test method for + * {@link org.springframework.batch.core.domain.JobExecution#getEndTime()}. + */ + public void testGetEndTime() { + assertNull(execution.getEndTime()); + execution.setEndTime(new Date(0L)); + assertEquals(0L, execution.getEndTime().getTime()); + } + + /** + * Test method for + * {@link org.springframework.batch.core.domain.JobExecution#getStartTime()}. + */ + public void testGetStartTime() { + assertNotNull(execution.getStartTime()); + execution.setStartTime(new Date(10L)); + assertEquals(10L, execution.getStartTime().getTime()); + } + + /** + * Test method for + * {@link org.springframework.batch.core.domain.JobExecution#getStatus()}. + */ + public void testGetStatus() { + assertEquals(BatchStatus.STARTING, execution.getStatus()); + execution.setStatus(BatchStatus.COMPLETED); + assertEquals(BatchStatus.COMPLETED, execution.getStatus()); + } + + /** + * Test method for + * {@link org.springframework.batch.core.domain.JobExecution#getJobId()}. + */ + public void testGetJobId() { + assertEquals(23, execution.getJobExecutionId().longValue()); + } + + /** + * Test method for + * {@link org.springframework.batch.core.domain.JobExecution#getExitStatus()}. + */ + public void testGetExitCode() { + assertEquals(ExitStatus.UNKNOWN, execution.getExitStatus()); + execution.setExitStatus(ExitStatus.FINISHED); + assertEquals(ExitStatus.FINISHED, execution.getExitStatus()); + } + + /** + * Test method for + * {@link org.springframework.batch.core.domain.StepExecution#incrementCommitCount()}. + */ + public void testIncrementCommitCount() { + int before = execution.getCommitCount().intValue(); + execution.incrementCommitCount(); + int after = execution.getCommitCount().intValue(); + assertEquals(before + 1, after); + } + + /** + * Test method for + * {@link org.springframework.batch.core.domain.StepExecution#incrementTaskCount()}. + */ + public void testIncrementLuwCount() { + int before = execution.getTaskCount().intValue(); + execution.incrementTaskCount(); + int after = execution.getTaskCount().intValue(); + assertEquals(before + 1, after); + } + + /** + * Test method for + * {@link org.springframework.batch.core.domain.StepExecution#rollback()}. + */ + public void testIncrementRollbackCount() { + int before = execution.getRollbackCount().intValue(); + execution.rollback(); + int after = execution.getRollbackCount().intValue(); + assertEquals(before + 1, after); + } + + /** + * Test method for + * {@link org.springframework.batch.core.domain.StepExecution#getCommitCount()}. + */ + public void testGetCommitCount() { + execution.setCommitCount(123); + assertEquals(123, execution.getCommitCount().intValue()); + } + + /** + * Test method for + * {@link org.springframework.batch.core.domain.StepExecution#getTaskCount()}. + */ + public void testGetTaskCount() { + execution.setTaskCount(123); + assertEquals(123, execution.getTaskCount().intValue()); + } + + /** + * Test method for + * {@link org.springframework.batch.core.domain.StepExecution#getRollbackCount()}. + */ + public void testGetRollbackCount() { + execution.setRollbackCount(123); + assertEquals(123, execution.getRollbackCount().intValue()); + } + + public void testGetJobExecution() throws Exception { + assertNotNull(execution.getJobExecution()); + } + + public void testApplyContribution() throws Exception { + StepContribution contribution = execution.createStepContribution(); + contribution.incrementCommitCount(); + execution.apply(contribution); + assertEquals(new Integer(1), execution.getCommitCount()); + } + + public void testTerminateOnly() throws Exception { + assertFalse(execution.isTerminateOnly()); + execution.setTerminateOnly(); + assertTrue(execution.isTerminateOnly()); + } + + public void testToStringWithNullName() throws Exception { + String value = new StepExecution(new StepSupport(null), new JobExecution()).toString(); + assertTrue("Should contain name=null: "+value, value.indexOf("name=null")>=0); + } + + public void testToString() throws Exception { + assertTrue("Should contain task count: " + execution.toString(), + execution.toString().indexOf("task") >= 0); + assertTrue("Should contain commit count: " + execution.toString(), + execution.toString().indexOf("commit") >= 0); + assertTrue("Should contain rollback count: " + execution.toString(), + execution.toString().indexOf("rollback") >= 0); + } + + public void testExecutionContext() throws Exception { + assertNotNull(execution.getExecutionContext()); + ExecutionContext context = new ExecutionContext(); + context.putString("foo", "bar"); + execution.setExecutionContext(context ); + assertEquals("bar", execution.getExecutionContext().getString("foo")); + } + + public void testEqualsWithSameIdentifier() throws Exception { + Step step = new StepSupport("stepName"); + Entity stepExecution1 = newStepExecution(step, new Long(11)); + Entity stepExecution2 = newStepExecution(step, new Long(11)); + assertEquals(stepExecution1, stepExecution2); + } + + public void testEqualsWithNull() throws Exception { + Entity stepExecution = newStepExecution(new StepSupport("stepName"), new Long(11)); + assertFalse(stepExecution.equals(null)); + } + + public void testEqualsWithNullIdentifiers() throws Exception { + Entity stepExecution = newStepExecution(new StepSupport("stepName"), new Long(11)); + assertFalse(stepExecution.equals(blankExecution)); + } + + public void testEqualsWithNullJob() throws Exception { + Entity stepExecution = newStepExecution(new StepSupport("stepName"), new Long(11)); + assertFalse(stepExecution.equals(blankExecution)); + } + + public void testEqualsWithNullStep() throws Exception { + Entity stepExecution = newStepExecution(new StepSupport("stepName"), null); + assertFalse(stepExecution.equals(blankExecution)); + } + + public void testEqualsWithSelf() throws Exception { + assertTrue(execution.equals(execution)); + } + + public void testEqualsWithDifferent() throws Exception { + Entity stepExecution = newStepExecution(new StepSupport("foo"), new Long(13)); + assertFalse(execution.equals(stepExecution)); + } + + public void testEqualsWithNullStepId() throws Exception { + Step step = new StepSupport("name"); + execution = newStepExecution(step, new Long(31)); + assertEquals("name", execution.getStepName()); + StepExecution stepExecution = newStepExecution(step, new Long(31)); + assertEquals(stepExecution.getJobExecutionId(), execution.getJobExecutionId()); + assertTrue(execution.equals(stepExecution)); + } + + public void testHashCode() throws Exception { + assertTrue("Hash code same as parent", new Entity(execution.getId()) + .hashCode() != execution.hashCode()); + } + + public void testHashCodeWithNullIds() throws Exception { + assertTrue("Hash code not same as parent", + new Entity(execution.getId()).hashCode() != blankExecution + .hashCode()); + } + + public void testHashCodeViaHashSet() throws Exception { + Set set = new HashSet(); + set.add(execution); + assertTrue(set.contains(execution)); + execution.setExecutionContext(new ExecutionContext(PropertiesConverter.stringToProperties("foo=bar"))); + assertTrue(set.contains(execution)); + } + + private StepExecution newStepExecution(Step step, Long long2) { + JobInstance job = new JobInstance(new Long(3), new JobParameters(), new JobSupport("testJob")); + StepExecution execution = new StepExecution(step, new JobExecution(job, long2), new Long(4)); + return execution; + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/domain/StepSupport.java b/spring-batch-core/src/test/java/org/springframework/batch/core/domain/StepSupport.java index 4e41aaa036..4abc07b641 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/domain/StepSupport.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/domain/StepSupport.java @@ -1,117 +1,117 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.domain; - -import org.springframework.batch.core.domain.JobInterruptedException; -import org.springframework.batch.core.domain.Step; -import org.springframework.batch.core.domain.StepExecution; -import org.springframework.batch.io.exception.InfrastructureException; -import org.springframework.beans.factory.BeanNameAware; - -/** - * Basic no-op support implementation for use as base class for {@link Step}. Implements {@link BeanNameAware} so that - * if no name is provided explicitly it will be inferred from the bean definition in Spring configuration. - * - * @author Dave Syer - * - */ -public class StepSupport implements Step, BeanNameAware { - - private String name; - - private int startLimit = Integer.MAX_VALUE; - - private boolean allowStartIfComplete; - - /** - * Default constructor for {@link StepSupport}. - */ - public StepSupport() { - super(); - } - - /** - * @param string - */ - public StepSupport(String string) { - super(); - this.name = string; - } - - public String getName() { - return this.name; - } - - /** - * Set the name property if it is not already set. Because of the order of the callbacks in a Spring container the - * name property will be set first if it is present. Care is needed with bean definition inheritance - if a parent - * bean has a name, then its children need an explicit name as well, otherwise they will not be unique. - * - * @see org.springframework.beans.factory.BeanNameAware#setBeanName(java.lang.String) - */ - public void setBeanName(String name) { - if (this.name == null) { - this.name = name; - } - } - - /** - * Set the name property. Always overrides the default value if this object is a Spring bean. - * - * @see #setBeanName(java.lang.String) - */ - public void setName(String name) { - this.name = name; - } - - public int getStartLimit() { - return this.startLimit; - } - - /** - * Public setter for the startLimit. - * - * @param startLimit the startLimit to set - */ - public void setStartLimit(int startLimit) { - this.startLimit = startLimit; - } - - public boolean isAllowStartIfComplete() { - return this.allowStartIfComplete; - } - - /** - * Public setter for the shouldAllowStartIfComplete. - * - * @param allowStartIfComplete the shouldAllowStartIfComplete to set - */ - public void setAllowStartIfComplete(boolean allowStartIfComplete) { - this.allowStartIfComplete = allowStartIfComplete; - } - - /** - * Not supported but provided so that tests can easily create a step. - * - * @throws UnsupportedOperationException always - * - * @see org.springframework.batch.core.domain.Step#execute(org.springframework.batch.core.domain.StepExecution) - */ - public void execute(StepExecution stepExecution) throws JobInterruptedException, InfrastructureException { - throw new UnsupportedOperationException( - "Cannot process a StepExecution. Use a smarter subclass of StepSupport."); - } -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.domain; + +import org.springframework.batch.core.domain.JobInterruptedException; +import org.springframework.batch.core.domain.Step; +import org.springframework.batch.core.domain.StepExecution; +import org.springframework.batch.io.exception.InfrastructureException; +import org.springframework.beans.factory.BeanNameAware; + +/** + * Basic no-op support implementation for use as base class for {@link Step}. Implements {@link BeanNameAware} so that + * if no name is provided explicitly it will be inferred from the bean definition in Spring configuration. + * + * @author Dave Syer + * + */ +public class StepSupport implements Step, BeanNameAware { + + private String name; + + private int startLimit = Integer.MAX_VALUE; + + private boolean allowStartIfComplete; + + /** + * Default constructor for {@link StepSupport}. + */ + public StepSupport() { + super(); + } + + /** + * @param string + */ + public StepSupport(String string) { + super(); + this.name = string; + } + + public String getName() { + return this.name; + } + + /** + * Set the name property if it is not already set. Because of the order of the callbacks in a Spring container the + * name property will be set first if it is present. Care is needed with bean definition inheritance - if a parent + * bean has a name, then its children need an explicit name as well, otherwise they will not be unique. + * + * @see org.springframework.beans.factory.BeanNameAware#setBeanName(java.lang.String) + */ + public void setBeanName(String name) { + if (this.name == null) { + this.name = name; + } + } + + /** + * Set the name property. Always overrides the default value if this object is a Spring bean. + * + * @see #setBeanName(java.lang.String) + */ + public void setName(String name) { + this.name = name; + } + + public int getStartLimit() { + return this.startLimit; + } + + /** + * Public setter for the startLimit. + * + * @param startLimit the startLimit to set + */ + public void setStartLimit(int startLimit) { + this.startLimit = startLimit; + } + + public boolean isAllowStartIfComplete() { + return this.allowStartIfComplete; + } + + /** + * Public setter for the shouldAllowStartIfComplete. + * + * @param allowStartIfComplete the shouldAllowStartIfComplete to set + */ + public void setAllowStartIfComplete(boolean allowStartIfComplete) { + this.allowStartIfComplete = allowStartIfComplete; + } + + /** + * Not supported but provided so that tests can easily create a step. + * + * @throws UnsupportedOperationException always + * + * @see org.springframework.batch.core.domain.Step#execute(org.springframework.batch.core.domain.StepExecution) + */ + public void execute(StepExecution stepExecution) throws JobInterruptedException, InfrastructureException { + throw new UnsupportedOperationException( + "Cannot process a StepExecution. Use a smarter subclass of StepSupport."); + } +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/DuplicateJobExceptionTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/DuplicateJobExceptionTests.java index 3b3e2bbb1f..4ebabb3860 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/DuplicateJobExceptionTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/DuplicateJobExceptionTests.java @@ -1,44 +1,44 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.repository; - -import org.springframework.batch.core.AbstractExceptionTests; -import org.springframework.batch.core.repository.DuplicateJobException; - -/** - * @author Dave Syer - * - */ -public class DuplicateJobExceptionTests extends AbstractExceptionTests { - - /* - * (non-Javadoc) - * @see org.springframework.batch.io.exception.AbstractExceptionTests#getException(java.lang.String) - */ - public Exception getException(String msg) throws Exception { - return new DuplicateJobException(msg); - } - - /* - * (non-Javadoc) - * @see org.springframework.batch.io.exception.AbstractExceptionTests#getException(java.lang.String, - * java.lang.Throwable) - */ - public Exception getException(String msg, Throwable t) throws Exception { - return new DuplicateJobException(msg, t); - } - -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.repository; + +import org.springframework.batch.core.AbstractExceptionTests; +import org.springframework.batch.core.repository.DuplicateJobException; + +/** + * @author Dave Syer + * + */ +public class DuplicateJobExceptionTests extends AbstractExceptionTests { + + /* + * (non-Javadoc) + * @see org.springframework.batch.io.exception.AbstractExceptionTests#getException(java.lang.String) + */ + public Exception getException(String msg) throws Exception { + return new DuplicateJobException(msg); + } + + /* + * (non-Javadoc) + * @see org.springframework.batch.io.exception.AbstractExceptionTests#getException(java.lang.String, + * java.lang.Throwable) + */ + public Exception getException(String msg, Throwable t) throws Exception { + return new DuplicateJobException(msg, t); + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/JobExceptionTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/JobExceptionTests.java index b2e63f6042..8b010b7151 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/JobExceptionTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/JobExceptionTests.java @@ -1,44 +1,44 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.repository; - -import org.springframework.batch.core.AbstractExceptionTests; -import org.springframework.batch.core.repository.JobException; - -/** - * @author Dave Syer - * - */ -public class JobExceptionTests extends AbstractExceptionTests { - - /* - * (non-Javadoc) - * @see org.springframework.batch.io.exception.AbstractExceptionTests#getException(java.lang.String) - */ - public Exception getException(String msg) throws Exception { - return new JobException(msg); - } - - /* - * (non-Javadoc) - * @see org.springframework.batch.io.exception.AbstractExceptionTests#getException(java.lang.String, - * java.lang.Throwable) - */ - public Exception getException(String msg, Throwable t) throws Exception { - return new JobException(msg, t); - } - -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.repository; + +import org.springframework.batch.core.AbstractExceptionTests; +import org.springframework.batch.core.repository.JobException; + +/** + * @author Dave Syer + * + */ +public class JobExceptionTests extends AbstractExceptionTests { + + /* + * (non-Javadoc) + * @see org.springframework.batch.io.exception.AbstractExceptionTests#getException(java.lang.String) + */ + public Exception getException(String msg) throws Exception { + return new JobException(msg); + } + + /* + * (non-Javadoc) + * @see org.springframework.batch.io.exception.AbstractExceptionTests#getException(java.lang.String, + * java.lang.Throwable) + */ + public Exception getException(String msg, Throwable t) throws Exception { + return new JobException(msg, t); + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/JobExecutionAlreadyRunningExceptionTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/JobExecutionAlreadyRunningExceptionTests.java index 10ac6053f2..3dfa323ceb 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/JobExecutionAlreadyRunningExceptionTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/JobExecutionAlreadyRunningExceptionTests.java @@ -1,40 +1,40 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.repository; - -import org.springframework.batch.core.AbstractExceptionTests; - -/** - * @author Dave Syer - * - */ -public class JobExecutionAlreadyRunningExceptionTests extends AbstractExceptionTests { - - /* (non-Javadoc) - * @see org.springframework.batch.io.exception.AbstractExceptionTests#getException(java.lang.String) - */ - public Exception getException(String msg) throws Exception { - return new JobExecutionAlreadyRunningException(msg); - } - - /* (non-Javadoc) - * @see org.springframework.batch.io.exception.AbstractExceptionTests#getException(java.lang.String, java.lang.Throwable) - */ - public Exception getException(String msg, Throwable t) throws Exception { - return new JobExecutionAlreadyRunningException(msg, t); - } - -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.repository; + +import org.springframework.batch.core.AbstractExceptionTests; + +/** + * @author Dave Syer + * + */ +public class JobExecutionAlreadyRunningExceptionTests extends AbstractExceptionTests { + + /* (non-Javadoc) + * @see org.springframework.batch.io.exception.AbstractExceptionTests#getException(java.lang.String) + */ + public Exception getException(String msg) throws Exception { + return new JobExecutionAlreadyRunningException(msg); + } + + /* (non-Javadoc) + * @see org.springframework.batch.io.exception.AbstractExceptionTests#getException(java.lang.String, java.lang.Throwable) + */ + public Exception getException(String msg, Throwable t) throws Exception { + return new JobExecutionAlreadyRunningException(msg, t); + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/JobRestartExceptionTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/JobRestartExceptionTests.java index 702c8333ae..a07f0e7196 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/JobRestartExceptionTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/JobRestartExceptionTests.java @@ -1,43 +1,43 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.repository; - -import org.springframework.batch.core.AbstractExceptionTests; - -/** - * @author Dave Syer - * - */ -public class JobRestartExceptionTests extends AbstractExceptionTests { - - /* - * (non-Javadoc) - * @see org.springframework.batch.io.exception.AbstractExceptionTests#getException(java.lang.String) - */ - public Exception getException(String msg) throws Exception { - return new JobRestartException(msg); - } - - /* - * (non-Javadoc) - * @see org.springframework.batch.io.exception.AbstractExceptionTests#getException(java.lang.String, - * java.lang.Throwable) - */ - public Exception getException(String msg, Throwable t) throws Exception { - return new JobRestartException(msg, t); - } - -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.repository; + +import org.springframework.batch.core.AbstractExceptionTests; + +/** + * @author Dave Syer + * + */ +public class JobRestartExceptionTests extends AbstractExceptionTests { + + /* + * (non-Javadoc) + * @see org.springframework.batch.io.exception.AbstractExceptionTests#getException(java.lang.String) + */ + public Exception getException(String msg) throws Exception { + return new JobRestartException(msg); + } + + /* + * (non-Javadoc) + * @see org.springframework.batch.io.exception.AbstractExceptionTests#getException(java.lang.String, + * java.lang.Throwable) + */ + public Exception getException(String msg, Throwable t) throws Exception { + return new JobRestartException(msg, t); + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/NoSuchJobExceptionTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/NoSuchJobExceptionTests.java index be2a86c3c1..d3c5b7f240 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/NoSuchJobExceptionTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/NoSuchJobExceptionTests.java @@ -1,44 +1,44 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.repository; - -import org.springframework.batch.core.AbstractExceptionTests; -import org.springframework.batch.core.repository.NoSuchJobException; - -/** - * @author Dave Syer - * - */ -public class NoSuchJobExceptionTests extends AbstractExceptionTests { - - /* - * (non-Javadoc) - * @see org.springframework.batch.io.exception.AbstractExceptionTests#getException(java.lang.String) - */ - public Exception getException(String msg) throws Exception { - return new NoSuchJobException(msg); - } - - /* - * (non-Javadoc) - * @see org.springframework.batch.io.exception.AbstractExceptionTests#getException(java.lang.String, - * java.lang.Throwable) - */ - public Exception getException(String msg, Throwable t) throws Exception { - return new NoSuchJobException(msg, t); - } - -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.repository; + +import org.springframework.batch.core.AbstractExceptionTests; +import org.springframework.batch.core.repository.NoSuchJobException; + +/** + * @author Dave Syer + * + */ +public class NoSuchJobExceptionTests extends AbstractExceptionTests { + + /* + * (non-Javadoc) + * @see org.springframework.batch.io.exception.AbstractExceptionTests#getException(java.lang.String) + */ + public Exception getException(String msg) throws Exception { + return new NoSuchJobException(msg); + } + + /* + * (non-Javadoc) + * @see org.springframework.batch.io.exception.AbstractExceptionTests#getException(java.lang.String, + * java.lang.Throwable) + */ + public Exception getException(String msg, Throwable t) throws Exception { + return new NoSuchJobException(msg, t); + } + +} diff --git a/spring-batch-execution/.project b/spring-batch-execution/.project index 48fc2b0261..f052224418 100644 --- a/spring-batch-execution/.project +++ b/spring-batch-execution/.project @@ -1,31 +1,31 @@ - - - spring-batch-execution - Execution tools and implementations of Spring Batch Core interfaces - - spring-batch-core - spring-batch-infrastructure - - - - org.eclipse.jdt.core.javabuilder - - - - - org.springframework.ide.eclipse.core.springbuilder - - - - - org.devzuz.q.maven.jdt.core.mavenIncrementalBuilder - - - - - - org.springframework.ide.eclipse.core.springnature - org.eclipse.jdt.core.javanature - org.devzuz.q.maven.jdt.core.mavenNature - - + + + spring-batch-execution + Execution tools and implementations of Spring Batch Core interfaces + + spring-batch-core + spring-batch-infrastructure + + + + org.eclipse.jdt.core.javabuilder + + + + + org.springframework.ide.eclipse.core.springbuilder + + + + + org.devzuz.q.maven.jdt.core.mavenIncrementalBuilder + + + + + + org.springframework.ide.eclipse.core.springnature + org.eclipse.jdt.core.javanature + org.devzuz.q.maven.jdt.core.mavenNature + + diff --git a/spring-batch-execution/.settings/org.eclipse.jdt.core.prefs b/spring-batch-execution/.settings/org.eclipse.jdt.core.prefs index f13e0b0650..29b1973a79 100644 --- a/spring-batch-execution/.settings/org.eclipse.jdt.core.prefs +++ b/spring-batch-execution/.settings/org.eclipse.jdt.core.prefs @@ -1,7 +1,7 @@ -#Thu Mar 06 17:27:20 GMT 2008 -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.4 -org.eclipse.jdt.core.compiler.compliance=1.4 -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.enumIdentifier=warning -org.eclipse.jdt.core.compiler.source=1.4 +#Thu Mar 06 17:27:20 GMT 2008 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.4 +org.eclipse.jdt.core.compiler.compliance=1.4 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=warning +org.eclipse.jdt.core.compiler.source=1.4 diff --git a/spring-batch-execution/.springBeans b/spring-batch-execution/.springBeans index 3f58094ef0..0d78bec76a 100644 --- a/spring-batch-execution/.springBeans +++ b/spring-batch-execution/.springBeans @@ -1,44 +1,44 @@ - - - 1 - - - - - - - src/test/resources/org/springframework/batch/execution/repository/dao/data-source-context.xml - src/test/resources/org/springframework/batch/execution/repository/dao/sql-dao-test.xml - src/test/resources/org/springframework/batch/execution/configuration/test-context.xml - src/test/resources/org/springframework/batch/execution/bootstrap/support/job.xml - src/test/resources/org/springframework/batch/execution/bootstrap/support/test-environment.xml - - - - - true - false - - src/test/resources/org/springframework/batch/execution/repository/dao/data-source-context.xml - src/test/resources/org/springframework/batch/execution/repository/dao/sql-dao-test.xml - - - - - true - false - - src/test/resources/org/springframework/batch/execution/repository/dao/data-source-context.xml - - - - - true - false - - src/test/resources/org/springframework/batch/execution/bootstrap/support/job.xml - src/test/resources/org/springframework/batch/execution/bootstrap/support/test-environment.xml - - - - + + + 1 + + + + + + + src/test/resources/org/springframework/batch/execution/repository/dao/data-source-context.xml + src/test/resources/org/springframework/batch/execution/repository/dao/sql-dao-test.xml + src/test/resources/org/springframework/batch/execution/configuration/test-context.xml + src/test/resources/org/springframework/batch/execution/bootstrap/support/job.xml + src/test/resources/org/springframework/batch/execution/bootstrap/support/test-environment.xml + + + + + true + false + + src/test/resources/org/springframework/batch/execution/repository/dao/data-source-context.xml + src/test/resources/org/springframework/batch/execution/repository/dao/sql-dao-test.xml + + + + + true + false + + src/test/resources/org/springframework/batch/execution/repository/dao/data-source-context.xml + + + + + true + false + + src/test/resources/org/springframework/batch/execution/bootstrap/support/job.xml + src/test/resources/org/springframework/batch/execution/bootstrap/support/test-environment.xml + + + + diff --git a/spring-batch-execution/src/main/java/org/springframework/batch/execution/configuration/JobRegistryBeanPostProcessor.java b/spring-batch-execution/src/main/java/org/springframework/batch/execution/configuration/JobRegistryBeanPostProcessor.java index 63ec01dc07..1f6e34239c 100644 --- a/spring-batch-execution/src/main/java/org/springframework/batch/execution/configuration/JobRegistryBeanPostProcessor.java +++ b/spring-batch-execution/src/main/java/org/springframework/batch/execution/configuration/JobRegistryBeanPostProcessor.java @@ -1,113 +1,113 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.execution.configuration; - -import java.util.Collection; -import java.util.HashSet; -import java.util.Iterator; - -import org.springframework.batch.core.configuration.JobLocator; -import org.springframework.batch.core.configuration.JobRegistry; -import org.springframework.batch.core.domain.Job; -import org.springframework.batch.core.repository.DuplicateJobException; -import org.springframework.beans.BeansException; -import org.springframework.beans.FatalBeanException; -import org.springframework.beans.factory.DisposableBean; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.beans.factory.config.BeanPostProcessor; -import org.springframework.util.Assert; - -/** - * A {@link BeanPostProcessor} that registers {@link Job} beans - * with a {@link JobRegistry}. Include a bean of this type along - * with your job configuration, and use the same - * {@link JobRegistry} as a {@link JobLocator} when - * you need to locate a {@link JobLocator} to launch. - * - * @author Dave Syer - * - */ -public class JobRegistryBeanPostProcessor implements BeanPostProcessor, InitializingBean, DisposableBean { - - // It doesn't make sense for this to have a default value... - private JobRegistry jobConfigurationRegistry = null; - - private Collection jobNames = new HashSet(); - - /** - * Injection setter for {@link JobRegistry}. - * - * @param jobRegistry the jobConfigurationRegistry to set - */ - public void setJobRegistry(JobRegistry jobRegistry) { - this.jobConfigurationRegistry = jobRegistry; - } - - /** - * Make sure the registry is set before use. - * - * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet() - */ - public void afterPropertiesSet() throws Exception { - Assert.notNull(jobConfigurationRegistry, "JobConfigurationRegistry must not be null"); - } - - /** - * De-register all the {@link Job} instances that were - * regsistered by this post processor. - * @see org.springframework.beans.factory.DisposableBean#destroy() - */ - public void destroy() throws Exception { - for (Iterator iter = jobNames.iterator(); iter.hasNext();) { - String name = (String) iter.next(); - jobConfigurationRegistry.unregister(name); - } - jobNames.clear(); - } - - /** - * If the bean is an instance of {@link Job} then register it. - * @throws FatalBeanException if there is a - * {@link DuplicateJobException}. - * - * @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessAfterInitialization(java.lang.Object, - * java.lang.String) - */ - public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { - if (bean instanceof Job) { - Job job = (Job) bean; - try { - jobConfigurationRegistry.register(new ReferenceJobFactory(job)); - jobNames.add(job.getName()); - } - catch (DuplicateJobException e) { - throw new FatalBeanException("Cannot register job configuration", e); - } - } - return bean; - } - - /** - * Do nothing. - * - * @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessBeforeInitialization(java.lang.Object, - * java.lang.String) - */ - public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { - return bean; - } - -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.execution.configuration; + +import java.util.Collection; +import java.util.HashSet; +import java.util.Iterator; + +import org.springframework.batch.core.configuration.JobLocator; +import org.springframework.batch.core.configuration.JobRegistry; +import org.springframework.batch.core.domain.Job; +import org.springframework.batch.core.repository.DuplicateJobException; +import org.springframework.beans.BeansException; +import org.springframework.beans.FatalBeanException; +import org.springframework.beans.factory.DisposableBean; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.beans.factory.config.BeanPostProcessor; +import org.springframework.util.Assert; + +/** + * A {@link BeanPostProcessor} that registers {@link Job} beans + * with a {@link JobRegistry}. Include a bean of this type along + * with your job configuration, and use the same + * {@link JobRegistry} as a {@link JobLocator} when + * you need to locate a {@link JobLocator} to launch. + * + * @author Dave Syer + * + */ +public class JobRegistryBeanPostProcessor implements BeanPostProcessor, InitializingBean, DisposableBean { + + // It doesn't make sense for this to have a default value... + private JobRegistry jobConfigurationRegistry = null; + + private Collection jobNames = new HashSet(); + + /** + * Injection setter for {@link JobRegistry}. + * + * @param jobRegistry the jobConfigurationRegistry to set + */ + public void setJobRegistry(JobRegistry jobRegistry) { + this.jobConfigurationRegistry = jobRegistry; + } + + /** + * Make sure the registry is set before use. + * + * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet() + */ + public void afterPropertiesSet() throws Exception { + Assert.notNull(jobConfigurationRegistry, "JobConfigurationRegistry must not be null"); + } + + /** + * De-register all the {@link Job} instances that were + * regsistered by this post processor. + * @see org.springframework.beans.factory.DisposableBean#destroy() + */ + public void destroy() throws Exception { + for (Iterator iter = jobNames.iterator(); iter.hasNext();) { + String name = (String) iter.next(); + jobConfigurationRegistry.unregister(name); + } + jobNames.clear(); + } + + /** + * If the bean is an instance of {@link Job} then register it. + * @throws FatalBeanException if there is a + * {@link DuplicateJobException}. + * + * @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessAfterInitialization(java.lang.Object, + * java.lang.String) + */ + public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { + if (bean instanceof Job) { + Job job = (Job) bean; + try { + jobConfigurationRegistry.register(new ReferenceJobFactory(job)); + jobNames.add(job.getName()); + } + catch (DuplicateJobException e) { + throw new FatalBeanException("Cannot register job configuration", e); + } + } + return bean; + } + + /** + * Do nothing. + * + * @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessBeforeInitialization(java.lang.Object, + * java.lang.String) + */ + public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { + return bean; + } + +} diff --git a/spring-batch-execution/src/main/java/org/springframework/batch/execution/configuration/MapJobRegistry.java b/spring-batch-execution/src/main/java/org/springframework/batch/execution/configuration/MapJobRegistry.java index ff5806a37b..269d65408b 100644 --- a/spring-batch-execution/src/main/java/org/springframework/batch/execution/configuration/MapJobRegistry.java +++ b/spring-batch-execution/src/main/java/org/springframework/batch/execution/configuration/MapJobRegistry.java @@ -1,95 +1,95 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.execution.configuration; - -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; - -import org.springframework.batch.core.configuration.JobFactory; -import org.springframework.batch.core.configuration.JobRegistry; -import org.springframework.batch.core.configuration.ListableJobRegistry; -import org.springframework.batch.core.domain.Job; -import org.springframework.batch.core.repository.DuplicateJobException; -import org.springframework.batch.core.repository.NoSuchJobException; -import org.springframework.util.Assert; - -/** - * Simple map-based implementation of {@link JobRegistry}. Access to the map is - * synchronized, guarded by an internal lock. - * - * @author Dave Syer - * - */ -public class MapJobRegistry implements ListableJobRegistry { - - private Map map = new HashMap(); - - /* - * (non-Javadoc) - * @see org.springframework.batch.container.common.configuration.JobConfigurationRegistry#registerJobConfiguration(org.springframework.batch.container.common.configuration.JobConfiguration) - */ - public void register(JobFactory jobFactory) throws DuplicateJobException { - Assert.notNull(jobFactory); - String name = jobFactory.getJobName(); - Assert.notNull(name, "Job configuration must have a name."); - synchronized (map) { - if (map.containsKey(name)) { - throw new DuplicateJobException("A job configuration with this name [" + name - + "] was already registered"); - } - map.put(name, jobFactory); - } - } - - /* - * (non-Javadoc) - * @see org.springframework.batch.container.common.configuration.JobConfigurationRegistry#unregister(org.springframework.batch.container.common.configuration.JobConfiguration) - */ - public void unregister(String name) { - Assert.notNull(name, "Job configuration must have a name."); - synchronized (map) { - map.remove(name); - } - - } - - /* - * (non-Javadoc) - * @see org.springframework.batch.container.common.configuration.JobConfigurationLocator#getJobConfiguration(java.lang.String) - */ - public Job getJob(String name) throws NoSuchJobException { - synchronized (map) { - if (!map.containsKey(name)) { - throw new NoSuchJobException("No job configuration with the name [" + name + "] was registered"); - } - return (Job) ((JobFactory) map.get(name)).createJob(); - } - } - - /* - * (non-Javadoc) - * @see org.springframework.batch.container.common.configuration.ListableJobConfigurationRegistry#getJobConfigurations() - */ - public Collection getJobNames() { - synchronized (map) { - return Collections.unmodifiableCollection(new HashSet(map.keySet())); - } - } - -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.execution.configuration; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; + +import org.springframework.batch.core.configuration.JobFactory; +import org.springframework.batch.core.configuration.JobRegistry; +import org.springframework.batch.core.configuration.ListableJobRegistry; +import org.springframework.batch.core.domain.Job; +import org.springframework.batch.core.repository.DuplicateJobException; +import org.springframework.batch.core.repository.NoSuchJobException; +import org.springframework.util.Assert; + +/** + * Simple map-based implementation of {@link JobRegistry}. Access to the map is + * synchronized, guarded by an internal lock. + * + * @author Dave Syer + * + */ +public class MapJobRegistry implements ListableJobRegistry { + + private Map map = new HashMap(); + + /* + * (non-Javadoc) + * @see org.springframework.batch.container.common.configuration.JobConfigurationRegistry#registerJobConfiguration(org.springframework.batch.container.common.configuration.JobConfiguration) + */ + public void register(JobFactory jobFactory) throws DuplicateJobException { + Assert.notNull(jobFactory); + String name = jobFactory.getJobName(); + Assert.notNull(name, "Job configuration must have a name."); + synchronized (map) { + if (map.containsKey(name)) { + throw new DuplicateJobException("A job configuration with this name [" + name + + "] was already registered"); + } + map.put(name, jobFactory); + } + } + + /* + * (non-Javadoc) + * @see org.springframework.batch.container.common.configuration.JobConfigurationRegistry#unregister(org.springframework.batch.container.common.configuration.JobConfiguration) + */ + public void unregister(String name) { + Assert.notNull(name, "Job configuration must have a name."); + synchronized (map) { + map.remove(name); + } + + } + + /* + * (non-Javadoc) + * @see org.springframework.batch.container.common.configuration.JobConfigurationLocator#getJobConfiguration(java.lang.String) + */ + public Job getJob(String name) throws NoSuchJobException { + synchronized (map) { + if (!map.containsKey(name)) { + throw new NoSuchJobException("No job configuration with the name [" + name + "] was registered"); + } + return (Job) ((JobFactory) map.get(name)).createJob(); + } + } + + /* + * (non-Javadoc) + * @see org.springframework.batch.container.common.configuration.ListableJobConfigurationRegistry#getJobConfigurations() + */ + public Collection getJobNames() { + synchronized (map) { + return Collections.unmodifiableCollection(new HashSet(map.keySet())); + } + } + +} diff --git a/spring-batch-execution/src/main/java/org/springframework/batch/execution/launch/JobLauncher.java b/spring-batch-execution/src/main/java/org/springframework/batch/execution/launch/JobLauncher.java index 734e5fd990..52aad39990 100644 --- a/spring-batch-execution/src/main/java/org/springframework/batch/execution/launch/JobLauncher.java +++ b/spring-batch-execution/src/main/java/org/springframework/batch/execution/launch/JobLauncher.java @@ -1,54 +1,54 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.execution.launch; - -import org.springframework.batch.core.domain.Job; -import org.springframework.batch.core.domain.JobExecution; -import org.springframework.batch.core.domain.JobParameters; -import org.springframework.batch.core.repository.JobRestartException; -import org.springframework.batch.core.repository.JobExecutionAlreadyRunningException; - -/** - * Simple interface for controlling jobs, including possible ad-hoc executions, - * based on different runtime identifiers. It is extremely important to note - * that this interface makes absolutely no guarantees about whether or not calls - * to it are executed synchronously or asynchronously. The javadocs for specific - * implementations should be checked to ensure callers fully understand how the - * job will be run. - * - * @author Lucas Ward - * @author Dave Syer - */ - -public interface JobLauncher { - - /** - * Start a job execution for the given {@link Job} and {@link JobParameters}. - * - * @return the exit code from the job if it returns synchronously. If the - * implementation is asynchronous, the status might well be unknown. - * - * @throws JobExecutionAlreadyRunningException if the JobInstance identified - * by the properties already has an execution running. - * @throws IllegalArgumentException if the job or jobInstanceProperties are - * null. - * @throws JobRestartException if the job has been run before and - * circumstances that preclude a re-start. - */ - public JobExecution run(Job job, JobParameters jobParameters) throws JobExecutionAlreadyRunningException, - JobRestartException; - -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.execution.launch; + +import org.springframework.batch.core.domain.Job; +import org.springframework.batch.core.domain.JobExecution; +import org.springframework.batch.core.domain.JobParameters; +import org.springframework.batch.core.repository.JobRestartException; +import org.springframework.batch.core.repository.JobExecutionAlreadyRunningException; + +/** + * Simple interface for controlling jobs, including possible ad-hoc executions, + * based on different runtime identifiers. It is extremely important to note + * that this interface makes absolutely no guarantees about whether or not calls + * to it are executed synchronously or asynchronously. The javadocs for specific + * implementations should be checked to ensure callers fully understand how the + * job will be run. + * + * @author Lucas Ward + * @author Dave Syer + */ + +public interface JobLauncher { + + /** + * Start a job execution for the given {@link Job} and {@link JobParameters}. + * + * @return the exit code from the job if it returns synchronously. If the + * implementation is asynchronous, the status might well be unknown. + * + * @throws JobExecutionAlreadyRunningException if the JobInstance identified + * by the properties already has an execution running. + * @throws IllegalArgumentException if the job or jobInstanceProperties are + * null. + * @throws JobRestartException if the job has been run before and + * circumstances that preclude a re-start. + */ + public JobExecution run(Job job, JobParameters jobParameters) throws JobExecutionAlreadyRunningException, + JobRestartException; + +} diff --git a/spring-batch-execution/src/main/java/org/springframework/batch/execution/launch/support/ExitCodeMapper.java b/spring-batch-execution/src/main/java/org/springframework/batch/execution/launch/support/ExitCodeMapper.java index 14bde3e0e2..772028bf2d 100644 --- a/spring-batch-execution/src/main/java/org/springframework/batch/execution/launch/support/ExitCodeMapper.java +++ b/spring-batch-execution/src/main/java/org/springframework/batch/execution/launch/support/ExitCodeMapper.java @@ -1,30 +1,30 @@ -package org.springframework.batch.execution.launch.support; - - -/** - * - * This interface should be implemented when an environment calling the batch famework has specific - * requirements regarding the process return codes. - * - * @param The type of returncode expected by the environment - * @author Stijn Maller - * @author Lucas Ward - * @author Dave Syer - */ -public interface ExitCodeMapper { - - static int JVM_EXITCODE_COMPLETED = 0; - static int JVM_EXITCODE_GENERIC_ERROR = 1; - static int JVM_EXITCODE_JOB_ERROR = 2; - public static final String NO_SUCH_JOB = "NO_SUCH_JOB"; - public static final String JOB_NOT_PROVIDED = "JOB_NOT_PROVIDED"; - - /** - * Transform the exitcode known by the batchframework into an exitcode in the - * format of the calling environment. - * @param exitCode The exitcode which is used internally by the batch framework. - * @return The corresponding exitcode as known by the calling environment. - */ - public int getExitCode(String exitCode); - -} +package org.springframework.batch.execution.launch.support; + + +/** + * + * This interface should be implemented when an environment calling the batch famework has specific + * requirements regarding the process return codes. + * + * @param The type of returncode expected by the environment + * @author Stijn Maller + * @author Lucas Ward + * @author Dave Syer + */ +public interface ExitCodeMapper { + + static int JVM_EXITCODE_COMPLETED = 0; + static int JVM_EXITCODE_GENERIC_ERROR = 1; + static int JVM_EXITCODE_JOB_ERROR = 2; + public static final String NO_SUCH_JOB = "NO_SUCH_JOB"; + public static final String JOB_NOT_PROVIDED = "JOB_NOT_PROVIDED"; + + /** + * Transform the exitcode known by the batchframework into an exitcode in the + * format of the calling environment. + * @param exitCode The exitcode which is used internally by the batch framework. + * @return The corresponding exitcode as known by the calling environment. + */ + public int getExitCode(String exitCode); + +} diff --git a/spring-batch-execution/src/main/java/org/springframework/batch/execution/launch/support/ExportedJobLauncher.java b/spring-batch-execution/src/main/java/org/springframework/batch/execution/launch/support/ExportedJobLauncher.java index 9c81360dbc..8f50422fbe 100644 --- a/spring-batch-execution/src/main/java/org/springframework/batch/execution/launch/support/ExportedJobLauncher.java +++ b/spring-batch-execution/src/main/java/org/springframework/batch/execution/launch/support/ExportedJobLauncher.java @@ -1,74 +1,74 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.batch.execution.launch.support; - -import java.util.Properties; - -import org.springframework.batch.core.domain.JobExecution; -import org.springframework.batch.execution.launch.JobLauncher; - -/** - * Interface to expose for remote management of jobs. Similar to - * {@link JobLauncher}, but replaces {@link JobExecution} and - * {@link JobIdentifier} with Strings in return types and method parameters, so - * it can be inspected by remote clients like the jconsole from the JRE without - * any links to Spring Batch. - * - * @author Dave Syer - * - */ -public interface ExportedJobLauncher { - - /** - * Launch a job with the given name. - * - * @param name the name of the job to launch - * @return a representation of the {@link JobExecution} returned by a - * {@link JobLauncher}. - */ - String run(String name); - - /** - * Launch a job with the given name and parameters. - * - * @param name the name of the job to launch - * @return a representation of the {@link JobExecution} returned by a - * {@link JobLauncher}. - */ - String run(String name, String params); - - /** - * Stop all running jobs. - */ - void stop(); - - /** - * Enquire if any jobs launched here are still running. - * - * @return true if any jobs are running. - */ - boolean isRunning(); - - /** - * Query statistics of currently executing jobs. - * - * @return properties representing last known state of currently executing - * jobs - */ - public Properties getStatistics(); - -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.batch.execution.launch.support; + +import java.util.Properties; + +import org.springframework.batch.core.domain.JobExecution; +import org.springframework.batch.execution.launch.JobLauncher; + +/** + * Interface to expose for remote management of jobs. Similar to + * {@link JobLauncher}, but replaces {@link JobExecution} and + * {@link JobIdentifier} with Strings in return types and method parameters, so + * it can be inspected by remote clients like the jconsole from the JRE without + * any links to Spring Batch. + * + * @author Dave Syer + * + */ +public interface ExportedJobLauncher { + + /** + * Launch a job with the given name. + * + * @param name the name of the job to launch + * @return a representation of the {@link JobExecution} returned by a + * {@link JobLauncher}. + */ + String run(String name); + + /** + * Launch a job with the given name and parameters. + * + * @param name the name of the job to launch + * @return a representation of the {@link JobExecution} returned by a + * {@link JobLauncher}. + */ + String run(String name, String params); + + /** + * Stop all running jobs. + */ + void stop(); + + /** + * Enquire if any jobs launched here are still running. + * + * @return true if any jobs are running. + */ + boolean isRunning(); + + /** + * Query statistics of currently executing jobs. + * + * @return properties representing last known state of currently executing + * jobs + */ + public Properties getStatistics(); + +} diff --git a/spring-batch-execution/src/main/java/org/springframework/batch/execution/launch/support/JvmSystemExiter.java b/spring-batch-execution/src/main/java/org/springframework/batch/execution/launch/support/JvmSystemExiter.java index fd1329d9cb..bbd1b92780 100644 --- a/spring-batch-execution/src/main/java/org/springframework/batch/execution/launch/support/JvmSystemExiter.java +++ b/spring-batch-execution/src/main/java/org/springframework/batch/execution/launch/support/JvmSystemExiter.java @@ -1,40 +1,40 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.execution.launch.support; - -/** - * Implementation of the {@link SystemExiter} interface that calls the standards - * System.exit method. It should be noted that there will be no unit tests for - * this class, since there is only one line of actual code, that would only be - * testable by mocking System or Runtime. - * - * @author Lucas Ward - * @author Dave Syer - * - */ -public class JvmSystemExiter implements SystemExiter { - - /** - * Delegate call to System.exit() with the argument provided. Do not use - * this at home children! - * - * @see org.springframework.batch.execution.launch.support.SystemExiter#exit(int) - */ - public void exit(int status) { - System.exit(status); - } - -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.execution.launch.support; + +/** + * Implementation of the {@link SystemExiter} interface that calls the standards + * System.exit method. It should be noted that there will be no unit tests for + * this class, since there is only one line of actual code, that would only be + * testable by mocking System or Runtime. + * + * @author Lucas Ward + * @author Dave Syer + * + */ +public class JvmSystemExiter implements SystemExiter { + + /** + * Delegate call to System.exit() with the argument provided. Do not use + * this at home children! + * + * @see org.springframework.batch.execution.launch.support.SystemExiter#exit(int) + */ + public void exit(int status) { + System.exit(status); + } + +} diff --git a/spring-batch-execution/src/main/java/org/springframework/batch/execution/launch/support/SimpleJvmExitCodeMapper.java b/spring-batch-execution/src/main/java/org/springframework/batch/execution/launch/support/SimpleJvmExitCodeMapper.java index cfea7de706..65b5f8a301 100644 --- a/spring-batch-execution/src/main/java/org/springframework/batch/execution/launch/support/SimpleJvmExitCodeMapper.java +++ b/spring-batch-execution/src/main/java/org/springframework/batch/execution/launch/support/SimpleJvmExitCodeMapper.java @@ -1,88 +1,88 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.batch.execution.launch.support; - -import java.util.HashMap; -import java.util.Map; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.springframework.batch.repeat.ExitStatus; - - -/** - * An implementation of {@link ExitCodeMapper} that can be configured - * through a map from batch exit codes (String) to integer results. - * - * @author Stijn Maller - * @author Lucas Ward - * @author Dave Syer - */ - -public class SimpleJvmExitCodeMapper implements ExitCodeMapper { - - protected Log logger = LogFactory.getLog(getClass()); - - private Map mapping; - - public SimpleJvmExitCodeMapper(){ - mapping = new HashMap(); - mapping.put(ExitStatus.FINISHED.getExitCode(), - new Integer(JVM_EXITCODE_COMPLETED)); - mapping.put(ExitStatus.FAILED.getExitCode(), - new Integer(JVM_EXITCODE_GENERIC_ERROR)); - mapping.put(ExitCodeMapper.JOB_NOT_PROVIDED, - new Integer(JVM_EXITCODE_JOB_ERROR)); - mapping.put(ExitCodeMapper.NO_SUCH_JOB, - new Integer(JVM_EXITCODE_JOB_ERROR)); - } - - public Map getMapping() { - return mapping; - } - - /** - * Supply the ExitCodeMappings - * @param exitCodeMap A set of mappings between environment specific exit codes - * and batch framework internal exit codes - */ - public void setMapping(Map exitCodeMap) { - mapping.putAll(exitCodeMap); - } - - /** - * Get the JVM exitcode that matches a certain Batch Framework Exitcode - * @param exitCode The exitcode of the Batch Job as known by the Batch Framework - * @return The exitCode of the Batch Job as known by the JVM - */ - public int getExitCode(String exitCode) { - - Integer statusCode = null; - - try{ - statusCode = (Integer)mapping.get(exitCode); - } - catch(RuntimeException ex){ - //We still need to return an exit code, even if there is an issue with - //the mapper. - logger.fatal("Error mapping exit code, generic exit code returned.", ex); - } - - return (statusCode != null) ? statusCode.intValue() : JVM_EXITCODE_GENERIC_ERROR; - } - -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.batch.execution.launch.support; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.batch.repeat.ExitStatus; + + +/** + * An implementation of {@link ExitCodeMapper} that can be configured + * through a map from batch exit codes (String) to integer results. + * + * @author Stijn Maller + * @author Lucas Ward + * @author Dave Syer + */ + +public class SimpleJvmExitCodeMapper implements ExitCodeMapper { + + protected Log logger = LogFactory.getLog(getClass()); + + private Map mapping; + + public SimpleJvmExitCodeMapper(){ + mapping = new HashMap(); + mapping.put(ExitStatus.FINISHED.getExitCode(), + new Integer(JVM_EXITCODE_COMPLETED)); + mapping.put(ExitStatus.FAILED.getExitCode(), + new Integer(JVM_EXITCODE_GENERIC_ERROR)); + mapping.put(ExitCodeMapper.JOB_NOT_PROVIDED, + new Integer(JVM_EXITCODE_JOB_ERROR)); + mapping.put(ExitCodeMapper.NO_SUCH_JOB, + new Integer(JVM_EXITCODE_JOB_ERROR)); + } + + public Map getMapping() { + return mapping; + } + + /** + * Supply the ExitCodeMappings + * @param exitCodeMap A set of mappings between environment specific exit codes + * and batch framework internal exit codes + */ + public void setMapping(Map exitCodeMap) { + mapping.putAll(exitCodeMap); + } + + /** + * Get the JVM exitcode that matches a certain Batch Framework Exitcode + * @param exitCode The exitcode of the Batch Job as known by the Batch Framework + * @return The exitCode of the Batch Job as known by the JVM + */ + public int getExitCode(String exitCode) { + + Integer statusCode = null; + + try{ + statusCode = (Integer)mapping.get(exitCode); + } + catch(RuntimeException ex){ + //We still need to return an exit code, even if there is an issue with + //the mapper. + logger.fatal("Error mapping exit code, generic exit code returned.", ex); + } + + return (statusCode != null) ? statusCode.intValue() : JVM_EXITCODE_GENERIC_ERROR; + } + +} diff --git a/spring-batch-execution/src/main/java/org/springframework/batch/execution/launch/support/SystemExiter.java b/spring-batch-execution/src/main/java/org/springframework/batch/execution/launch/support/SystemExiter.java index 7f4d8bb327..34e97382f1 100644 --- a/spring-batch-execution/src/main/java/org/springframework/batch/execution/launch/support/SystemExiter.java +++ b/spring-batch-execution/src/main/java/org/springframework/batch/execution/launch/support/SystemExiter.java @@ -1,39 +1,39 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.execution.launch.support; - -/** - * Interface for exiting the JVM. This abstraction is only - * useful in order to allow classes that make System.exit calls - * to be testable, since calling System.exit during a unit - * test would cause the entire jvm to finish. - * - * @author Lucas Ward - * - */ -public interface SystemExiter { - - /** - * Terminate the currently running Java Virtual Machine. - * - * @param status exit status. - * @throws SecurityException - * if a security manager exists and its checkExit - * method doesn't allow exit with the specified status. - * @see System.exit - */ - void exit(int status); -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.execution.launch.support; + +/** + * Interface for exiting the JVM. This abstraction is only + * useful in order to allow classes that make System.exit calls + * to be testable, since calling System.exit during a unit + * test would cause the entire jvm to finish. + * + * @author Lucas Ward + * + */ +public interface SystemExiter { + + /** + * Terminate the currently running Java Virtual Machine. + * + * @param status exit status. + * @throws SecurityException + * if a security manager exists and its checkExit + * method doesn't allow exit with the specified status. + * @see System.exit + */ + void exit(int status); +} diff --git a/spring-batch-execution/src/main/java/org/springframework/batch/execution/repository/dao/AbstractJdbcBatchMetadataDao.java b/spring-batch-execution/src/main/java/org/springframework/batch/execution/repository/dao/AbstractJdbcBatchMetadataDao.java index 46fbe376fe..ab5239cc67 100644 --- a/spring-batch-execution/src/main/java/org/springframework/batch/execution/repository/dao/AbstractJdbcBatchMetadataDao.java +++ b/spring-batch-execution/src/main/java/org/springframework/batch/execution/repository/dao/AbstractJdbcBatchMetadataDao.java @@ -1,52 +1,52 @@ -package org.springframework.batch.execution.repository.dao; - -import org.springframework.beans.factory.InitializingBean; -import org.springframework.jdbc.core.JdbcOperations; -import org.springframework.util.Assert; -import org.springframework.util.StringUtils; - -/** - * Encapsulates common functionality needed by JDBC batch metadata DAOs - - * provides jdbcTemplate for subclasses and handles table prefixes. - * - * @author Robert Kasanicky - */ -public abstract class AbstractJdbcBatchMetadataDao implements InitializingBean { - - /** - * Default value for the table prefix property. - */ - public static final String DEFAULT_TABLE_PREFIX = "BATCH_"; - - private String tablePrefix = DEFAULT_TABLE_PREFIX; - - private JdbcOperations jdbcTemplate; - - protected String getQuery(String base) { - return StringUtils.replace(base, "%PREFIX%", tablePrefix); - } - - /** - * Public setter for the table prefix property. This will be prefixed to all - * the table names before queries are executed. Defaults to - * {@value #DEFAULT_TABLE_PREFIX}. - * - * @param tablePrefix the tablePrefix to set - */ - public void setTablePrefix(String tablePrefix) { - this.tablePrefix = tablePrefix; - } - - public void setJdbcTemplate(JdbcOperations jdbcTemplate) { - this.jdbcTemplate = jdbcTemplate; - } - - protected JdbcOperations getJdbcTemplate() { - return jdbcTemplate; - } - - public void afterPropertiesSet() throws Exception { - Assert.notNull(jdbcTemplate); - } - -} +package org.springframework.batch.execution.repository.dao; + +import org.springframework.beans.factory.InitializingBean; +import org.springframework.jdbc.core.JdbcOperations; +import org.springframework.util.Assert; +import org.springframework.util.StringUtils; + +/** + * Encapsulates common functionality needed by JDBC batch metadata DAOs - + * provides jdbcTemplate for subclasses and handles table prefixes. + * + * @author Robert Kasanicky + */ +public abstract class AbstractJdbcBatchMetadataDao implements InitializingBean { + + /** + * Default value for the table prefix property. + */ + public static final String DEFAULT_TABLE_PREFIX = "BATCH_"; + + private String tablePrefix = DEFAULT_TABLE_PREFIX; + + private JdbcOperations jdbcTemplate; + + protected String getQuery(String base) { + return StringUtils.replace(base, "%PREFIX%", tablePrefix); + } + + /** + * Public setter for the table prefix property. This will be prefixed to all + * the table names before queries are executed. Defaults to + * {@value #DEFAULT_TABLE_PREFIX}. + * + * @param tablePrefix the tablePrefix to set + */ + public void setTablePrefix(String tablePrefix) { + this.tablePrefix = tablePrefix; + } + + public void setJdbcTemplate(JdbcOperations jdbcTemplate) { + this.jdbcTemplate = jdbcTemplate; + } + + protected JdbcOperations getJdbcTemplate() { + return jdbcTemplate; + } + + public void afterPropertiesSet() throws Exception { + Assert.notNull(jdbcTemplate); + } + +} diff --git a/spring-batch-execution/src/main/java/org/springframework/batch/execution/repository/dao/JdbcJobExecutionDao.java b/spring-batch-execution/src/main/java/org/springframework/batch/execution/repository/dao/JdbcJobExecutionDao.java index 132f71a36f..66e995ceff 100644 --- a/spring-batch-execution/src/main/java/org/springframework/batch/execution/repository/dao/JdbcJobExecutionDao.java +++ b/spring-batch-execution/src/main/java/org/springframework/batch/execution/repository/dao/JdbcJobExecutionDao.java @@ -1,219 +1,219 @@ -package org.springframework.batch.execution.repository.dao; - -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Types; -import java.util.List; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.springframework.batch.core.domain.BatchStatus; -import org.springframework.batch.core.domain.JobExecution; -import org.springframework.batch.core.domain.JobInstance; -import org.springframework.batch.repeat.ExitStatus; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.jdbc.core.RowMapper; -import org.springframework.jdbc.support.incrementer.DataFieldMaxValueIncrementer; -import org.springframework.util.Assert; - -/** - * Jdbc implementation of {@link JobExecutionDao}. Uses sequences (via Spring's - * {@link DataFieldMaxValueIncrementer} abstraction) to create all primary keys - * before inserting a new row. Objects are checked to ensure all mandatory - * fields to be stored are not null. If any are found to be null, an - * IllegalArgumentException will be thrown. This could be left to JdbcTemplate, - * however, the exception will be fairly vague, and fails to highlight which - * field caused the exception. - * - * @author Lucas Ward - * @author Dave Syer - * @author Robert Kasanicky - */ -public class JdbcJobExecutionDao extends AbstractJdbcBatchMetadataDao implements JobExecutionDao, InitializingBean { - - private static final Log logger = LogFactory.getLog(JdbcJobExecutionDao.class); - - private static final int EXIT_MESSAGE_LENGTH = 250; - - private static final String GET_JOB_EXECUTION_COUNT = "SELECT count(JOB_EXECUTION_ID) from %PREFIX%JOB_EXECUTION " - + "where JOB_INSTANCE_ID = ?"; - - private static final String SAVE_JOB_EXECUTION = "INSERT into %PREFIX%JOB_EXECUTION(JOB_EXECUTION_ID, JOB_INSTANCE_ID, START_TIME, " - + "END_TIME, STATUS, CONTINUABLE, EXIT_CODE, EXIT_MESSAGE) values (?, ?, ?, ?, ?, ?, ?, ?)"; - - private static final String CHECK_JOB_EXECUTION_EXISTS = "SELECT COUNT(*) FROM %PREFIX%JOB_EXECUTION WHERE JOB_EXECUTION_ID = ?"; - - private static final String UPDATE_JOB_EXECUTION = "UPDATE %PREFIX%JOB_EXECUTION set START_TIME = ?, END_TIME = ?, " - + " STATUS = ?, CONTINUABLE = ?, EXIT_CODE = ?, EXIT_MESSAGE = ? where JOB_EXECUTION_ID = ?"; - - private static final String FIND_JOB_EXECUTIONS = "SELECT JOB_EXECUTION_ID, START_TIME, END_TIME, STATUS, CONTINUABLE, EXIT_CODE, EXIT_MESSAGE from %PREFIX%JOB_EXECUTION" - + " where JOB_INSTANCE_ID = ?"; - - private static final String GET_LAST_EXECUTION = "SELECT JOB_EXECUTION_ID, START_TIME, END_TIME, STATUS, CONTINUABLE, EXIT_CODE, EXIT_MESSAGE from %PREFIX%JOB_EXECUTION" - + " where JOB_INSTANCE_ID = ? and START_TIME = (SELECT max(START_TIME) from %PREFIX%JOB_EXECUTION where JOB_INSTANCE_ID = ?)"; - - private DataFieldMaxValueIncrementer jobExecutionIncrementer; - - public List findJobExecutions(final JobInstance job) { - - Assert.notNull(job, "Job cannot be null."); - Assert.notNull(job.getId(), "Job Id cannot be null."); - - return getJdbcTemplate().query(getQuery(FIND_JOB_EXECUTIONS), new Object[] { job.getId() }, - new JobExecutionRowMapper(job)); - } - - /** - * @see JobDao#getJobExecutionCount(JobInstance) - * @throws IllegalArgumentException if jobId is null. - */ - public int getJobExecutionCount(JobInstance jobInstance) { - Long jobId = jobInstance.getId(); - Assert.notNull(jobId, "JobId cannot be null"); - - Object[] parameters = new Object[] { jobId }; - - return getJdbcTemplate().queryForInt(getQuery(GET_JOB_EXECUTION_COUNT), parameters); - } - - /** - * - * SQL implementation using Sequences via the Spring incrementer - * abstraction. Once a new id has been obtained, the JobExecution is saved - * via a SQL INSERT statement. - * - * @see JobDao#saveJobExecution(JobExecution) - * @throws IllegalArgumentException if jobExecution is null, as well as any - * of it's fields to be persisted. - */ - public void saveJobExecution(JobExecution jobExecution) { - - validateJobExecution(jobExecution); - - jobExecution.setId(new Long(jobExecutionIncrementer.nextLongValue())); - Object[] parameters = new Object[] { jobExecution.getId(), jobExecution.getJobId(), - jobExecution.getStartTime(), jobExecution.getEndTime(), jobExecution.getStatus().toString(), - jobExecution.getExitStatus().isContinuable() ? "Y" : "N", jobExecution.getExitStatus().getExitCode(), - jobExecution.getExitStatus().getExitDescription() }; - getJdbcTemplate().update( - getQuery(SAVE_JOB_EXECUTION), - parameters, - new int[] { Types.INTEGER, Types.INTEGER, Types.TIMESTAMP, Types.TIMESTAMP, Types.VARCHAR, Types.CHAR, - Types.VARCHAR, Types.VARCHAR }); - } - - /** - * Validate JobExecution. At a minimum, JobId, StartTime, EndTime, and - * Status cannot be null. - * - * @param jobExecution - * @throws IllegalArgumentException - */ - private void validateJobExecution(JobExecution jobExecution) { - - Assert.notNull(jobExecution); - Assert.notNull(jobExecution.getJobId(), "JobExecution Job-Id cannot be null."); - Assert.notNull(jobExecution.getStatus(), "JobExecution status cannot be null."); - } - - /** - * Update given JobExecution using a SQL UPDATE statement. The JobExecution - * is first checked to ensure all fields are not null, and that it has an - * ID. The database is then queried to ensure that the ID exists, which - * ensures that it is valid. - * - * @see JobDao#updateJobExecution(JobExecution) - */ - public void updateJobExecution(JobExecution jobExecution) { - - validateJobExecution(jobExecution); - - String exitDescription = jobExecution.getExitStatus().getExitDescription(); - if (exitDescription != null && exitDescription.length() > EXIT_MESSAGE_LENGTH) { - exitDescription = exitDescription.substring(0, EXIT_MESSAGE_LENGTH); - logger.debug("Truncating long message before update of JobExecution: " + jobExecution); - } - Object[] parameters = new Object[] { jobExecution.getStartTime(), jobExecution.getEndTime(), - jobExecution.getStatus().toString(), jobExecution.getExitStatus().isContinuable() ? "Y" : "N", - jobExecution.getExitStatus().getExitCode(), exitDescription, jobExecution.getId() }; - - if (jobExecution.getId() == null) { - throw new IllegalArgumentException("JobExecution ID cannot be null. JobExecution must be saved " - + "before it can be updated."); - } - - // Check if given JobExecution's Id already exists, if none is found it - // is invalid and - // an exception should be thrown. - if (getJdbcTemplate().queryForInt(getQuery(CHECK_JOB_EXECUTION_EXISTS), new Object[] { jobExecution.getId() }) != 1) { - throw new NoSuchObjectException("Invalid JobExecution, ID " + jobExecution.getId() - + " not found."); - } - - getJdbcTemplate().update( - getQuery(UPDATE_JOB_EXECUTION), - parameters, - new int[] { Types.TIMESTAMP, Types.TIMESTAMP, Types.VARCHAR, Types.CHAR, Types.VARCHAR, Types.VARCHAR, - Types.INTEGER }); - } - - /** - * Setter for {@link DataFieldMaxValueIncrementer} to be used when - * generating primary keys for {@link JobExecution} instances. - * - * @param jobExecutionIncrementer the {@link DataFieldMaxValueIncrementer} - */ - public void setJobExecutionIncrementer(DataFieldMaxValueIncrementer jobExecutionIncrementer) { - this.jobExecutionIncrementer = jobExecutionIncrementer; - } - - public void afterPropertiesSet() throws Exception { - super.afterPropertiesSet(); - Assert.notNull(jobExecutionIncrementer); - } - - /** - * Re-usable mapper for {@link JobExecution} instances. - * - * @author Dave Syer - * - */ - private static class JobExecutionRowMapper implements RowMapper { - - private JobInstance job; - - public JobExecutionRowMapper(JobInstance job) { - super(); - this.job = job; - } - - public Object mapRow(ResultSet rs, int rowNum) throws SQLException { - JobExecution jobExecution = new JobExecution(job); - jobExecution.setId(new Long(rs.getLong(1))); - jobExecution.setStartTime(rs.getTimestamp(2)); - jobExecution.setEndTime(rs.getTimestamp(3)); - jobExecution.setStatus(BatchStatus.getStatus(rs.getString(4))); - jobExecution.setExitStatus(new ExitStatus("Y".equals(rs.getString(5)), rs.getString(6), rs.getString(7))); - return jobExecution; - } - - } - - public JobExecution getLastJobExecution(JobInstance jobInstance) { - - Long id = jobInstance.getId(); - - List executions = getJdbcTemplate().query(getQuery(GET_LAST_EXECUTION), new Object[] { id, id }, - new JobExecutionRowMapper(jobInstance)); - - Assert.state(executions.size() <= 1, "There must be at most one latest job execution"); - - if (executions.isEmpty()) { - return null; - } - else { - return (JobExecution) executions.get(0); - } - } - -} +package org.springframework.batch.execution.repository.dao; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Types; +import java.util.List; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.batch.core.domain.BatchStatus; +import org.springframework.batch.core.domain.JobExecution; +import org.springframework.batch.core.domain.JobInstance; +import org.springframework.batch.repeat.ExitStatus; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.jdbc.core.RowMapper; +import org.springframework.jdbc.support.incrementer.DataFieldMaxValueIncrementer; +import org.springframework.util.Assert; + +/** + * Jdbc implementation of {@link JobExecutionDao}. Uses sequences (via Spring's + * {@link DataFieldMaxValueIncrementer} abstraction) to create all primary keys + * before inserting a new row. Objects are checked to ensure all mandatory + * fields to be stored are not null. If any are found to be null, an + * IllegalArgumentException will be thrown. This could be left to JdbcTemplate, + * however, the exception will be fairly vague, and fails to highlight which + * field caused the exception. + * + * @author Lucas Ward + * @author Dave Syer + * @author Robert Kasanicky + */ +public class JdbcJobExecutionDao extends AbstractJdbcBatchMetadataDao implements JobExecutionDao, InitializingBean { + + private static final Log logger = LogFactory.getLog(JdbcJobExecutionDao.class); + + private static final int EXIT_MESSAGE_LENGTH = 250; + + private static final String GET_JOB_EXECUTION_COUNT = "SELECT count(JOB_EXECUTION_ID) from %PREFIX%JOB_EXECUTION " + + "where JOB_INSTANCE_ID = ?"; + + private static final String SAVE_JOB_EXECUTION = "INSERT into %PREFIX%JOB_EXECUTION(JOB_EXECUTION_ID, JOB_INSTANCE_ID, START_TIME, " + + "END_TIME, STATUS, CONTINUABLE, EXIT_CODE, EXIT_MESSAGE) values (?, ?, ?, ?, ?, ?, ?, ?)"; + + private static final String CHECK_JOB_EXECUTION_EXISTS = "SELECT COUNT(*) FROM %PREFIX%JOB_EXECUTION WHERE JOB_EXECUTION_ID = ?"; + + private static final String UPDATE_JOB_EXECUTION = "UPDATE %PREFIX%JOB_EXECUTION set START_TIME = ?, END_TIME = ?, " + + " STATUS = ?, CONTINUABLE = ?, EXIT_CODE = ?, EXIT_MESSAGE = ? where JOB_EXECUTION_ID = ?"; + + private static final String FIND_JOB_EXECUTIONS = "SELECT JOB_EXECUTION_ID, START_TIME, END_TIME, STATUS, CONTINUABLE, EXIT_CODE, EXIT_MESSAGE from %PREFIX%JOB_EXECUTION" + + " where JOB_INSTANCE_ID = ?"; + + private static final String GET_LAST_EXECUTION = "SELECT JOB_EXECUTION_ID, START_TIME, END_TIME, STATUS, CONTINUABLE, EXIT_CODE, EXIT_MESSAGE from %PREFIX%JOB_EXECUTION" + + " where JOB_INSTANCE_ID = ? and START_TIME = (SELECT max(START_TIME) from %PREFIX%JOB_EXECUTION where JOB_INSTANCE_ID = ?)"; + + private DataFieldMaxValueIncrementer jobExecutionIncrementer; + + public List findJobExecutions(final JobInstance job) { + + Assert.notNull(job, "Job cannot be null."); + Assert.notNull(job.getId(), "Job Id cannot be null."); + + return getJdbcTemplate().query(getQuery(FIND_JOB_EXECUTIONS), new Object[] { job.getId() }, + new JobExecutionRowMapper(job)); + } + + /** + * @see JobDao#getJobExecutionCount(JobInstance) + * @throws IllegalArgumentException if jobId is null. + */ + public int getJobExecutionCount(JobInstance jobInstance) { + Long jobId = jobInstance.getId(); + Assert.notNull(jobId, "JobId cannot be null"); + + Object[] parameters = new Object[] { jobId }; + + return getJdbcTemplate().queryForInt(getQuery(GET_JOB_EXECUTION_COUNT), parameters); + } + + /** + * + * SQL implementation using Sequences via the Spring incrementer + * abstraction. Once a new id has been obtained, the JobExecution is saved + * via a SQL INSERT statement. + * + * @see JobDao#saveJobExecution(JobExecution) + * @throws IllegalArgumentException if jobExecution is null, as well as any + * of it's fields to be persisted. + */ + public void saveJobExecution(JobExecution jobExecution) { + + validateJobExecution(jobExecution); + + jobExecution.setId(new Long(jobExecutionIncrementer.nextLongValue())); + Object[] parameters = new Object[] { jobExecution.getId(), jobExecution.getJobId(), + jobExecution.getStartTime(), jobExecution.getEndTime(), jobExecution.getStatus().toString(), + jobExecution.getExitStatus().isContinuable() ? "Y" : "N", jobExecution.getExitStatus().getExitCode(), + jobExecution.getExitStatus().getExitDescription() }; + getJdbcTemplate().update( + getQuery(SAVE_JOB_EXECUTION), + parameters, + new int[] { Types.INTEGER, Types.INTEGER, Types.TIMESTAMP, Types.TIMESTAMP, Types.VARCHAR, Types.CHAR, + Types.VARCHAR, Types.VARCHAR }); + } + + /** + * Validate JobExecution. At a minimum, JobId, StartTime, EndTime, and + * Status cannot be null. + * + * @param jobExecution + * @throws IllegalArgumentException + */ + private void validateJobExecution(JobExecution jobExecution) { + + Assert.notNull(jobExecution); + Assert.notNull(jobExecution.getJobId(), "JobExecution Job-Id cannot be null."); + Assert.notNull(jobExecution.getStatus(), "JobExecution status cannot be null."); + } + + /** + * Update given JobExecution using a SQL UPDATE statement. The JobExecution + * is first checked to ensure all fields are not null, and that it has an + * ID. The database is then queried to ensure that the ID exists, which + * ensures that it is valid. + * + * @see JobDao#updateJobExecution(JobExecution) + */ + public void updateJobExecution(JobExecution jobExecution) { + + validateJobExecution(jobExecution); + + String exitDescription = jobExecution.getExitStatus().getExitDescription(); + if (exitDescription != null && exitDescription.length() > EXIT_MESSAGE_LENGTH) { + exitDescription = exitDescription.substring(0, EXIT_MESSAGE_LENGTH); + logger.debug("Truncating long message before update of JobExecution: " + jobExecution); + } + Object[] parameters = new Object[] { jobExecution.getStartTime(), jobExecution.getEndTime(), + jobExecution.getStatus().toString(), jobExecution.getExitStatus().isContinuable() ? "Y" : "N", + jobExecution.getExitStatus().getExitCode(), exitDescription, jobExecution.getId() }; + + if (jobExecution.getId() == null) { + throw new IllegalArgumentException("JobExecution ID cannot be null. JobExecution must be saved " + + "before it can be updated."); + } + + // Check if given JobExecution's Id already exists, if none is found it + // is invalid and + // an exception should be thrown. + if (getJdbcTemplate().queryForInt(getQuery(CHECK_JOB_EXECUTION_EXISTS), new Object[] { jobExecution.getId() }) != 1) { + throw new NoSuchObjectException("Invalid JobExecution, ID " + jobExecution.getId() + + " not found."); + } + + getJdbcTemplate().update( + getQuery(UPDATE_JOB_EXECUTION), + parameters, + new int[] { Types.TIMESTAMP, Types.TIMESTAMP, Types.VARCHAR, Types.CHAR, Types.VARCHAR, Types.VARCHAR, + Types.INTEGER }); + } + + /** + * Setter for {@link DataFieldMaxValueIncrementer} to be used when + * generating primary keys for {@link JobExecution} instances. + * + * @param jobExecutionIncrementer the {@link DataFieldMaxValueIncrementer} + */ + public void setJobExecutionIncrementer(DataFieldMaxValueIncrementer jobExecutionIncrementer) { + this.jobExecutionIncrementer = jobExecutionIncrementer; + } + + public void afterPropertiesSet() throws Exception { + super.afterPropertiesSet(); + Assert.notNull(jobExecutionIncrementer); + } + + /** + * Re-usable mapper for {@link JobExecution} instances. + * + * @author Dave Syer + * + */ + private static class JobExecutionRowMapper implements RowMapper { + + private JobInstance job; + + public JobExecutionRowMapper(JobInstance job) { + super(); + this.job = job; + } + + public Object mapRow(ResultSet rs, int rowNum) throws SQLException { + JobExecution jobExecution = new JobExecution(job); + jobExecution.setId(new Long(rs.getLong(1))); + jobExecution.setStartTime(rs.getTimestamp(2)); + jobExecution.setEndTime(rs.getTimestamp(3)); + jobExecution.setStatus(BatchStatus.getStatus(rs.getString(4))); + jobExecution.setExitStatus(new ExitStatus("Y".equals(rs.getString(5)), rs.getString(6), rs.getString(7))); + return jobExecution; + } + + } + + public JobExecution getLastJobExecution(JobInstance jobInstance) { + + Long id = jobInstance.getId(); + + List executions = getJdbcTemplate().query(getQuery(GET_LAST_EXECUTION), new Object[] { id, id }, + new JobExecutionRowMapper(jobInstance)); + + Assert.state(executions.size() <= 1, "There must be at most one latest job execution"); + + if (executions.isEmpty()) { + return null; + } + else { + return (JobExecution) executions.get(0); + } + } + +} diff --git a/spring-batch-execution/src/main/java/org/springframework/batch/execution/repository/dao/JdbcJobInstanceDao.java b/spring-batch-execution/src/main/java/org/springframework/batch/execution/repository/dao/JdbcJobInstanceDao.java index d3e1c45510..31f874dd0b 100644 --- a/spring-batch-execution/src/main/java/org/springframework/batch/execution/repository/dao/JdbcJobInstanceDao.java +++ b/spring-batch-execution/src/main/java/org/springframework/batch/execution/repository/dao/JdbcJobInstanceDao.java @@ -1,236 +1,236 @@ -package org.springframework.batch.execution.repository.dao; - -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Timestamp; -import java.sql.Types; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; - -import org.springframework.batch.core.domain.Job; -import org.springframework.batch.core.domain.JobInstance; -import org.springframework.batch.core.domain.JobParameters; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.jdbc.core.RowMapper; -import org.springframework.jdbc.support.incrementer.DataFieldMaxValueIncrementer; -import org.springframework.util.Assert; - -/** - * Jdbc implementation of {@link JobInstanceDao}. Uses sequences (via Spring's - * {@link DataFieldMaxValueIncrementer} abstraction) to create all primary keys - * before inserting a new row. Objects are checked to ensure all mandatory - * fields to be stored are not null. If any are found to be null, an - * IllegalArgumentException will be thrown. This could be left to JdbcTemplate, - * however, the exception will be fairly vague, and fails to highlight which - * field caused the exception. - * - * @author Lucas Ward - * @author Dave Syer - * @author Robert Kasanicky - */ -public class JdbcJobInstanceDao extends AbstractJdbcBatchMetadataDao implements JobInstanceDao, InitializingBean { - - private static final String CREATE_JOB_INSTANCE = "INSERT into %PREFIX%JOB_INSTANCE(JOB_INSTANCE_ID, JOB_NAME, JOB_KEY)" - + " values (?, ?, ?)"; - - private static final String CREATE_JOB_PARAMETERS = "INSERT into %PREFIX%JOB_PARAMS(JOB_INSTANCE_ID, KEY_NAME, TYPE_CD, " - + "STRING_VAL, DATE_VAL, LONG_VAL, DOUBLE_VAL) values (?, ?, ?, ?, ?, ?, ?)"; - - private static final String FIND_JOBS = "SELECT JOB_INSTANCE_ID from %PREFIX%JOB_INSTANCE where JOB_NAME = ? and JOB_KEY = ?"; - - private DataFieldMaxValueIncrementer jobIncrementer; - - /** - * In this jdbc implementation a job id is obtained by asking the - * jobIncrementer (which is likely a sequence) for the nextLong, and then - * passing the Id and parameter values into an INSERT statement. - * - * @see JobDao#createJob(JobIdentifier) - * @throws IllegalArgumentException if any {@link JobIdentifier} fields are - * null. - */ - public JobInstance createJobInstance(Job job, JobParameters jobParameters) { - - Assert.notNull(job, "Job must not be null."); - Assert.hasLength(job.getName(), "Job must have a name"); - Assert.notNull(jobParameters, "JobParameters must not be null."); - - Assert.state(getJobInstance(job, jobParameters) == null, "JobInstance must not already exist"); - - Long jobId = new Long(jobIncrementer.nextLongValue()); - Object[] parameters = new Object[] { jobId, job.getName(), createJobKey(jobParameters) }; - getJdbcTemplate().update(getQuery(CREATE_JOB_INSTANCE), parameters, - new int[] { Types.INTEGER, Types.VARCHAR, Types.VARCHAR }); - - insertJobParameters(jobId, jobParameters); - - JobInstance jobInstance = new JobInstance(jobId, jobParameters, job); - return jobInstance; - } - - private String createJobKey(JobParameters jobParameters) { - - Map props = jobParameters.getParameters(); - StringBuffer stringBuffer = new StringBuffer(); - for (Iterator it = props.entrySet().iterator(); it.hasNext();) { - Entry entry = (Entry) it.next(); - stringBuffer.append(entry.toString() + ";"); - } - - return stringBuffer.toString(); - } - - /** - * Convenience method that inserts all parameters from the provided - * JobParameters. - * - */ - private void insertJobParameters(Long jobId, JobParameters jobParameters) { - - Map parameters = jobParameters.getStringParameters(); - - if (!parameters.isEmpty()) { - for (Iterator it = parameters.entrySet().iterator(); it.hasNext();) { - Entry entry = (Entry) it.next(); - insertParameter(jobId, ParameterType.STRING, entry.getKey().toString(), entry.getValue()); - } - } - - parameters = jobParameters.getLongParameters(); - - if (!parameters.isEmpty()) { - for (Iterator it = parameters.entrySet().iterator(); it.hasNext();) { - Entry entry = (Entry) it.next(); - insertParameter(jobId, ParameterType.LONG, entry.getKey().toString(), entry.getValue()); - } - } - - parameters = jobParameters.getDoubleParameters(); - - if (!parameters.isEmpty()) { - for (Iterator it = parameters.entrySet().iterator(); it.hasNext();) { - Entry entry = (Entry) it.next(); - insertParameter(jobId, ParameterType.DOUBLE, entry.getKey().toString(), entry.getValue()); - } - } - - parameters = jobParameters.getDateParameters(); - - if (!parameters.isEmpty()) { - for (Iterator it = parameters.entrySet().iterator(); it.hasNext();) { - Entry entry = (Entry) it.next(); - insertParameter(jobId, ParameterType.DATE, entry.getKey().toString(), entry.getValue()); - } - } - } - - /** - * Convenience method that inserts an individual records into the - * JobParameters table. - */ - private void insertParameter(Long jobId, ParameterType type, String key, Object value) { - - Object[] args = new Object[0]; - int[] argTypes = new int[] { Types.INTEGER, Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.TIMESTAMP, - Types.INTEGER, Types.DOUBLE }; - - if (type == ParameterType.STRING) { - args = new Object[] { jobId, key, type, value, new Timestamp(0L), new Long(0), new Double(0) }; - } - else if (type == ParameterType.LONG) { - args = new Object[] { jobId, key, type, "", new Timestamp(0L), value, new Double(0) }; - } - else if (type == ParameterType.DOUBLE) { - args = new Object[] { jobId, key, type, "", new Timestamp(0L), new Long(0), value }; - } - else if (type == ParameterType.DATE) { - args = new Object[] { jobId, key, type, "", value, new Long(0), new Double(0) }; - } - - getJdbcTemplate().update(getQuery(CREATE_JOB_PARAMETERS), args, argTypes); - } - - /** - * The job table is queried for any jobs that match the - * given identifier, adding them to a list via the RowMapper callback. - * - * @see JobDao#findJobInstances(JobIdentifier) - * @throws IllegalArgumentException if any {@link JobIdentifier} fields are - * null. - */ - public JobInstance getJobInstance(final Job job, final JobParameters jobParameters) { - - Assert.notNull(job, "Job must not be null."); - Assert.hasLength(job.getName(), "Job must have a name"); - Assert.notNull(jobParameters, "JobParameters must not be null."); - - Object[] parameters = new Object[] { job.getName(), createJobKey(jobParameters) }; - - RowMapper rowMapper = new RowMapper() { - public Object mapRow(ResultSet rs, int rowNum) throws SQLException { - JobInstance jobInstance = new JobInstance(new Long(rs.getLong(1)), jobParameters, job); - return jobInstance; - } - }; - - List instances = getJdbcTemplate().query(getQuery(FIND_JOBS), parameters, rowMapper); - - if (instances.isEmpty()) { - return null; - } else { - Assert.state(instances.size() == 1); - return (JobInstance) instances.get(0); - } - } - - /** - * Setter for {@link DataFieldMaxValueIncrementer} to be used when - * generating primary keys for {@link JobInstance} instances. - * - * @param jobIncrementer the {@link DataFieldMaxValueIncrementer} - */ - public void setJobIncrementer(DataFieldMaxValueIncrementer jobIncrementer) { - this.jobIncrementer = jobIncrementer; - } - - public void afterPropertiesSet() throws Exception { - super.afterPropertiesSet(); - Assert.notNull(jobIncrementer); - } - - private static class ParameterType { - - private final String type; - - private ParameterType(String type) { - this.type = type; - } - - public String toString() { - return type; - } - - public static final ParameterType STRING = new ParameterType("STRING"); - - public static final ParameterType DATE = new ParameterType("DATE"); - - public static final ParameterType LONG = new ParameterType("LONG"); - - public static final ParameterType DOUBLE = new ParameterType("DOUBLE"); - - private static final ParameterType[] VALUES = { STRING, DATE, LONG, DOUBLE }; - - public static ParameterType getType(String typeAsString) { - - for (int i = 0; i < VALUES.length; i++) { - if (VALUES[i].toString().equals(typeAsString)) { - return (ParameterType) VALUES[i]; - } - } - - return null; - } - } -} +package org.springframework.batch.execution.repository.dao; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Timestamp; +import java.sql.Types; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import org.springframework.batch.core.domain.Job; +import org.springframework.batch.core.domain.JobInstance; +import org.springframework.batch.core.domain.JobParameters; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.jdbc.core.RowMapper; +import org.springframework.jdbc.support.incrementer.DataFieldMaxValueIncrementer; +import org.springframework.util.Assert; + +/** + * Jdbc implementation of {@link JobInstanceDao}. Uses sequences (via Spring's + * {@link DataFieldMaxValueIncrementer} abstraction) to create all primary keys + * before inserting a new row. Objects are checked to ensure all mandatory + * fields to be stored are not null. If any are found to be null, an + * IllegalArgumentException will be thrown. This could be left to JdbcTemplate, + * however, the exception will be fairly vague, and fails to highlight which + * field caused the exception. + * + * @author Lucas Ward + * @author Dave Syer + * @author Robert Kasanicky + */ +public class JdbcJobInstanceDao extends AbstractJdbcBatchMetadataDao implements JobInstanceDao, InitializingBean { + + private static final String CREATE_JOB_INSTANCE = "INSERT into %PREFIX%JOB_INSTANCE(JOB_INSTANCE_ID, JOB_NAME, JOB_KEY)" + + " values (?, ?, ?)"; + + private static final String CREATE_JOB_PARAMETERS = "INSERT into %PREFIX%JOB_PARAMS(JOB_INSTANCE_ID, KEY_NAME, TYPE_CD, " + + "STRING_VAL, DATE_VAL, LONG_VAL, DOUBLE_VAL) values (?, ?, ?, ?, ?, ?, ?)"; + + private static final String FIND_JOBS = "SELECT JOB_INSTANCE_ID from %PREFIX%JOB_INSTANCE where JOB_NAME = ? and JOB_KEY = ?"; + + private DataFieldMaxValueIncrementer jobIncrementer; + + /** + * In this jdbc implementation a job id is obtained by asking the + * jobIncrementer (which is likely a sequence) for the nextLong, and then + * passing the Id and parameter values into an INSERT statement. + * + * @see JobDao#createJob(JobIdentifier) + * @throws IllegalArgumentException if any {@link JobIdentifier} fields are + * null. + */ + public JobInstance createJobInstance(Job job, JobParameters jobParameters) { + + Assert.notNull(job, "Job must not be null."); + Assert.hasLength(job.getName(), "Job must have a name"); + Assert.notNull(jobParameters, "JobParameters must not be null."); + + Assert.state(getJobInstance(job, jobParameters) == null, "JobInstance must not already exist"); + + Long jobId = new Long(jobIncrementer.nextLongValue()); + Object[] parameters = new Object[] { jobId, job.getName(), createJobKey(jobParameters) }; + getJdbcTemplate().update(getQuery(CREATE_JOB_INSTANCE), parameters, + new int[] { Types.INTEGER, Types.VARCHAR, Types.VARCHAR }); + + insertJobParameters(jobId, jobParameters); + + JobInstance jobInstance = new JobInstance(jobId, jobParameters, job); + return jobInstance; + } + + private String createJobKey(JobParameters jobParameters) { + + Map props = jobParameters.getParameters(); + StringBuffer stringBuffer = new StringBuffer(); + for (Iterator it = props.entrySet().iterator(); it.hasNext();) { + Entry entry = (Entry) it.next(); + stringBuffer.append(entry.toString() + ";"); + } + + return stringBuffer.toString(); + } + + /** + * Convenience method that inserts all parameters from the provided + * JobParameters. + * + */ + private void insertJobParameters(Long jobId, JobParameters jobParameters) { + + Map parameters = jobParameters.getStringParameters(); + + if (!parameters.isEmpty()) { + for (Iterator it = parameters.entrySet().iterator(); it.hasNext();) { + Entry entry = (Entry) it.next(); + insertParameter(jobId, ParameterType.STRING, entry.getKey().toString(), entry.getValue()); + } + } + + parameters = jobParameters.getLongParameters(); + + if (!parameters.isEmpty()) { + for (Iterator it = parameters.entrySet().iterator(); it.hasNext();) { + Entry entry = (Entry) it.next(); + insertParameter(jobId, ParameterType.LONG, entry.getKey().toString(), entry.getValue()); + } + } + + parameters = jobParameters.getDoubleParameters(); + + if (!parameters.isEmpty()) { + for (Iterator it = parameters.entrySet().iterator(); it.hasNext();) { + Entry entry = (Entry) it.next(); + insertParameter(jobId, ParameterType.DOUBLE, entry.getKey().toString(), entry.getValue()); + } + } + + parameters = jobParameters.getDateParameters(); + + if (!parameters.isEmpty()) { + for (Iterator it = parameters.entrySet().iterator(); it.hasNext();) { + Entry entry = (Entry) it.next(); + insertParameter(jobId, ParameterType.DATE, entry.getKey().toString(), entry.getValue()); + } + } + } + + /** + * Convenience method that inserts an individual records into the + * JobParameters table. + */ + private void insertParameter(Long jobId, ParameterType type, String key, Object value) { + + Object[] args = new Object[0]; + int[] argTypes = new int[] { Types.INTEGER, Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.TIMESTAMP, + Types.INTEGER, Types.DOUBLE }; + + if (type == ParameterType.STRING) { + args = new Object[] { jobId, key, type, value, new Timestamp(0L), new Long(0), new Double(0) }; + } + else if (type == ParameterType.LONG) { + args = new Object[] { jobId, key, type, "", new Timestamp(0L), value, new Double(0) }; + } + else if (type == ParameterType.DOUBLE) { + args = new Object[] { jobId, key, type, "", new Timestamp(0L), new Long(0), value }; + } + else if (type == ParameterType.DATE) { + args = new Object[] { jobId, key, type, "", value, new Long(0), new Double(0) }; + } + + getJdbcTemplate().update(getQuery(CREATE_JOB_PARAMETERS), args, argTypes); + } + + /** + * The job table is queried for any jobs that match the + * given identifier, adding them to a list via the RowMapper callback. + * + * @see JobDao#findJobInstances(JobIdentifier) + * @throws IllegalArgumentException if any {@link JobIdentifier} fields are + * null. + */ + public JobInstance getJobInstance(final Job job, final JobParameters jobParameters) { + + Assert.notNull(job, "Job must not be null."); + Assert.hasLength(job.getName(), "Job must have a name"); + Assert.notNull(jobParameters, "JobParameters must not be null."); + + Object[] parameters = new Object[] { job.getName(), createJobKey(jobParameters) }; + + RowMapper rowMapper = new RowMapper() { + public Object mapRow(ResultSet rs, int rowNum) throws SQLException { + JobInstance jobInstance = new JobInstance(new Long(rs.getLong(1)), jobParameters, job); + return jobInstance; + } + }; + + List instances = getJdbcTemplate().query(getQuery(FIND_JOBS), parameters, rowMapper); + + if (instances.isEmpty()) { + return null; + } else { + Assert.state(instances.size() == 1); + return (JobInstance) instances.get(0); + } + } + + /** + * Setter for {@link DataFieldMaxValueIncrementer} to be used when + * generating primary keys for {@link JobInstance} instances. + * + * @param jobIncrementer the {@link DataFieldMaxValueIncrementer} + */ + public void setJobIncrementer(DataFieldMaxValueIncrementer jobIncrementer) { + this.jobIncrementer = jobIncrementer; + } + + public void afterPropertiesSet() throws Exception { + super.afterPropertiesSet(); + Assert.notNull(jobIncrementer); + } + + private static class ParameterType { + + private final String type; + + private ParameterType(String type) { + this.type = type; + } + + public String toString() { + return type; + } + + public static final ParameterType STRING = new ParameterType("STRING"); + + public static final ParameterType DATE = new ParameterType("DATE"); + + public static final ParameterType LONG = new ParameterType("LONG"); + + public static final ParameterType DOUBLE = new ParameterType("DOUBLE"); + + private static final ParameterType[] VALUES = { STRING, DATE, LONG, DOUBLE }; + + public static ParameterType getType(String typeAsString) { + + for (int i = 0; i < VALUES.length; i++) { + if (VALUES[i].toString().equals(typeAsString)) { + return (ParameterType) VALUES[i]; + } + } + + return null; + } + } +} diff --git a/spring-batch-execution/src/main/java/org/springframework/batch/execution/repository/dao/JdbcStepExecutionDao.java b/spring-batch-execution/src/main/java/org/springframework/batch/execution/repository/dao/JdbcStepExecutionDao.java index 21e3f4dce8..9ed8a84b5f 100644 --- a/spring-batch-execution/src/main/java/org/springframework/batch/execution/repository/dao/JdbcStepExecutionDao.java +++ b/spring-batch-execution/src/main/java/org/springframework/batch/execution/repository/dao/JdbcStepExecutionDao.java @@ -1,425 +1,425 @@ -package org.springframework.batch.execution.repository.dao; - -import java.io.Serializable; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Types; -import java.util.Iterator; -import java.util.List; -import java.util.Map.Entry; - -import org.apache.commons.lang.SerializationUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.springframework.batch.core.domain.BatchStatus; -import org.springframework.batch.core.domain.JobExecution; -import org.springframework.batch.core.domain.Step; -import org.springframework.batch.core.domain.StepExecution; -import org.springframework.batch.io.exception.InfrastructureException; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.repeat.ExitStatus; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.dao.DataAccessException; -import org.springframework.dao.OptimisticLockingFailureException; -import org.springframework.jdbc.core.PreparedStatementCallback; -import org.springframework.jdbc.core.RowCallbackHandler; -import org.springframework.jdbc.core.RowMapper; -import org.springframework.jdbc.core.support.AbstractLobCreatingPreparedStatementCallback; -import org.springframework.jdbc.support.incrementer.DataFieldMaxValueIncrementer; -import org.springframework.jdbc.support.lob.DefaultLobHandler; -import org.springframework.jdbc.support.lob.LobCreator; -import org.springframework.jdbc.support.lob.LobHandler; -import org.springframework.util.Assert; - -/** - * Jdbc implementation of {@link StepExecutionDao}.
- * - * Allows customization of the tables names used by Spring Batch for step meta - * data via a prefix property.
- * - * Uses sequences or tables (via Spring's {@link DataFieldMaxValueIncrementer} - * abstraction) to create all primary keys before inserting a new row. All - * objects are checked to ensure all fields to be stored are not null. If any - * are found to be null, an IllegalArgumentException will be thrown. This could - * be left to JdbcTemplate, however, the exception will be fairly vague, and - * fails to highlight which field caused the exception.
- * - * @author Lucas Ward - * @author Dave Syer - * @author Robert Kasanicky - * - * @see StepExecutionDao - */ -public class JdbcStepExecutionDao extends AbstractJdbcBatchMetadataDao implements StepExecutionDao, InitializingBean { - - private static final Log logger = LogFactory.getLog(JdbcStepExecutionDao.class); - - private static final String FIND_STEP_EXECUTION_CONTEXT = "SELECT TYPE_CD, KEY_NAME, STRING_VAL, DOUBLE_VAL, LONG_VAL, OBJECT_VAL " - + "from %PREFIX%STEP_EXECUTION_CONTEXT where STEP_EXECUTION_ID = ?"; - - private static final String INSERT_STEP_EXECUTION_CONTEXT = "INSERT into %PREFIX%STEP_EXECUTION_CONTEXT(STEP_EXECUTION_ID, TYPE_CD," - + " KEY_NAME, STRING_VAL, DOUBLE_VAL, LONG_VAL, OBJECT_VAL) values(?,?,?,?,?,?,?)"; - - private static final String SAVE_STEP_EXECUTION = "INSERT into %PREFIX%STEP_EXECUTION(STEP_EXECUTION_ID, VERSION, STEP_NAME, JOB_EXECUTION_ID, START_TIME, " - + "END_TIME, STATUS, COMMIT_COUNT, TASK_COUNT, CONTINUABLE, EXIT_CODE, EXIT_MESSAGE) " - + "values(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; - - private static final String UPDATE_STEP_EXECUTION_CONTEXT = "UPDATE %PREFIX%STEP_EXECUTION_CONTEXT set " - + "TYPE_CD = ?, STRING_VAL = ?, DOUBLE_VAL = ?, LONG_VAL = ?, OBJECT_VAL = ? where STEP_EXECUTION_ID = ? and KEY_NAME = ?"; - - private static final String UPDATE_STEP_EXECUTION = "UPDATE %PREFIX%STEP_EXECUTION set START_TIME = ?, END_TIME = ?, " - + "STATUS = ?, COMMIT_COUNT = ?, TASK_COUNT = ?, CONTINUABLE = ? , EXIT_CODE = ?, " - + "EXIT_MESSAGE = ?, VERSION = ? where STEP_EXECUTION_ID = ? and VERSION = ?"; - - private static final String GET_STEP_EXECUTION = "SELECT STEP_EXECUTION_ID, STEP_NAME, START_TIME, END_TIME, STATUS, COMMIT_COUNT," - + " TASK_COUNT, CONTINUABLE, EXIT_CODE, EXIT_MESSAGE from %PREFIX%STEP_EXECUTION where STEP_NAME = ? and JOB_EXECUTION_ID = ?"; - - private static final String CURRENT_VERSION_STEP_EXECUTION = "SELECT VERSION FROM %PREFIX%STEP_EXECUTION WHERE STEP_EXECUTION_ID=?"; - - private static final int EXIT_MESSAGE_LENGTH = 250; - - private LobHandler lobHandler = new DefaultLobHandler(); - - private DataFieldMaxValueIncrementer stepExecutionIncrementer; - - public ExecutionContext findExecutionContext(final StepExecution stepExecution) { - - final Long executionId = stepExecution.getId(); - Assert.notNull(executionId, "ExecutionId must not be null."); - - final ExecutionContext executionContext = new ExecutionContext(); - - RowCallbackHandler callback = new RowCallbackHandler() { - - public void processRow(ResultSet rs) throws SQLException { - - String typeCd = rs.getString("TYPE_CD"); - AttributeType type = AttributeType.getType(typeCd); - String key = rs.getString("KEY_NAME"); - if (type == AttributeType.STRING) { - executionContext.putString(key, rs.getString("STRING_VAL")); - } - else if (type == AttributeType.LONG) { - executionContext.putLong(key, rs.getLong("LONG_VAL")); - } - else if (type == AttributeType.DOUBLE) { - executionContext.putDouble(key, rs.getDouble("DOUBLE_VAL")); - } - else if (type == AttributeType.OBJECT) { - executionContext.put(key, rs.getObject("OBJECT_VAL")); - } - else { - throw new InfrastructureException("Invalid type found: [" + typeCd + "] for execution id: [" - + executionId + "]"); - } - } - }; - - getJdbcTemplate().query(getQuery(FIND_STEP_EXECUTION_CONTEXT), new Object[] { executionId }, callback); - - return executionContext; - } - - private void insertExecutionAttribute(final Long executionId, final String key, final Object value, - final AttributeType type) { - PreparedStatementCallback callback = new AbstractLobCreatingPreparedStatementCallback(lobHandler) { - - protected void setValues(PreparedStatement ps, LobCreator lobCreator) throws SQLException, - DataAccessException { - - ps.setLong(1, executionId.longValue()); - ps.setString(3, key); - if (type == AttributeType.STRING) { - ps.setString(2, AttributeType.STRING.toString()); - ps.setString(4, value.toString()); - ps.setDouble(5, 0.0); - ps.setLong(6, 0); - lobCreator.setBlobAsBytes(ps, 7, null); - } - else if (type == AttributeType.DOUBLE) { - ps.setString(2, AttributeType.DOUBLE.toString()); - ps.setString(4, null); - ps.setDouble(5, ((Double) value).doubleValue()); - ps.setLong(6, 0); - lobCreator.setBlobAsBytes(ps, 7, null); - } - else if (type == AttributeType.LONG) { - ps.setString(2, AttributeType.LONG.toString()); - ps.setString(4, null); - ps.setDouble(5, 0.0); - ps.setLong(6, ((Long) value).longValue()); - lobCreator.setBlobAsBytes(ps, 7, null); - } - else { - ps.setString(2, AttributeType.OBJECT.toString()); - ps.setString(4, null); - ps.setDouble(5, 0.0); - ps.setLong(6, 0); - lobCreator.setBlobAsBytes(ps, 7, SerializationUtils.serialize((Serializable) value)); - } - } - }; - getJdbcTemplate().execute(getQuery(INSERT_STEP_EXECUTION_CONTEXT), callback); - } - - /** - * Save a StepExecution. A unique id will be generated by the - * stepExecutionIncrementor, and then set in the StepExecution. All values - * will then be stored via an INSERT statement. - * - * @see StepDao#saveStepExecution(StepExecution) - */ - public void saveStepExecution(StepExecution stepExecution) { - - validateStepExecution(stepExecution); - - stepExecution.setId(new Long(stepExecutionIncrementer.nextLongValue())); - stepExecution.incrementVersion(); // should be 0 now - Object[] parameters = new Object[] { stepExecution.getId(), stepExecution.getVersion(), - stepExecution.getStepName(), stepExecution.getJobExecutionId(), stepExecution.getStartTime(), - stepExecution.getEndTime(), stepExecution.getStatus().toString(), stepExecution.getCommitCount(), - stepExecution.getTaskCount(), stepExecution.getExitStatus().isContinuable() ? "Y" : "N", - stepExecution.getExitStatus().getExitCode(), stepExecution.getExitStatus().getExitDescription() }; - getJdbcTemplate().update( - getQuery(SAVE_STEP_EXECUTION), - parameters, - new int[] { Types.INTEGER, Types.INTEGER, Types.VARCHAR, Types.INTEGER, Types.TIMESTAMP, - Types.TIMESTAMP, Types.VARCHAR, Types.INTEGER, Types.INTEGER, Types.CHAR, Types.VARCHAR, - Types.VARCHAR }); - } - - /** - * Validate StepExecution. At a minimum, JobId, StartTime, and Status cannot - * be null. EndTime can be null for an unfinished job. - * - * @param jobExecution - * @throws IllegalArgumentException - */ - private void validateStepExecution(StepExecution stepExecution) { - Assert.notNull(stepExecution); - Assert.notNull(stepExecution.getStepName(), "StepExecution step name cannot be null."); - Assert.notNull(stepExecution.getStartTime(), "StepExecution start time cannot be null."); - Assert.notNull(stepExecution.getStatus(), "StepExecution status cannot be null."); - } - - /** - * Save or update execution attributes. A lob creator must be used, since - * any attributes that don't match a provided type must be serialized into a - * blob. - * - * @see {@link LobCreator} - */ - public void saveOrUpdateExecutionContext(final StepExecution stepExecution) { - - Long executionId = stepExecution.getId(); - ExecutionContext executionContext = stepExecution.getExecutionContext(); - Assert.notNull(executionId, "ExecutionId must not be null."); - Assert.notNull(executionContext, "The ExecutionContext must not be null."); - - for (Iterator it = executionContext.entrySet().iterator(); it.hasNext();) { - Entry entry = (Entry) it.next(); - final String key = entry.getKey().toString(); - final Object value = entry.getValue(); - - if (value instanceof String) { - updateExecutionAttribute(executionId, key, value, AttributeType.STRING); - } - else if (value instanceof Double) { - updateExecutionAttribute(executionId, key, value, AttributeType.DOUBLE); - } - else if (value instanceof Long) { - updateExecutionAttribute(executionId, key, value, AttributeType.LONG); - } - else { - updateExecutionAttribute(executionId, key, value, AttributeType.OBJECT); - } - } - } - - private void updateExecutionAttribute(final Long executionId, final String key, final Object value, - final AttributeType type) { - - PreparedStatementCallback callback = new AbstractLobCreatingPreparedStatementCallback(lobHandler) { - - protected void setValues(PreparedStatement ps, LobCreator lobCreator) throws SQLException, - DataAccessException { - - ps.setLong(6, executionId.longValue()); - ps.setString(7, key); - if (type == AttributeType.STRING) { - ps.setString(1, AttributeType.STRING.toString()); - ps.setString(2, value.toString()); - ps.setDouble(3, 0.0); - ps.setLong(4, 0); - lobCreator.setBlobAsBytes(ps, 5, null); - } - else if (type == AttributeType.DOUBLE) { - ps.setString(1, AttributeType.DOUBLE.toString()); - ps.setString(2, null); - ps.setDouble(3, ((Double) value).doubleValue()); - ps.setLong(4, 0); - lobCreator.setBlobAsBytes(ps, 5, null); - } - else if (type == AttributeType.LONG) { - ps.setString(1, AttributeType.LONG.toString()); - ps.setString(2, null); - ps.setDouble(3, 0.0); - ps.setLong(4, ((Long) value).longValue()); - lobCreator.setBlobAsBytes(ps, 5, null); - } - else { - ps.setString(1, AttributeType.OBJECT.toString()); - ps.setString(2, null); - ps.setDouble(3, 0.0); - ps.setLong(4, 0); - lobCreator.setBlobAsBytes(ps, 5, SerializationUtils.serialize((Serializable) value)); - } - } - }; - - // LobCreating callbacks always return the affect row count for SQL DML - // statements, if less than 1 row - // is affected, then this row is new and should be inserted. - Integer affectedRows = (Integer) getJdbcTemplate().execute(getQuery(UPDATE_STEP_EXECUTION_CONTEXT), callback); - if (affectedRows.intValue() < 1) { - insertExecutionAttribute(executionId, key, value, type); - } - } - - /* - * (non-Javadoc) - * @see org.springframework.batch.execution.repository.dao.StepExecutionDao#updateStepExecution(org.springframework.batch.core.domain.StepExecution) - */ - public void updateStepExecution(StepExecution stepExecution) { - - validateStepExecution(stepExecution); - Assert.notNull(stepExecution.getId(), "StepExecution Id cannot be null. StepExecution must saved" - + " before it can be updated."); - - // Do not check for existence of step execution considering - // it is saved at every commit point. - - String exitDescription = stepExecution.getExitStatus().getExitDescription(); - if (exitDescription != null && exitDescription.length() > EXIT_MESSAGE_LENGTH) { - exitDescription = exitDescription.substring(0, EXIT_MESSAGE_LENGTH); - logger.debug("Truncating long message before update of StepExecution: " + stepExecution); - } - - // Attempt to prevent concurrent modification errors by blocking here if - // someone is already trying to do it. - synchronized (stepExecution) { - - Integer version = new Integer(stepExecution.getVersion().intValue() + 1); - Object[] parameters = new Object[] { stepExecution.getStartTime(), stepExecution.getEndTime(), - stepExecution.getStatus().toString(), stepExecution.getCommitCount(), stepExecution.getTaskCount(), - stepExecution.getExitStatus().isContinuable() ? "Y" : "N", - stepExecution.getExitStatus().getExitCode(), exitDescription, version, stepExecution.getId(), - stepExecution.getVersion() }; - int count = getJdbcTemplate().update( - getQuery(UPDATE_STEP_EXECUTION), - parameters, - new int[] { Types.TIMESTAMP, Types.TIMESTAMP, Types.VARCHAR, Types.INTEGER, Types.INTEGER, - Types.CHAR, Types.VARCHAR, Types.VARCHAR, Types.INTEGER, Types.INTEGER, Types.INTEGER }); - - // Avoid concurrent modifications... - if (count == 0) { - int curentVersion = getJdbcTemplate().queryForInt( - getQuery(CURRENT_VERSION_STEP_EXECUTION), - new Object[] { stepExecution.getId() }); - throw new OptimisticLockingFailureException("Attempt to update step execution id=" - + stepExecution.getId() + " with wrong version (" + stepExecution.getVersion() + "), where current version is "+curentVersion); - } - - stepExecution.incrementVersion(); - - } - } - - private class StepExecutionRowMapper implements RowMapper { - - private final JobExecution jobExecution; - - private final Step step; - - public StepExecutionRowMapper(JobExecution jobExecution, Step step) { - this.jobExecution = jobExecution; - this.step = step; - } - - public Object mapRow(ResultSet rs, int rowNum) throws SQLException { - - StepExecution stepExecution = new StepExecution(step, jobExecution, new Long(rs.getLong(1))); - stepExecution.setStartTime(rs.getTimestamp(3)); - stepExecution.setEndTime(rs.getTimestamp(4)); - stepExecution.setStatus(BatchStatus.getStatus(rs.getString(5))); - stepExecution.setCommitCount(rs.getInt(6)); - stepExecution.setTaskCount(rs.getInt(7)); - stepExecution.setExitStatus(new ExitStatus("Y".equals(rs.getString(8)), rs.getString(9), rs.getString(10))); - stepExecution.setExecutionContext(findExecutionContext(stepExecution)); - return stepExecution; - } - - } - - public void setLobHandler(LobHandler lobHandler) { - this.lobHandler = lobHandler; - } - - public void setStepExecutionIncrementer(DataFieldMaxValueIncrementer stepExecutionIncrementer) { - this.stepExecutionIncrementer = stepExecutionIncrementer; - } - - public void afterPropertiesSet() throws Exception { - Assert.notNull(stepExecutionIncrementer, "StepExecutionIncrementer cannot be null."); - } - - public static class AttributeType { - - private final String type; - - private AttributeType(String type) { - this.type = type; - } - - public String toString() { - return type; - } - - public static final AttributeType STRING = new AttributeType("STRING"); - - public static final AttributeType LONG = new AttributeType("LONG"); - - public static final AttributeType OBJECT = new AttributeType("OBJECT"); - - public static final AttributeType DOUBLE = new AttributeType("DOUBLE"); - - private static final AttributeType[] VALUES = { STRING, OBJECT, LONG, DOUBLE }; - - public static AttributeType getType(String typeAsString) { - - for (int i = 0; i < VALUES.length; i++) { - if (VALUES[i].toString().equals(typeAsString)) { - return (AttributeType) VALUES[i]; - } - } - - return null; - } - } - - public StepExecution getStepExecution(JobExecution jobExecution, Step step) { - List executions = getJdbcTemplate().query(getQuery(GET_STEP_EXECUTION), - new Object[] { step.getName(), jobExecution.getId() }, new StepExecutionRowMapper(jobExecution, step)); - - Assert.state(executions.size() <= 1, - "There can be at most one step execution with given name for single job execution"); - if (executions.isEmpty()) { - return null; - } - else { - return (StepExecution) executions.get(0); - } - } - -} +package org.springframework.batch.execution.repository.dao; + +import java.io.Serializable; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Types; +import java.util.Iterator; +import java.util.List; +import java.util.Map.Entry; + +import org.apache.commons.lang.SerializationUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.batch.core.domain.BatchStatus; +import org.springframework.batch.core.domain.JobExecution; +import org.springframework.batch.core.domain.Step; +import org.springframework.batch.core.domain.StepExecution; +import org.springframework.batch.io.exception.InfrastructureException; +import org.springframework.batch.item.ExecutionContext; +import org.springframework.batch.repeat.ExitStatus; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.dao.DataAccessException; +import org.springframework.dao.OptimisticLockingFailureException; +import org.springframework.jdbc.core.PreparedStatementCallback; +import org.springframework.jdbc.core.RowCallbackHandler; +import org.springframework.jdbc.core.RowMapper; +import org.springframework.jdbc.core.support.AbstractLobCreatingPreparedStatementCallback; +import org.springframework.jdbc.support.incrementer.DataFieldMaxValueIncrementer; +import org.springframework.jdbc.support.lob.DefaultLobHandler; +import org.springframework.jdbc.support.lob.LobCreator; +import org.springframework.jdbc.support.lob.LobHandler; +import org.springframework.util.Assert; + +/** + * Jdbc implementation of {@link StepExecutionDao}.
+ * + * Allows customization of the tables names used by Spring Batch for step meta + * data via a prefix property.
+ * + * Uses sequences or tables (via Spring's {@link DataFieldMaxValueIncrementer} + * abstraction) to create all primary keys before inserting a new row. All + * objects are checked to ensure all fields to be stored are not null. If any + * are found to be null, an IllegalArgumentException will be thrown. This could + * be left to JdbcTemplate, however, the exception will be fairly vague, and + * fails to highlight which field caused the exception.
+ * + * @author Lucas Ward + * @author Dave Syer + * @author Robert Kasanicky + * + * @see StepExecutionDao + */ +public class JdbcStepExecutionDao extends AbstractJdbcBatchMetadataDao implements StepExecutionDao, InitializingBean { + + private static final Log logger = LogFactory.getLog(JdbcStepExecutionDao.class); + + private static final String FIND_STEP_EXECUTION_CONTEXT = "SELECT TYPE_CD, KEY_NAME, STRING_VAL, DOUBLE_VAL, LONG_VAL, OBJECT_VAL " + + "from %PREFIX%STEP_EXECUTION_CONTEXT where STEP_EXECUTION_ID = ?"; + + private static final String INSERT_STEP_EXECUTION_CONTEXT = "INSERT into %PREFIX%STEP_EXECUTION_CONTEXT(STEP_EXECUTION_ID, TYPE_CD," + + " KEY_NAME, STRING_VAL, DOUBLE_VAL, LONG_VAL, OBJECT_VAL) values(?,?,?,?,?,?,?)"; + + private static final String SAVE_STEP_EXECUTION = "INSERT into %PREFIX%STEP_EXECUTION(STEP_EXECUTION_ID, VERSION, STEP_NAME, JOB_EXECUTION_ID, START_TIME, " + + "END_TIME, STATUS, COMMIT_COUNT, TASK_COUNT, CONTINUABLE, EXIT_CODE, EXIT_MESSAGE) " + + "values(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; + + private static final String UPDATE_STEP_EXECUTION_CONTEXT = "UPDATE %PREFIX%STEP_EXECUTION_CONTEXT set " + + "TYPE_CD = ?, STRING_VAL = ?, DOUBLE_VAL = ?, LONG_VAL = ?, OBJECT_VAL = ? where STEP_EXECUTION_ID = ? and KEY_NAME = ?"; + + private static final String UPDATE_STEP_EXECUTION = "UPDATE %PREFIX%STEP_EXECUTION set START_TIME = ?, END_TIME = ?, " + + "STATUS = ?, COMMIT_COUNT = ?, TASK_COUNT = ?, CONTINUABLE = ? , EXIT_CODE = ?, " + + "EXIT_MESSAGE = ?, VERSION = ? where STEP_EXECUTION_ID = ? and VERSION = ?"; + + private static final String GET_STEP_EXECUTION = "SELECT STEP_EXECUTION_ID, STEP_NAME, START_TIME, END_TIME, STATUS, COMMIT_COUNT," + + " TASK_COUNT, CONTINUABLE, EXIT_CODE, EXIT_MESSAGE from %PREFIX%STEP_EXECUTION where STEP_NAME = ? and JOB_EXECUTION_ID = ?"; + + private static final String CURRENT_VERSION_STEP_EXECUTION = "SELECT VERSION FROM %PREFIX%STEP_EXECUTION WHERE STEP_EXECUTION_ID=?"; + + private static final int EXIT_MESSAGE_LENGTH = 250; + + private LobHandler lobHandler = new DefaultLobHandler(); + + private DataFieldMaxValueIncrementer stepExecutionIncrementer; + + public ExecutionContext findExecutionContext(final StepExecution stepExecution) { + + final Long executionId = stepExecution.getId(); + Assert.notNull(executionId, "ExecutionId must not be null."); + + final ExecutionContext executionContext = new ExecutionContext(); + + RowCallbackHandler callback = new RowCallbackHandler() { + + public void processRow(ResultSet rs) throws SQLException { + + String typeCd = rs.getString("TYPE_CD"); + AttributeType type = AttributeType.getType(typeCd); + String key = rs.getString("KEY_NAME"); + if (type == AttributeType.STRING) { + executionContext.putString(key, rs.getString("STRING_VAL")); + } + else if (type == AttributeType.LONG) { + executionContext.putLong(key, rs.getLong("LONG_VAL")); + } + else if (type == AttributeType.DOUBLE) { + executionContext.putDouble(key, rs.getDouble("DOUBLE_VAL")); + } + else if (type == AttributeType.OBJECT) { + executionContext.put(key, rs.getObject("OBJECT_VAL")); + } + else { + throw new InfrastructureException("Invalid type found: [" + typeCd + "] for execution id: [" + + executionId + "]"); + } + } + }; + + getJdbcTemplate().query(getQuery(FIND_STEP_EXECUTION_CONTEXT), new Object[] { executionId }, callback); + + return executionContext; + } + + private void insertExecutionAttribute(final Long executionId, final String key, final Object value, + final AttributeType type) { + PreparedStatementCallback callback = new AbstractLobCreatingPreparedStatementCallback(lobHandler) { + + protected void setValues(PreparedStatement ps, LobCreator lobCreator) throws SQLException, + DataAccessException { + + ps.setLong(1, executionId.longValue()); + ps.setString(3, key); + if (type == AttributeType.STRING) { + ps.setString(2, AttributeType.STRING.toString()); + ps.setString(4, value.toString()); + ps.setDouble(5, 0.0); + ps.setLong(6, 0); + lobCreator.setBlobAsBytes(ps, 7, null); + } + else if (type == AttributeType.DOUBLE) { + ps.setString(2, AttributeType.DOUBLE.toString()); + ps.setString(4, null); + ps.setDouble(5, ((Double) value).doubleValue()); + ps.setLong(6, 0); + lobCreator.setBlobAsBytes(ps, 7, null); + } + else if (type == AttributeType.LONG) { + ps.setString(2, AttributeType.LONG.toString()); + ps.setString(4, null); + ps.setDouble(5, 0.0); + ps.setLong(6, ((Long) value).longValue()); + lobCreator.setBlobAsBytes(ps, 7, null); + } + else { + ps.setString(2, AttributeType.OBJECT.toString()); + ps.setString(4, null); + ps.setDouble(5, 0.0); + ps.setLong(6, 0); + lobCreator.setBlobAsBytes(ps, 7, SerializationUtils.serialize((Serializable) value)); + } + } + }; + getJdbcTemplate().execute(getQuery(INSERT_STEP_EXECUTION_CONTEXT), callback); + } + + /** + * Save a StepExecution. A unique id will be generated by the + * stepExecutionIncrementor, and then set in the StepExecution. All values + * will then be stored via an INSERT statement. + * + * @see StepDao#saveStepExecution(StepExecution) + */ + public void saveStepExecution(StepExecution stepExecution) { + + validateStepExecution(stepExecution); + + stepExecution.setId(new Long(stepExecutionIncrementer.nextLongValue())); + stepExecution.incrementVersion(); // should be 0 now + Object[] parameters = new Object[] { stepExecution.getId(), stepExecution.getVersion(), + stepExecution.getStepName(), stepExecution.getJobExecutionId(), stepExecution.getStartTime(), + stepExecution.getEndTime(), stepExecution.getStatus().toString(), stepExecution.getCommitCount(), + stepExecution.getTaskCount(), stepExecution.getExitStatus().isContinuable() ? "Y" : "N", + stepExecution.getExitStatus().getExitCode(), stepExecution.getExitStatus().getExitDescription() }; + getJdbcTemplate().update( + getQuery(SAVE_STEP_EXECUTION), + parameters, + new int[] { Types.INTEGER, Types.INTEGER, Types.VARCHAR, Types.INTEGER, Types.TIMESTAMP, + Types.TIMESTAMP, Types.VARCHAR, Types.INTEGER, Types.INTEGER, Types.CHAR, Types.VARCHAR, + Types.VARCHAR }); + } + + /** + * Validate StepExecution. At a minimum, JobId, StartTime, and Status cannot + * be null. EndTime can be null for an unfinished job. + * + * @param jobExecution + * @throws IllegalArgumentException + */ + private void validateStepExecution(StepExecution stepExecution) { + Assert.notNull(stepExecution); + Assert.notNull(stepExecution.getStepName(), "StepExecution step name cannot be null."); + Assert.notNull(stepExecution.getStartTime(), "StepExecution start time cannot be null."); + Assert.notNull(stepExecution.getStatus(), "StepExecution status cannot be null."); + } + + /** + * Save or update execution attributes. A lob creator must be used, since + * any attributes that don't match a provided type must be serialized into a + * blob. + * + * @see {@link LobCreator} + */ + public void saveOrUpdateExecutionContext(final StepExecution stepExecution) { + + Long executionId = stepExecution.getId(); + ExecutionContext executionContext = stepExecution.getExecutionContext(); + Assert.notNull(executionId, "ExecutionId must not be null."); + Assert.notNull(executionContext, "The ExecutionContext must not be null."); + + for (Iterator it = executionContext.entrySet().iterator(); it.hasNext();) { + Entry entry = (Entry) it.next(); + final String key = entry.getKey().toString(); + final Object value = entry.getValue(); + + if (value instanceof String) { + updateExecutionAttribute(executionId, key, value, AttributeType.STRING); + } + else if (value instanceof Double) { + updateExecutionAttribute(executionId, key, value, AttributeType.DOUBLE); + } + else if (value instanceof Long) { + updateExecutionAttribute(executionId, key, value, AttributeType.LONG); + } + else { + updateExecutionAttribute(executionId, key, value, AttributeType.OBJECT); + } + } + } + + private void updateExecutionAttribute(final Long executionId, final String key, final Object value, + final AttributeType type) { + + PreparedStatementCallback callback = new AbstractLobCreatingPreparedStatementCallback(lobHandler) { + + protected void setValues(PreparedStatement ps, LobCreator lobCreator) throws SQLException, + DataAccessException { + + ps.setLong(6, executionId.longValue()); + ps.setString(7, key); + if (type == AttributeType.STRING) { + ps.setString(1, AttributeType.STRING.toString()); + ps.setString(2, value.toString()); + ps.setDouble(3, 0.0); + ps.setLong(4, 0); + lobCreator.setBlobAsBytes(ps, 5, null); + } + else if (type == AttributeType.DOUBLE) { + ps.setString(1, AttributeType.DOUBLE.toString()); + ps.setString(2, null); + ps.setDouble(3, ((Double) value).doubleValue()); + ps.setLong(4, 0); + lobCreator.setBlobAsBytes(ps, 5, null); + } + else if (type == AttributeType.LONG) { + ps.setString(1, AttributeType.LONG.toString()); + ps.setString(2, null); + ps.setDouble(3, 0.0); + ps.setLong(4, ((Long) value).longValue()); + lobCreator.setBlobAsBytes(ps, 5, null); + } + else { + ps.setString(1, AttributeType.OBJECT.toString()); + ps.setString(2, null); + ps.setDouble(3, 0.0); + ps.setLong(4, 0); + lobCreator.setBlobAsBytes(ps, 5, SerializationUtils.serialize((Serializable) value)); + } + } + }; + + // LobCreating callbacks always return the affect row count for SQL DML + // statements, if less than 1 row + // is affected, then this row is new and should be inserted. + Integer affectedRows = (Integer) getJdbcTemplate().execute(getQuery(UPDATE_STEP_EXECUTION_CONTEXT), callback); + if (affectedRows.intValue() < 1) { + insertExecutionAttribute(executionId, key, value, type); + } + } + + /* + * (non-Javadoc) + * @see org.springframework.batch.execution.repository.dao.StepExecutionDao#updateStepExecution(org.springframework.batch.core.domain.StepExecution) + */ + public void updateStepExecution(StepExecution stepExecution) { + + validateStepExecution(stepExecution); + Assert.notNull(stepExecution.getId(), "StepExecution Id cannot be null. StepExecution must saved" + + " before it can be updated."); + + // Do not check for existence of step execution considering + // it is saved at every commit point. + + String exitDescription = stepExecution.getExitStatus().getExitDescription(); + if (exitDescription != null && exitDescription.length() > EXIT_MESSAGE_LENGTH) { + exitDescription = exitDescription.substring(0, EXIT_MESSAGE_LENGTH); + logger.debug("Truncating long message before update of StepExecution: " + stepExecution); + } + + // Attempt to prevent concurrent modification errors by blocking here if + // someone is already trying to do it. + synchronized (stepExecution) { + + Integer version = new Integer(stepExecution.getVersion().intValue() + 1); + Object[] parameters = new Object[] { stepExecution.getStartTime(), stepExecution.getEndTime(), + stepExecution.getStatus().toString(), stepExecution.getCommitCount(), stepExecution.getTaskCount(), + stepExecution.getExitStatus().isContinuable() ? "Y" : "N", + stepExecution.getExitStatus().getExitCode(), exitDescription, version, stepExecution.getId(), + stepExecution.getVersion() }; + int count = getJdbcTemplate().update( + getQuery(UPDATE_STEP_EXECUTION), + parameters, + new int[] { Types.TIMESTAMP, Types.TIMESTAMP, Types.VARCHAR, Types.INTEGER, Types.INTEGER, + Types.CHAR, Types.VARCHAR, Types.VARCHAR, Types.INTEGER, Types.INTEGER, Types.INTEGER }); + + // Avoid concurrent modifications... + if (count == 0) { + int curentVersion = getJdbcTemplate().queryForInt( + getQuery(CURRENT_VERSION_STEP_EXECUTION), + new Object[] { stepExecution.getId() }); + throw new OptimisticLockingFailureException("Attempt to update step execution id=" + + stepExecution.getId() + " with wrong version (" + stepExecution.getVersion() + "), where current version is "+curentVersion); + } + + stepExecution.incrementVersion(); + + } + } + + private class StepExecutionRowMapper implements RowMapper { + + private final JobExecution jobExecution; + + private final Step step; + + public StepExecutionRowMapper(JobExecution jobExecution, Step step) { + this.jobExecution = jobExecution; + this.step = step; + } + + public Object mapRow(ResultSet rs, int rowNum) throws SQLException { + + StepExecution stepExecution = new StepExecution(step, jobExecution, new Long(rs.getLong(1))); + stepExecution.setStartTime(rs.getTimestamp(3)); + stepExecution.setEndTime(rs.getTimestamp(4)); + stepExecution.setStatus(BatchStatus.getStatus(rs.getString(5))); + stepExecution.setCommitCount(rs.getInt(6)); + stepExecution.setTaskCount(rs.getInt(7)); + stepExecution.setExitStatus(new ExitStatus("Y".equals(rs.getString(8)), rs.getString(9), rs.getString(10))); + stepExecution.setExecutionContext(findExecutionContext(stepExecution)); + return stepExecution; + } + + } + + public void setLobHandler(LobHandler lobHandler) { + this.lobHandler = lobHandler; + } + + public void setStepExecutionIncrementer(DataFieldMaxValueIncrementer stepExecutionIncrementer) { + this.stepExecutionIncrementer = stepExecutionIncrementer; + } + + public void afterPropertiesSet() throws Exception { + Assert.notNull(stepExecutionIncrementer, "StepExecutionIncrementer cannot be null."); + } + + public static class AttributeType { + + private final String type; + + private AttributeType(String type) { + this.type = type; + } + + public String toString() { + return type; + } + + public static final AttributeType STRING = new AttributeType("STRING"); + + public static final AttributeType LONG = new AttributeType("LONG"); + + public static final AttributeType OBJECT = new AttributeType("OBJECT"); + + public static final AttributeType DOUBLE = new AttributeType("DOUBLE"); + + private static final AttributeType[] VALUES = { STRING, OBJECT, LONG, DOUBLE }; + + public static AttributeType getType(String typeAsString) { + + for (int i = 0; i < VALUES.length; i++) { + if (VALUES[i].toString().equals(typeAsString)) { + return (AttributeType) VALUES[i]; + } + } + + return null; + } + } + + public StepExecution getStepExecution(JobExecution jobExecution, Step step) { + List executions = getJdbcTemplate().query(getQuery(GET_STEP_EXECUTION), + new Object[] { step.getName(), jobExecution.getId() }, new StepExecutionRowMapper(jobExecution, step)); + + Assert.state(executions.size() <= 1, + "There can be at most one step execution with given name for single job execution"); + if (executions.isEmpty()) { + return null; + } + else { + return (StepExecution) executions.get(0); + } + } + +} diff --git a/spring-batch-execution/src/main/java/org/springframework/batch/execution/repository/dao/JobExecutionDao.java b/spring-batch-execution/src/main/java/org/springframework/batch/execution/repository/dao/JobExecutionDao.java index e1aea0c02f..aac11ba7c4 100644 --- a/spring-batch-execution/src/main/java/org/springframework/batch/execution/repository/dao/JobExecutionDao.java +++ b/spring-batch-execution/src/main/java/org/springframework/batch/execution/repository/dao/JobExecutionDao.java @@ -1,55 +1,55 @@ -package org.springframework.batch.execution.repository.dao; - -import java.util.List; - -import org.springframework.batch.core.domain.JobExecution; -import org.springframework.batch.core.domain.JobInstance; - -/** - * Data Access Object for job executions. - * - * @author Lucas Ward - * @author Robert Kasanicky - */ -public interface JobExecutionDao { - - /** - * Save a new JobExecution. - * - * Preconditions: jobInstance the jobExecution belongs to must have a jobInstanceId. - * - * @param jobExecution - */ - void saveJobExecution(JobExecution jobExecution); - - /** - * Update and existing JobExecution. - * - * Preconditions: jobExecution must have an Id (which can be obtained by the - * save method) and a jobInstanceId. - * - * @param jobExecution - */ - void updateJobExecution(JobExecution jobExecution); - - /** - * Return the number of JobExecutions for the given JobInstance - * - * Preconditions: jobInstance must have an id. - */ - int getJobExecutionCount(JobInstance jobInstance); - - /** - * Return list of JobExecutions for given JobInstance. - * - * @param jobInstance - * @return list of jobExecutions. - */ - List findJobExecutions(JobInstance jobInstance); - - /** - * @return last JobExecution for given JobInstance. - */ - JobExecution getLastJobExecution(JobInstance jobInstance); - -} +package org.springframework.batch.execution.repository.dao; + +import java.util.List; + +import org.springframework.batch.core.domain.JobExecution; +import org.springframework.batch.core.domain.JobInstance; + +/** + * Data Access Object for job executions. + * + * @author Lucas Ward + * @author Robert Kasanicky + */ +public interface JobExecutionDao { + + /** + * Save a new JobExecution. + * + * Preconditions: jobInstance the jobExecution belongs to must have a jobInstanceId. + * + * @param jobExecution + */ + void saveJobExecution(JobExecution jobExecution); + + /** + * Update and existing JobExecution. + * + * Preconditions: jobExecution must have an Id (which can be obtained by the + * save method) and a jobInstanceId. + * + * @param jobExecution + */ + void updateJobExecution(JobExecution jobExecution); + + /** + * Return the number of JobExecutions for the given JobInstance + * + * Preconditions: jobInstance must have an id. + */ + int getJobExecutionCount(JobInstance jobInstance); + + /** + * Return list of JobExecutions for given JobInstance. + * + * @param jobInstance + * @return list of jobExecutions. + */ + List findJobExecutions(JobInstance jobInstance); + + /** + * @return last JobExecution for given JobInstance. + */ + JobExecution getLastJobExecution(JobInstance jobInstance); + +} diff --git a/spring-batch-execution/src/main/java/org/springframework/batch/execution/repository/dao/JobInstanceDao.java b/spring-batch-execution/src/main/java/org/springframework/batch/execution/repository/dao/JobInstanceDao.java index e551efd295..799551165d 100644 --- a/spring-batch-execution/src/main/java/org/springframework/batch/execution/repository/dao/JobInstanceDao.java +++ b/spring-batch-execution/src/main/java/org/springframework/batch/execution/repository/dao/JobInstanceDao.java @@ -1,42 +1,42 @@ -package org.springframework.batch.execution.repository.dao; - -import org.springframework.batch.core.domain.Job; -import org.springframework.batch.core.domain.JobInstance; -import org.springframework.batch.core.domain.JobParameters; - -/** - * Data Access Object for job instances. - * - * @author Lucas Ward - * @author Robert Kasanicky - * - */ -public interface JobInstanceDao { - - /** - * Create a JobInstance with given name and parameters. - * - * PreConditions: JobInstance for given name and parameters must not already exist - * - * PostConditions: A valid job instancewill be returned which has been persisted and - * contains an unique Id. - * - * @param jobName - * @param jobParameters - * @return JobInstance - */ - JobInstance createJobInstance(Job job, JobParameters jobParameters); - - /** - * Find all job instances that match the given name and parameters. If no - * matching job instances are found, then a list of size 0 will be - * returned. - * - * @param jobName - * @param jobParameters - * @return List of {@link JobInstance} objects matching - * {@link JobIdentifier} - */ - JobInstance getJobInstance(Job job, JobParameters jobParameters); - -} +package org.springframework.batch.execution.repository.dao; + +import org.springframework.batch.core.domain.Job; +import org.springframework.batch.core.domain.JobInstance; +import org.springframework.batch.core.domain.JobParameters; + +/** + * Data Access Object for job instances. + * + * @author Lucas Ward + * @author Robert Kasanicky + * + */ +public interface JobInstanceDao { + + /** + * Create a JobInstance with given name and parameters. + * + * PreConditions: JobInstance for given name and parameters must not already exist + * + * PostConditions: A valid job instancewill be returned which has been persisted and + * contains an unique Id. + * + * @param jobName + * @param jobParameters + * @return JobInstance + */ + JobInstance createJobInstance(Job job, JobParameters jobParameters); + + /** + * Find all job instances that match the given name and parameters. If no + * matching job instances are found, then a list of size 0 will be + * returned. + * + * @param jobName + * @param jobParameters + * @return List of {@link JobInstance} objects matching + * {@link JobIdentifier} + */ + JobInstance getJobInstance(Job job, JobParameters jobParameters); + +} diff --git a/spring-batch-execution/src/main/java/org/springframework/batch/execution/repository/dao/MapJobExecutionDao.java b/spring-batch-execution/src/main/java/org/springframework/batch/execution/repository/dao/MapJobExecutionDao.java index 3c75b9bdbc..99bc9bb052 100644 --- a/spring-batch-execution/src/main/java/org/springframework/batch/execution/repository/dao/MapJobExecutionDao.java +++ b/spring-batch-execution/src/main/java/org/springframework/batch/execution/repository/dao/MapJobExecutionDao.java @@ -1,76 +1,76 @@ -package org.springframework.batch.execution.repository.dao; - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.springframework.batch.core.domain.JobExecution; -import org.springframework.batch.core.domain.JobInstance; -import org.springframework.batch.support.transaction.TransactionAwareProxyFactory; - -/** - * In-memory implementation of {@link JobExecutionDao}. - * - */ -public class MapJobExecutionDao implements JobExecutionDao { - - private static Map executionsByJobInstanceId = TransactionAwareProxyFactory.createTransactionalMap(); - - private static long currentId; - - public static void clear() { - executionsByJobInstanceId.clear(); - } - - public int getJobExecutionCount(JobInstance jobInstance) { - Set executions = (Set) executionsByJobInstanceId.get(jobInstance.getId()); - if (executions == null) { - return 0; - } - return executions.size(); - } - - public void saveJobExecution(JobExecution jobExecution) { - Set executions = (Set) executionsByJobInstanceId.get(jobExecution.getJobId()); - if (executions == null) { - executions = TransactionAwareProxyFactory.createTransactionalSet(); - executionsByJobInstanceId.put(jobExecution.getJobId(), executions); - } - executions.add(jobExecution); - jobExecution.setId(new Long(currentId++)); - } - - public List findJobExecutions(JobInstance jobInstance) { - Set executions = (Set) executionsByJobInstanceId.get(jobInstance.getId()); - if (executions == null) { - return new ArrayList(); - } - else { - return new ArrayList(executions); - } - } - - public void updateJobExecution(JobExecution jobExecution) { - // no-op - } - - public JobExecution getLastJobExecution(JobInstance jobInstance) { - Set executions = (Set) executionsByJobInstanceId.get(jobInstance.getId()); - if (executions == null) { - return null; - } - JobExecution lastExec = null; - for (Iterator iterator = executions.iterator(); iterator.hasNext();) { - JobExecution exec = (JobExecution) iterator.next(); - if (lastExec == null) { - lastExec = exec; - } - if (lastExec.getStartTime().getTime() < exec.getStartTime().getTime()) { - lastExec = exec; - } - } - return lastExec; - } -} +package org.springframework.batch.execution.repository.dao; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.springframework.batch.core.domain.JobExecution; +import org.springframework.batch.core.domain.JobInstance; +import org.springframework.batch.support.transaction.TransactionAwareProxyFactory; + +/** + * In-memory implementation of {@link JobExecutionDao}. + * + */ +public class MapJobExecutionDao implements JobExecutionDao { + + private static Map executionsByJobInstanceId = TransactionAwareProxyFactory.createTransactionalMap(); + + private static long currentId; + + public static void clear() { + executionsByJobInstanceId.clear(); + } + + public int getJobExecutionCount(JobInstance jobInstance) { + Set executions = (Set) executionsByJobInstanceId.get(jobInstance.getId()); + if (executions == null) { + return 0; + } + return executions.size(); + } + + public void saveJobExecution(JobExecution jobExecution) { + Set executions = (Set) executionsByJobInstanceId.get(jobExecution.getJobId()); + if (executions == null) { + executions = TransactionAwareProxyFactory.createTransactionalSet(); + executionsByJobInstanceId.put(jobExecution.getJobId(), executions); + } + executions.add(jobExecution); + jobExecution.setId(new Long(currentId++)); + } + + public List findJobExecutions(JobInstance jobInstance) { + Set executions = (Set) executionsByJobInstanceId.get(jobInstance.getId()); + if (executions == null) { + return new ArrayList(); + } + else { + return new ArrayList(executions); + } + } + + public void updateJobExecution(JobExecution jobExecution) { + // no-op + } + + public JobExecution getLastJobExecution(JobInstance jobInstance) { + Set executions = (Set) executionsByJobInstanceId.get(jobInstance.getId()); + if (executions == null) { + return null; + } + JobExecution lastExec = null; + for (Iterator iterator = executions.iterator(); iterator.hasNext();) { + JobExecution exec = (JobExecution) iterator.next(); + if (lastExec == null) { + lastExec = exec; + } + if (lastExec.getStartTime().getTime() < exec.getStartTime().getTime()) { + lastExec = exec; + } + } + return lastExec; + } +} diff --git a/spring-batch-execution/src/main/java/org/springframework/batch/execution/repository/dao/MapJobInstanceDao.java b/spring-batch-execution/src/main/java/org/springframework/batch/execution/repository/dao/MapJobInstanceDao.java index 91c318c4f3..21c26648b5 100644 --- a/spring-batch-execution/src/main/java/org/springframework/batch/execution/repository/dao/MapJobInstanceDao.java +++ b/spring-batch-execution/src/main/java/org/springframework/batch/execution/repository/dao/MapJobInstanceDao.java @@ -1,44 +1,44 @@ -package org.springframework.batch.execution.repository.dao; - -import java.util.Collection; -import java.util.Iterator; - -import org.springframework.batch.core.domain.Job; -import org.springframework.batch.core.domain.JobInstance; -import org.springframework.batch.core.domain.JobParameters; -import org.springframework.batch.support.transaction.TransactionAwareProxyFactory; -import org.springframework.util.Assert; - -public class MapJobInstanceDao implements JobInstanceDao { - - private static Collection jobInstances = TransactionAwareProxyFactory.createTransactionalList(); - - private long currentId = 0; - - public static void clear() { - jobInstances.clear(); - } - - public JobInstance createJobInstance(Job job, JobParameters jobParameters) { - - Assert.state(getJobInstance(job, jobParameters) == null, "JobInstance must not already exist"); - - JobInstance jobInstance = new JobInstance(new Long(currentId++), jobParameters, job); - jobInstances.add(jobInstance); - - return jobInstance; - } - - public JobInstance getJobInstance(Job job, JobParameters jobParameters) { - - for (Iterator iterator = jobInstances.iterator(); iterator.hasNext();) { - JobInstance instance = (JobInstance) iterator.next(); - if (instance.getJobName().equals(job.getName()) && instance.getJobParameters().equals(jobParameters)) { - return instance; - } - } - return null; - - } - -} +package org.springframework.batch.execution.repository.dao; + +import java.util.Collection; +import java.util.Iterator; + +import org.springframework.batch.core.domain.Job; +import org.springframework.batch.core.domain.JobInstance; +import org.springframework.batch.core.domain.JobParameters; +import org.springframework.batch.support.transaction.TransactionAwareProxyFactory; +import org.springframework.util.Assert; + +public class MapJobInstanceDao implements JobInstanceDao { + + private static Collection jobInstances = TransactionAwareProxyFactory.createTransactionalList(); + + private long currentId = 0; + + public static void clear() { + jobInstances.clear(); + } + + public JobInstance createJobInstance(Job job, JobParameters jobParameters) { + + Assert.state(getJobInstance(job, jobParameters) == null, "JobInstance must not already exist"); + + JobInstance jobInstance = new JobInstance(new Long(currentId++), jobParameters, job); + jobInstances.add(jobInstance); + + return jobInstance; + } + + public JobInstance getJobInstance(Job job, JobParameters jobParameters) { + + for (Iterator iterator = jobInstances.iterator(); iterator.hasNext();) { + JobInstance instance = (JobInstance) iterator.next(); + if (instance.getJobName().equals(job.getName()) && instance.getJobParameters().equals(jobParameters)) { + return instance; + } + } + return null; + + } + +} diff --git a/spring-batch-execution/src/main/java/org/springframework/batch/execution/repository/dao/StepExecutionDao.java b/spring-batch-execution/src/main/java/org/springframework/batch/execution/repository/dao/StepExecutionDao.java index 8fecda0e52..af014946c8 100644 --- a/spring-batch-execution/src/main/java/org/springframework/batch/execution/repository/dao/StepExecutionDao.java +++ b/spring-batch-execution/src/main/java/org/springframework/batch/execution/repository/dao/StepExecutionDao.java @@ -1,48 +1,48 @@ -package org.springframework.batch.execution.repository.dao; - -import org.springframework.batch.core.domain.JobExecution; -import org.springframework.batch.core.domain.Step; -import org.springframework.batch.core.domain.StepExecution; -import org.springframework.batch.item.ExecutionContext; - -public interface StepExecutionDao { - - /** - * Save the given StepExecution. - * - * Preconditions: Id must be null. - * - * Postconditions: Id will be set to a unique Long. - * - * @param stepExecution - */ - void saveStepExecution(StepExecution stepExecution); - - /** - * Update the given StepExecution - * - * Preconditions: Id must not be null. - * - * @param stepExecution - */ - void updateStepExecution(StepExecution stepExecution); - - /** - * Find all {@link ExecutionContext} for the given {@link StepExecution}. - * - * @throws IllegalArgumentException if the id is null. - */ - ExecutionContext findExecutionContext(StepExecution stepExecution); - - /** - * Save the {@link ExecutionContext} of the given {@link StepExecution}. - * - * @param stepExecution the {@link StepExecution} containing the - * {@link ExecutionContext} to be saved. - * @throws IllegalArgumentException if the attributes are null. - */ - void saveOrUpdateExecutionContext(StepExecution stepExecution); - - StepExecution getStepExecution(JobExecution jobExecution, Step step); - -} +package org.springframework.batch.execution.repository.dao; + +import org.springframework.batch.core.domain.JobExecution; +import org.springframework.batch.core.domain.Step; +import org.springframework.batch.core.domain.StepExecution; +import org.springframework.batch.item.ExecutionContext; + +public interface StepExecutionDao { + + /** + * Save the given StepExecution. + * + * Preconditions: Id must be null. + * + * Postconditions: Id will be set to a unique Long. + * + * @param stepExecution + */ + void saveStepExecution(StepExecution stepExecution); + + /** + * Update the given StepExecution + * + * Preconditions: Id must not be null. + * + * @param stepExecution + */ + void updateStepExecution(StepExecution stepExecution); + + /** + * Find all {@link ExecutionContext} for the given {@link StepExecution}. + * + * @throws IllegalArgumentException if the id is null. + */ + ExecutionContext findExecutionContext(StepExecution stepExecution); + + /** + * Save the {@link ExecutionContext} of the given {@link StepExecution}. + * + * @param stepExecution the {@link StepExecution} containing the + * {@link ExecutionContext} to be saved. + * @throws IllegalArgumentException if the attributes are null. + */ + void saveOrUpdateExecutionContext(StepExecution stepExecution); + + StepExecution getStepExecution(JobExecution jobExecution, Step step); + +} diff --git a/spring-batch-execution/src/main/java/org/springframework/batch/execution/step/AbstractStep.java b/spring-batch-execution/src/main/java/org/springframework/batch/execution/step/AbstractStep.java index dbc11632b5..c7dd354195 100644 --- a/spring-batch-execution/src/main/java/org/springframework/batch/execution/step/AbstractStep.java +++ b/spring-batch-execution/src/main/java/org/springframework/batch/execution/step/AbstractStep.java @@ -1,94 +1,94 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.execution.step; - -import org.springframework.batch.core.domain.JobInterruptedException; -import org.springframework.batch.core.domain.Step; -import org.springframework.batch.core.domain.StepExecution; -import org.springframework.batch.io.exception.InfrastructureException; - -/** - * A {@link Step} implementation that provides common behaviour to subclasses. - * - * @author Dave Syer - * @author Ben Hale - */ -public abstract class AbstractStep implements Step { - - protected String name; - - protected int startLimit = Integer.MAX_VALUE; - - protected boolean allowStartIfComplete; - - /** - * Default constructor. - */ - public AbstractStep() { - super(); - } - - public String getName() { - return this.name; - } - - /** - * Set the name property. Always overrides the default value if this object - * is a Spring bean. - * - * @see #setBeanName(java.lang.String) - */ - public void setName(String name) { - this.name = name; - } - - public int getStartLimit() { - return this.startLimit; - } - - /** - * Public setter for the startLimit. - * - * @param startLimit the startLimit to set - */ - public void setStartLimit(int startLimit) { - this.startLimit = startLimit; - } - - public boolean isAllowStartIfComplete() { - return this.allowStartIfComplete; - } - - /** - * Public setter for the shouldAllowStartIfComplete. - * - * @param allowStartIfComplete the shouldAllowStartIfComplete to set - */ - public void setAllowStartIfComplete(boolean allowStartIfComplete) { - this.allowStartIfComplete = allowStartIfComplete; - } - - /** - * Convenient constructor for setting only the name property. - * - * @param name - */ - public AbstractStep(String name) { - this.name = name; - } - - public abstract void execute(StepExecution stepExecution) throws JobInterruptedException, InfrastructureException; +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.execution.step; + +import org.springframework.batch.core.domain.JobInterruptedException; +import org.springframework.batch.core.domain.Step; +import org.springframework.batch.core.domain.StepExecution; +import org.springframework.batch.io.exception.InfrastructureException; + +/** + * A {@link Step} implementation that provides common behaviour to subclasses. + * + * @author Dave Syer + * @author Ben Hale + */ +public abstract class AbstractStep implements Step { + + protected String name; + + protected int startLimit = Integer.MAX_VALUE; + + protected boolean allowStartIfComplete; + + /** + * Default constructor. + */ + public AbstractStep() { + super(); + } + + public String getName() { + return this.name; + } + + /** + * Set the name property. Always overrides the default value if this object + * is a Spring bean. + * + * @see #setBeanName(java.lang.String) + */ + public void setName(String name) { + this.name = name; + } + + public int getStartLimit() { + return this.startLimit; + } + + /** + * Public setter for the startLimit. + * + * @param startLimit the startLimit to set + */ + public void setStartLimit(int startLimit) { + this.startLimit = startLimit; + } + + public boolean isAllowStartIfComplete() { + return this.allowStartIfComplete; + } + + /** + * Public setter for the shouldAllowStartIfComplete. + * + * @param allowStartIfComplete the shouldAllowStartIfComplete to set + */ + public void setAllowStartIfComplete(boolean allowStartIfComplete) { + this.allowStartIfComplete = allowStartIfComplete; + } + + /** + * Convenient constructor for setting only the name property. + * + * @param name + */ + public AbstractStep(String name) { + this.name = name; + } + + public abstract void execute(StepExecution stepExecution) throws JobInterruptedException, InfrastructureException; } \ No newline at end of file diff --git a/spring-batch-execution/src/main/java/org/springframework/batch/execution/step/ItemHandler.java b/spring-batch-execution/src/main/java/org/springframework/batch/execution/step/ItemHandler.java index 8fec5629c7..0421ce8a7b 100644 --- a/spring-batch-execution/src/main/java/org/springframework/batch/execution/step/ItemHandler.java +++ b/spring-batch-execution/src/main/java/org/springframework/batch/execution/step/ItemHandler.java @@ -1,78 +1,78 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.execution.step; - -import org.springframework.batch.core.domain.StepContribution; -import org.springframework.batch.item.ItemReader; -import org.springframework.batch.item.ItemWriter; -import org.springframework.batch.item.exception.ClearFailedException; -import org.springframework.batch.item.exception.FlushFailedException; -import org.springframework.batch.item.exception.MarkFailedException; -import org.springframework.batch.item.exception.ResetFailedException; -import org.springframework.batch.repeat.ExitStatus; - -/** - * Strategy for processing a single item in an item-oriented step. Extends - * {@link ItemReader} and {@link ItemWriter} because part of the contract of the - * processor is that it should delegate calls to those interfaces. - * - * @author Dave Syer - * - */ -public interface ItemHandler { - - /** - * Given the current context in the form of a step contribution, do whatever - * is necessary to process this unit inside a chunk. Implementations obtain - * the item and return {@link ExitStatus#FINISHED} if it is null. If it is - * not null process the item and return {@link ExitStatus#CONTINUABLE}. On - * failure throws an exception. - * - * @param contribution the current step context - * @return an {@link ExitStatus} indicating whether processing is - * continuable. - */ - ExitStatus handle(StepContribution contribution) throws Exception; - - /** - * Implementations should delegate to an {@link ItemReader}. - * - * @see org.springframework.batch.item.ItemReader#mark() - */ - void mark() throws MarkFailedException; - - /** - * Implementations should delegate to an {@link ItemReader}. - * - * @see org.springframework.batch.item.ItemReader#reset() - */ - void reset() throws ResetFailedException; - - /** - * Implementations should delegate to an {@link ItemWriter}. - * - * @see org.springframework.batch.item.ItemWriter#flush() - */ - public void flush() throws FlushFailedException; - - /** - * Implementations should delegate to an {@link ItemWriter}. - * - * @see org.springframework.batch.item.ItemWriter#clear() - */ - public void clear() throws ClearFailedException; - -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.execution.step; + +import org.springframework.batch.core.domain.StepContribution; +import org.springframework.batch.item.ItemReader; +import org.springframework.batch.item.ItemWriter; +import org.springframework.batch.item.exception.ClearFailedException; +import org.springframework.batch.item.exception.FlushFailedException; +import org.springframework.batch.item.exception.MarkFailedException; +import org.springframework.batch.item.exception.ResetFailedException; +import org.springframework.batch.repeat.ExitStatus; + +/** + * Strategy for processing a single item in an item-oriented step. Extends + * {@link ItemReader} and {@link ItemWriter} because part of the contract of the + * processor is that it should delegate calls to those interfaces. + * + * @author Dave Syer + * + */ +public interface ItemHandler { + + /** + * Given the current context in the form of a step contribution, do whatever + * is necessary to process this unit inside a chunk. Implementations obtain + * the item and return {@link ExitStatus#FINISHED} if it is null. If it is + * not null process the item and return {@link ExitStatus#CONTINUABLE}. On + * failure throws an exception. + * + * @param contribution the current step context + * @return an {@link ExitStatus} indicating whether processing is + * continuable. + */ + ExitStatus handle(StepContribution contribution) throws Exception; + + /** + * Implementations should delegate to an {@link ItemReader}. + * + * @see org.springframework.batch.item.ItemReader#mark() + */ + void mark() throws MarkFailedException; + + /** + * Implementations should delegate to an {@link ItemReader}. + * + * @see org.springframework.batch.item.ItemReader#reset() + */ + void reset() throws ResetFailedException; + + /** + * Implementations should delegate to an {@link ItemWriter}. + * + * @see org.springframework.batch.item.ItemWriter#flush() + */ + public void flush() throws FlushFailedException; + + /** + * Implementations should delegate to an {@link ItemWriter}. + * + * @see org.springframework.batch.item.ItemWriter#clear() + */ + public void clear() throws ClearFailedException; + +} diff --git a/spring-batch-execution/src/main/java/org/springframework/batch/execution/step/ItemOrientedStep.java b/spring-batch-execution/src/main/java/org/springframework/batch/execution/step/ItemOrientedStep.java index 7fe52c8486..238976340c 100644 --- a/spring-batch-execution/src/main/java/org/springframework/batch/execution/step/ItemOrientedStep.java +++ b/spring-batch-execution/src/main/java/org/springframework/batch/execution/step/ItemOrientedStep.java @@ -1,537 +1,537 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.execution.step; - -import java.util.Date; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.springframework.batch.core.domain.BatchStatus; -import org.springframework.batch.core.domain.JobInstance; -import org.springframework.batch.core.domain.JobInterruptedException; -import org.springframework.batch.core.domain.StepContribution; -import org.springframework.batch.core.domain.StepExecution; -import org.springframework.batch.core.domain.StepListener; -import org.springframework.batch.core.repository.JobRepository; -import org.springframework.batch.core.runtime.ExitStatusExceptionClassifier; -import org.springframework.batch.core.tasklet.Tasklet; -import org.springframework.batch.execution.listener.CompositeStepListener; -import org.springframework.batch.execution.step.support.DefaultStepExecutionSynchronizer; -import org.springframework.batch.execution.step.support.SimpleExitStatusExceptionClassifier; -import org.springframework.batch.execution.step.support.StepExecutionSynchronizer; -import org.springframework.batch.execution.step.support.StepInterruptionPolicy; -import org.springframework.batch.execution.step.support.ThreadStepInterruptionPolicy; -import org.springframework.batch.io.exception.InfrastructureException; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.item.ItemReader; -import org.springframework.batch.item.ItemStream; -import org.springframework.batch.item.ItemWriter; -import org.springframework.batch.item.exception.CommitFailedException; -import org.springframework.batch.item.stream.CompositeItemStream; -import org.springframework.batch.repeat.ExitStatus; -import org.springframework.batch.repeat.RepeatCallback; -import org.springframework.batch.repeat.RepeatContext; -import org.springframework.batch.repeat.RepeatOperations; -import org.springframework.batch.repeat.support.RepeatTemplate; -import org.springframework.transaction.PlatformTransactionManager; -import org.springframework.transaction.TransactionStatus; -import org.springframework.transaction.support.DefaultTransactionDefinition; - -/** - * Simple implementation of executing the step as a set of chunks, each chunk - * surrounded by a transaction. The structure is therefore that of two nested - * loops, with transaction boundary around the whole inner loop. The outer loop - * is controlled by the step operations ({@link #setStepOperations(RepeatOperations)}), - * and the inner loop by the chunk operations ({@link #setChunkOperations(RepeatOperations)}). - * The inner loop should always be executed in a single thread, so the chunk - * operations should not do any concurrent execution. N.B. usually that means - * that the chunk operations should be a {@link RepeatTemplate} (which is the - * default).
- * - * Clients can use interceptors in the step operations to intercept or listen to - * the iteration on a step-wide basis, for instance to get a callback when the - * step is complete. Those that want callbacks at the level of an individual - * tasks, can specify interceptors for the chunk operations. - * - * @author Dave Syer - * @author Lucas Ward - * @author Ben Hale - */ -public class ItemOrientedStep extends AbstractStep { - - private static final Log logger = LogFactory.getLog(ItemOrientedStep.class); - - private RepeatOperations chunkOperations = new RepeatTemplate(); - - private RepeatOperations stepOperations = new RepeatTemplate(); - - private ExitStatusExceptionClassifier exceptionClassifier = new SimpleExitStatusExceptionClassifier(); - - // default to checking current thread for interruption. - private StepInterruptionPolicy interruptionPolicy = new ThreadStepInterruptionPolicy(); - - private CompositeItemStream stream = new CompositeItemStream(); - - private CompositeStepListener listener = new CompositeStepListener(); - - private JobRepository jobRepository; - - private PlatformTransactionManager transactionManager; - - private ItemHandler itemHandler; - - private StepExecutionSynchronizer synchronizer = new DefaultStepExecutionSynchronizer(); - - /** - * @param name - */ - public ItemOrientedStep(String name) { - super(name); - } - - /** - * Public setter for {@link JobRepository}. - * - * @param jobRepository is a mandatory dependence (no default). - */ - public void setJobRepository(JobRepository jobRepository) { - this.jobRepository = jobRepository; - } - - /** - * Public setter for the {@link PlatformTransactionManager}. - * - * @param transactionManager the transaction manager to set - */ - public void setTransactionManager(PlatformTransactionManager transactionManager) { - this.transactionManager = transactionManager; - } - - /** - * Public setter for the {@link ItemHandler}. - * @param itemHandler the {@link ItemHandler} to set - */ - public void setItemHandler(ItemHandler itemHandler) { - this.itemHandler = itemHandler; - } - - /** - * Register each of the streams for callbacks at the appropriate time in the - * step. The {@link ItemReader} and {@link ItemWriter} are automatically - * registered, but it doesn't hurt to also register them here. Injected - * dependencies of the reader and writer are not automatically registered, - * so if you implement {@link ItemWriter} using delegation to another object - * which itself is a {@link ItemStream}, you need to register the delegate - * here. - * - * @param streams an array of {@link ItemStream} objects. - */ - public void setStreams(ItemStream[] streams) { - for (int i = 0; i < streams.length; i++) { - registerStream(streams[i]); - } - } - - /** - * Register a single {@link ItemStream} for callbacks to the stream - * interface. - * @param stream - */ - public void registerStream(ItemStream stream) { - this.stream.register(stream); - } - - /** - * Register each of the objects as listeners. If the {@link ItemReader} or - * {@link ItemWriter} themselves implements this interface they will be - * registered automatically, but their injected dependencies will not be. - * This is a good way to get access to job parameters and execution context - * if the tasklet is parameterised. - * - * @param listeners an array of listener objects of known types. - */ - public void setStepListeners(StepListener[] listeners) { - for (int i = 0; i < listeners.length; i++) { - registerStepListener(listeners[i]); - } - } - - /** - * Register a step listener for callbacks at the appropriate stages in a - * step execution. - * - * @param listener a {@link StepListener} - */ - public void registerStepListener(StepListener listener) { - this.listener.register(listener); - } - - /** - * The {@link RepeatOperations} to use for the outer loop of the batch - * processing. Should be set up by the caller through a factory. Defaults to - * a plain {@link RepeatTemplate}. - * - * @param stepOperations a {@link RepeatOperations} instance. - */ - public void setStepOperations(RepeatOperations stepOperations) { - this.stepOperations = stepOperations; - } - - /** - * The {@link RepeatOperations} to use for the inner loop of the batch - * processing. should be set up by the caller through a factory. defaults to - * a plain {@link RepeatTemplate}. - * - * @param chunkOperations a {@link RepeatOperations} instance. - */ - public void setChunkOperations(RepeatOperations chunkOperations) { - this.chunkOperations = chunkOperations; - } - - /** - * Setter for the {@link StepInterruptionPolicy}. The policy is used to - * check whether an external request has been made to interrupt the job - * execution. - * - * @param interruptionPolicy a {@link StepInterruptionPolicy} - */ - public void setInterruptionPolicy(StepInterruptionPolicy interruptionPolicy) { - this.interruptionPolicy = interruptionPolicy; - } - - /** - * Setter for the {@link ExitStatusExceptionClassifier} that will be used to - * classify any exception that causes a job to fail. - * - * @param exceptionClassifier - */ - public void setExceptionClassifier(ExitStatusExceptionClassifier exceptionClassifier) { - this.exceptionClassifier = exceptionClassifier; - } - - /** - * Mostly useful for testing, but could be used to remove dependence on - * backport concurrency utilities. Public setter for the - * {@link StepExecutionSynchronizer}. - * @param synchronizer the {@link StepExecutionSynchronizer} to set - */ - public void setSynchronizer(StepExecutionSynchronizer synchronizer) { - this.synchronizer = synchronizer; - } - - /** - * Process the step and update its context so that progress can be monitored - * by the caller. The step is broken down into chunks, each one executing in - * a transaction. The step and its execution and execution context are all - * given an up to date {@link BatchStatus}, and the {@link JobRepository} - * is used to store the result. Various reporting information are also added - * to the current context (the {@link RepeatContext} governing the step - * execution, which would normally be available to the caller somehow - * through the step's {@link JobExecutionContext}.
- * - * @throws JobInterruptedException if the step or a chunk is interrupted - * @throws RuntimeException if there is an exception during a chunk - * execution - * @see StepExecutor#execute(StepExecution) - */ - public void execute(final StepExecution stepExecution) throws InfrastructureException, JobInterruptedException { - - JobInstance jobInstance = stepExecution.getJobExecution().getJobInstance(); - StepExecution lastStepExecution = jobRepository.getLastStepExecution(jobInstance, this); - - boolean isRestart = jobRepository.getStepExecutionCount(jobInstance, this) > 0 ? true : false; - - ExitStatus status = ExitStatus.FAILED; - final ExceptionHolder fatalException = new ExceptionHolder(); - - try { - - stepExecution.setStartTime(new Date(System.currentTimeMillis())); - // We need to save the step execution right away, before we start - // using its ID. It would be better to make the creation atomic in - // the caller. - fatalException.setException(updateStatus(stepExecution, BatchStatus.STARTED)); - - if (isRestart && lastStepExecution != null) { - stepExecution.setExecutionContext(lastStepExecution.getExecutionContext()); - } - else { - stepExecution.setExecutionContext(new ExecutionContext()); - } - - // Execute step level listeners *after* the execution context is - // fixed in the step. E.g. ItemStream instances need the the same - // reference to the ExecutionContext as the step execution. - listener.beforeStep(stepExecution); - stream.open(stepExecution.getExecutionContext()); - - status = stepOperations.iterate(new RepeatCallback() { - - public ExitStatus doInIteration(final RepeatContext context) throws Exception { - - final StepContribution contribution = stepExecution.createStepContribution(); - contribution.setExecutionContext(stepExecution.getExecutionContext()); - // Before starting a new transaction, check for - // interruption. - interruptionPolicy.checkInterrupted(context); - - ExitStatus result = ExitStatus.CONTINUABLE; - - TransactionStatus transaction = transactionManager - .getTransaction(new DefaultTransactionDefinition()); - - try { - - itemHandler.mark(); - result = processChunk(contribution); - contribution.incrementCommitCount(); - - // If the step operations are asynchronous then we need - // to synchronize changes to the step execution (at a - // minimum). - try { - synchronizer.lock(stepExecution); - } - catch (InterruptedException e) { - stepExecution.setStatus(BatchStatus.STOPPED); - Thread.currentThread().interrupt(); - } - - // Apply the contribution to the step - // only if chunk was successful - stepExecution.apply(contribution); - - stream.update(stepExecution.getExecutionContext()); - try { - jobRepository.saveOrUpdateExecutionContext(stepExecution); - } - catch (Exception e) { - fatalException.setException(e); - stepExecution.setStatus(BatchStatus.UNKNOWN); - throw new CommitFailedException( - "Fatal error detected during save of step execution context", e); - } - - try { - itemHandler.mark(); - itemHandler.flush(); - transactionManager.commit(transaction); - } - catch (Exception e) { - fatalException.setException(e); - stepExecution.setStatus(BatchStatus.UNKNOWN); - throw new CommitFailedException("Fatal error detected during commit", e); - } - - } - catch (CommitFailedException e) { - throw e; - } - catch (Throwable t) { - /* - * Any exception thrown within the transaction template - * will automatically cause the transaction to rollback. - * We need to include exceptions during an attempted - * commit (e.g. Hibernate flush) so this catch block - * comes outside the transaction. - */ - stepExecution.rollback(); - - try { - itemHandler.reset(); - itemHandler.clear(); - transactionManager.rollback(transaction); - } - catch (Exception e) { - fatalException.setException(e); - stepExecution.setStatus(BatchStatus.UNKNOWN); - } - - if (t instanceof RuntimeException) { - throw (RuntimeException) t; - } - else { - throw new RuntimeException(t); - } - - } - finally { - synchronizer.release(stepExecution); - } - - // Check for interruption after transaction as well, so that - // the interrupted exception is correctly propagated up to - // caller - interruptionPolicy.checkInterrupted(context); - - return result; - - } - }); - - fatalException.setException(updateStatus(stepExecution, BatchStatus.COMPLETED)); - } - catch (CommitFailedException e) { - logger.error("Fatal error detected during commit."); - throw e; - } - catch (RuntimeException e) { - - // classify exception so an exit code can be stored. - status = exceptionClassifier.classifyForExitCode(e); - - if (e.getCause() instanceof JobInterruptedException) { - updateStatus(stepExecution, BatchStatus.STOPPED); - throw (JobInterruptedException) e.getCause(); - } - else if (!fatalException.hasException()) { - try { - status = status.and(listener.onErrorInStep(stepExecution, e)); - } - catch (RuntimeException ex) { - logger.error("Unexpected error in listener on error in step.", ex); - } - updateStatus(stepExecution, BatchStatus.FAILED); - throw e; - } - else { - logger.error("Fatal error detected during rollback caused by underlying exception: ", e); - throw e; - } - - } - finally { - - try { - status = status.and(listener.afterStep(stepExecution)); - } - catch (RuntimeException e) { - logger.error("Unexpected error in listener after step.", e); - } - - stepExecution.setExitStatus(status); - stepExecution.setEndTime(new Date(System.currentTimeMillis())); - - try { - jobRepository.saveOrUpdate(stepExecution); - } - catch (RuntimeException e) { - String msg = "Fatal error detected during final save of meta data"; - logger.error(msg, e); - if (!fatalException.hasException()) { - fatalException.setException(e); - } - throw new InfrastructureException(msg, fatalException.getException()); - } - - try { - stream.close(stepExecution.getExecutionContext()); - } - catch (RuntimeException e) { - String msg = "Fatal error detected during close of streams. " - + "The job execution completed (possibly unsuccessfully but with consistent meta-data)."; - logger.error(msg, e); - if (!fatalException.hasException()) { - fatalException.setException(e); - } - throw new InfrastructureException(msg, fatalException.getException()); - } - - if (fatalException.hasException()) { - throw new InfrastructureException("Encountered an error saving batch meta data.", fatalException - .getException()); - } - - } - - } - - /** - * Execute a bunch of identical business logic operations all within a - * transaction. The transaction is programmatically started and stopped - * outside this method, so subclasses that override do not need to create a - * transaction. - * - * @param step the current step containing the {@link Tasklet} with the - * business logic. - * @return true if there is more data to process. - */ - protected ExitStatus processChunk(final StepContribution contribution) { - ExitStatus result = chunkOperations.iterate(new RepeatCallback() { - public ExitStatus doInIteration(final RepeatContext context) throws Exception { - if (contribution.isTerminateOnly()) { - context.setTerminateOnly(); - } - // check for interruption before each item as well - interruptionPolicy.checkInterrupted(context); - ExitStatus exitStatus = itemHandler.handle(contribution); - contribution.incrementTaskCount(); - // check for interruption after each item as well - interruptionPolicy.checkInterrupted(context); - return exitStatus; - } - }); - return result; - } - - /** - * Convenience method to update the status in all relevant places. - * - * @param stepInstance the current step - * @param stepExecution the current stepExecution - * @param status the status to set - */ - private Exception updateStatus(StepExecution stepExecution, BatchStatus status) { - stepExecution.setStatus(status); - try { - jobRepository.saveOrUpdate(stepExecution); - return null; - } - catch (Exception e) { - return e; - } - - } - - /** - * @author Dave Syer - * - */ - private static class ExceptionHolder { - - private Exception exception; - - public boolean hasException() { - return exception != null; - } - - /** - * @param exception - */ - public void setException(Exception exception) { - this.exception = exception; - } - - /** - * @return - */ - public Exception getException() { - return this.exception; - } - - } - -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.execution.step; + +import java.util.Date; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.batch.core.domain.BatchStatus; +import org.springframework.batch.core.domain.JobInstance; +import org.springframework.batch.core.domain.JobInterruptedException; +import org.springframework.batch.core.domain.StepContribution; +import org.springframework.batch.core.domain.StepExecution; +import org.springframework.batch.core.domain.StepListener; +import org.springframework.batch.core.repository.JobRepository; +import org.springframework.batch.core.runtime.ExitStatusExceptionClassifier; +import org.springframework.batch.core.tasklet.Tasklet; +import org.springframework.batch.execution.listener.CompositeStepListener; +import org.springframework.batch.execution.step.support.DefaultStepExecutionSynchronizer; +import org.springframework.batch.execution.step.support.SimpleExitStatusExceptionClassifier; +import org.springframework.batch.execution.step.support.StepExecutionSynchronizer; +import org.springframework.batch.execution.step.support.StepInterruptionPolicy; +import org.springframework.batch.execution.step.support.ThreadStepInterruptionPolicy; +import org.springframework.batch.io.exception.InfrastructureException; +import org.springframework.batch.item.ExecutionContext; +import org.springframework.batch.item.ItemReader; +import org.springframework.batch.item.ItemStream; +import org.springframework.batch.item.ItemWriter; +import org.springframework.batch.item.exception.CommitFailedException; +import org.springframework.batch.item.stream.CompositeItemStream; +import org.springframework.batch.repeat.ExitStatus; +import org.springframework.batch.repeat.RepeatCallback; +import org.springframework.batch.repeat.RepeatContext; +import org.springframework.batch.repeat.RepeatOperations; +import org.springframework.batch.repeat.support.RepeatTemplate; +import org.springframework.transaction.PlatformTransactionManager; +import org.springframework.transaction.TransactionStatus; +import org.springframework.transaction.support.DefaultTransactionDefinition; + +/** + * Simple implementation of executing the step as a set of chunks, each chunk + * surrounded by a transaction. The structure is therefore that of two nested + * loops, with transaction boundary around the whole inner loop. The outer loop + * is controlled by the step operations ({@link #setStepOperations(RepeatOperations)}), + * and the inner loop by the chunk operations ({@link #setChunkOperations(RepeatOperations)}). + * The inner loop should always be executed in a single thread, so the chunk + * operations should not do any concurrent execution. N.B. usually that means + * that the chunk operations should be a {@link RepeatTemplate} (which is the + * default).
+ * + * Clients can use interceptors in the step operations to intercept or listen to + * the iteration on a step-wide basis, for instance to get a callback when the + * step is complete. Those that want callbacks at the level of an individual + * tasks, can specify interceptors for the chunk operations. + * + * @author Dave Syer + * @author Lucas Ward + * @author Ben Hale + */ +public class ItemOrientedStep extends AbstractStep { + + private static final Log logger = LogFactory.getLog(ItemOrientedStep.class); + + private RepeatOperations chunkOperations = new RepeatTemplate(); + + private RepeatOperations stepOperations = new RepeatTemplate(); + + private ExitStatusExceptionClassifier exceptionClassifier = new SimpleExitStatusExceptionClassifier(); + + // default to checking current thread for interruption. + private StepInterruptionPolicy interruptionPolicy = new ThreadStepInterruptionPolicy(); + + private CompositeItemStream stream = new CompositeItemStream(); + + private CompositeStepListener listener = new CompositeStepListener(); + + private JobRepository jobRepository; + + private PlatformTransactionManager transactionManager; + + private ItemHandler itemHandler; + + private StepExecutionSynchronizer synchronizer = new DefaultStepExecutionSynchronizer(); + + /** + * @param name + */ + public ItemOrientedStep(String name) { + super(name); + } + + /** + * Public setter for {@link JobRepository}. + * + * @param jobRepository is a mandatory dependence (no default). + */ + public void setJobRepository(JobRepository jobRepository) { + this.jobRepository = jobRepository; + } + + /** + * Public setter for the {@link PlatformTransactionManager}. + * + * @param transactionManager the transaction manager to set + */ + public void setTransactionManager(PlatformTransactionManager transactionManager) { + this.transactionManager = transactionManager; + } + + /** + * Public setter for the {@link ItemHandler}. + * @param itemHandler the {@link ItemHandler} to set + */ + public void setItemHandler(ItemHandler itemHandler) { + this.itemHandler = itemHandler; + } + + /** + * Register each of the streams for callbacks at the appropriate time in the + * step. The {@link ItemReader} and {@link ItemWriter} are automatically + * registered, but it doesn't hurt to also register them here. Injected + * dependencies of the reader and writer are not automatically registered, + * so if you implement {@link ItemWriter} using delegation to another object + * which itself is a {@link ItemStream}, you need to register the delegate + * here. + * + * @param streams an array of {@link ItemStream} objects. + */ + public void setStreams(ItemStream[] streams) { + for (int i = 0; i < streams.length; i++) { + registerStream(streams[i]); + } + } + + /** + * Register a single {@link ItemStream} for callbacks to the stream + * interface. + * @param stream + */ + public void registerStream(ItemStream stream) { + this.stream.register(stream); + } + + /** + * Register each of the objects as listeners. If the {@link ItemReader} or + * {@link ItemWriter} themselves implements this interface they will be + * registered automatically, but their injected dependencies will not be. + * This is a good way to get access to job parameters and execution context + * if the tasklet is parameterised. + * + * @param listeners an array of listener objects of known types. + */ + public void setStepListeners(StepListener[] listeners) { + for (int i = 0; i < listeners.length; i++) { + registerStepListener(listeners[i]); + } + } + + /** + * Register a step listener for callbacks at the appropriate stages in a + * step execution. + * + * @param listener a {@link StepListener} + */ + public void registerStepListener(StepListener listener) { + this.listener.register(listener); + } + + /** + * The {@link RepeatOperations} to use for the outer loop of the batch + * processing. Should be set up by the caller through a factory. Defaults to + * a plain {@link RepeatTemplate}. + * + * @param stepOperations a {@link RepeatOperations} instance. + */ + public void setStepOperations(RepeatOperations stepOperations) { + this.stepOperations = stepOperations; + } + + /** + * The {@link RepeatOperations} to use for the inner loop of the batch + * processing. should be set up by the caller through a factory. defaults to + * a plain {@link RepeatTemplate}. + * + * @param chunkOperations a {@link RepeatOperations} instance. + */ + public void setChunkOperations(RepeatOperations chunkOperations) { + this.chunkOperations = chunkOperations; + } + + /** + * Setter for the {@link StepInterruptionPolicy}. The policy is used to + * check whether an external request has been made to interrupt the job + * execution. + * + * @param interruptionPolicy a {@link StepInterruptionPolicy} + */ + public void setInterruptionPolicy(StepInterruptionPolicy interruptionPolicy) { + this.interruptionPolicy = interruptionPolicy; + } + + /** + * Setter for the {@link ExitStatusExceptionClassifier} that will be used to + * classify any exception that causes a job to fail. + * + * @param exceptionClassifier + */ + public void setExceptionClassifier(ExitStatusExceptionClassifier exceptionClassifier) { + this.exceptionClassifier = exceptionClassifier; + } + + /** + * Mostly useful for testing, but could be used to remove dependence on + * backport concurrency utilities. Public setter for the + * {@link StepExecutionSynchronizer}. + * @param synchronizer the {@link StepExecutionSynchronizer} to set + */ + public void setSynchronizer(StepExecutionSynchronizer synchronizer) { + this.synchronizer = synchronizer; + } + + /** + * Process the step and update its context so that progress can be monitored + * by the caller. The step is broken down into chunks, each one executing in + * a transaction. The step and its execution and execution context are all + * given an up to date {@link BatchStatus}, and the {@link JobRepository} + * is used to store the result. Various reporting information are also added + * to the current context (the {@link RepeatContext} governing the step + * execution, which would normally be available to the caller somehow + * through the step's {@link JobExecutionContext}.
+ * + * @throws JobInterruptedException if the step or a chunk is interrupted + * @throws RuntimeException if there is an exception during a chunk + * execution + * @see StepExecutor#execute(StepExecution) + */ + public void execute(final StepExecution stepExecution) throws InfrastructureException, JobInterruptedException { + + JobInstance jobInstance = stepExecution.getJobExecution().getJobInstance(); + StepExecution lastStepExecution = jobRepository.getLastStepExecution(jobInstance, this); + + boolean isRestart = jobRepository.getStepExecutionCount(jobInstance, this) > 0 ? true : false; + + ExitStatus status = ExitStatus.FAILED; + final ExceptionHolder fatalException = new ExceptionHolder(); + + try { + + stepExecution.setStartTime(new Date(System.currentTimeMillis())); + // We need to save the step execution right away, before we start + // using its ID. It would be better to make the creation atomic in + // the caller. + fatalException.setException(updateStatus(stepExecution, BatchStatus.STARTED)); + + if (isRestart && lastStepExecution != null) { + stepExecution.setExecutionContext(lastStepExecution.getExecutionContext()); + } + else { + stepExecution.setExecutionContext(new ExecutionContext()); + } + + // Execute step level listeners *after* the execution context is + // fixed in the step. E.g. ItemStream instances need the the same + // reference to the ExecutionContext as the step execution. + listener.beforeStep(stepExecution); + stream.open(stepExecution.getExecutionContext()); + + status = stepOperations.iterate(new RepeatCallback() { + + public ExitStatus doInIteration(final RepeatContext context) throws Exception { + + final StepContribution contribution = stepExecution.createStepContribution(); + contribution.setExecutionContext(stepExecution.getExecutionContext()); + // Before starting a new transaction, check for + // interruption. + interruptionPolicy.checkInterrupted(context); + + ExitStatus result = ExitStatus.CONTINUABLE; + + TransactionStatus transaction = transactionManager + .getTransaction(new DefaultTransactionDefinition()); + + try { + + itemHandler.mark(); + result = processChunk(contribution); + contribution.incrementCommitCount(); + + // If the step operations are asynchronous then we need + // to synchronize changes to the step execution (at a + // minimum). + try { + synchronizer.lock(stepExecution); + } + catch (InterruptedException e) { + stepExecution.setStatus(BatchStatus.STOPPED); + Thread.currentThread().interrupt(); + } + + // Apply the contribution to the step + // only if chunk was successful + stepExecution.apply(contribution); + + stream.update(stepExecution.getExecutionContext()); + try { + jobRepository.saveOrUpdateExecutionContext(stepExecution); + } + catch (Exception e) { + fatalException.setException(e); + stepExecution.setStatus(BatchStatus.UNKNOWN); + throw new CommitFailedException( + "Fatal error detected during save of step execution context", e); + } + + try { + itemHandler.mark(); + itemHandler.flush(); + transactionManager.commit(transaction); + } + catch (Exception e) { + fatalException.setException(e); + stepExecution.setStatus(BatchStatus.UNKNOWN); + throw new CommitFailedException("Fatal error detected during commit", e); + } + + } + catch (CommitFailedException e) { + throw e; + } + catch (Throwable t) { + /* + * Any exception thrown within the transaction template + * will automatically cause the transaction to rollback. + * We need to include exceptions during an attempted + * commit (e.g. Hibernate flush) so this catch block + * comes outside the transaction. + */ + stepExecution.rollback(); + + try { + itemHandler.reset(); + itemHandler.clear(); + transactionManager.rollback(transaction); + } + catch (Exception e) { + fatalException.setException(e); + stepExecution.setStatus(BatchStatus.UNKNOWN); + } + + if (t instanceof RuntimeException) { + throw (RuntimeException) t; + } + else { + throw new RuntimeException(t); + } + + } + finally { + synchronizer.release(stepExecution); + } + + // Check for interruption after transaction as well, so that + // the interrupted exception is correctly propagated up to + // caller + interruptionPolicy.checkInterrupted(context); + + return result; + + } + }); + + fatalException.setException(updateStatus(stepExecution, BatchStatus.COMPLETED)); + } + catch (CommitFailedException e) { + logger.error("Fatal error detected during commit."); + throw e; + } + catch (RuntimeException e) { + + // classify exception so an exit code can be stored. + status = exceptionClassifier.classifyForExitCode(e); + + if (e.getCause() instanceof JobInterruptedException) { + updateStatus(stepExecution, BatchStatus.STOPPED); + throw (JobInterruptedException) e.getCause(); + } + else if (!fatalException.hasException()) { + try { + status = status.and(listener.onErrorInStep(stepExecution, e)); + } + catch (RuntimeException ex) { + logger.error("Unexpected error in listener on error in step.", ex); + } + updateStatus(stepExecution, BatchStatus.FAILED); + throw e; + } + else { + logger.error("Fatal error detected during rollback caused by underlying exception: ", e); + throw e; + } + + } + finally { + + try { + status = status.and(listener.afterStep(stepExecution)); + } + catch (RuntimeException e) { + logger.error("Unexpected error in listener after step.", e); + } + + stepExecution.setExitStatus(status); + stepExecution.setEndTime(new Date(System.currentTimeMillis())); + + try { + jobRepository.saveOrUpdate(stepExecution); + } + catch (RuntimeException e) { + String msg = "Fatal error detected during final save of meta data"; + logger.error(msg, e); + if (!fatalException.hasException()) { + fatalException.setException(e); + } + throw new InfrastructureException(msg, fatalException.getException()); + } + + try { + stream.close(stepExecution.getExecutionContext()); + } + catch (RuntimeException e) { + String msg = "Fatal error detected during close of streams. " + + "The job execution completed (possibly unsuccessfully but with consistent meta-data)."; + logger.error(msg, e); + if (!fatalException.hasException()) { + fatalException.setException(e); + } + throw new InfrastructureException(msg, fatalException.getException()); + } + + if (fatalException.hasException()) { + throw new InfrastructureException("Encountered an error saving batch meta data.", fatalException + .getException()); + } + + } + + } + + /** + * Execute a bunch of identical business logic operations all within a + * transaction. The transaction is programmatically started and stopped + * outside this method, so subclasses that override do not need to create a + * transaction. + * + * @param step the current step containing the {@link Tasklet} with the + * business logic. + * @return true if there is more data to process. + */ + protected ExitStatus processChunk(final StepContribution contribution) { + ExitStatus result = chunkOperations.iterate(new RepeatCallback() { + public ExitStatus doInIteration(final RepeatContext context) throws Exception { + if (contribution.isTerminateOnly()) { + context.setTerminateOnly(); + } + // check for interruption before each item as well + interruptionPolicy.checkInterrupted(context); + ExitStatus exitStatus = itemHandler.handle(contribution); + contribution.incrementTaskCount(); + // check for interruption after each item as well + interruptionPolicy.checkInterrupted(context); + return exitStatus; + } + }); + return result; + } + + /** + * Convenience method to update the status in all relevant places. + * + * @param stepInstance the current step + * @param stepExecution the current stepExecution + * @param status the status to set + */ + private Exception updateStatus(StepExecution stepExecution, BatchStatus status) { + stepExecution.setStatus(status); + try { + jobRepository.saveOrUpdate(stepExecution); + return null; + } + catch (Exception e) { + return e; + } + + } + + /** + * @author Dave Syer + * + */ + private static class ExceptionHolder { + + private Exception exception; + + public boolean hasException() { + return exception != null; + } + + /** + * @param exception + */ + public void setException(Exception exception) { + this.exception = exception; + } + + /** + * @return + */ + public Exception getException() { + return this.exception; + } + + } + +} diff --git a/spring-batch-execution/src/main/java/org/springframework/batch/execution/step/support/AbstractStepFactoryBean.java b/spring-batch-execution/src/main/java/org/springframework/batch/execution/step/support/AbstractStepFactoryBean.java index 7ee7975c13..b76dc6b3c3 100644 --- a/spring-batch-execution/src/main/java/org/springframework/batch/execution/step/support/AbstractStepFactoryBean.java +++ b/spring-batch-execution/src/main/java/org/springframework/batch/execution/step/support/AbstractStepFactoryBean.java @@ -1,198 +1,198 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.execution.step.support; - -import org.springframework.batch.core.domain.Step; -import org.springframework.batch.core.repository.JobRepository; -import org.springframework.batch.execution.step.ItemOrientedStep; -import org.springframework.batch.item.ItemReader; -import org.springframework.batch.item.ItemWriter; -import org.springframework.beans.factory.BeanNameAware; -import org.springframework.beans.factory.FactoryBean; -import org.springframework.transaction.PlatformTransactionManager; -import org.springframework.util.Assert; - -/** - * Base class for factory beans for {@link ItemOrientedStep}. Ensures that all - * the mandatory properties are set, and provides basic support for the - * {@link Step} interface responsibilities like start limit. - * - * @author Dave Syer - * - */ -public abstract class AbstractStepFactoryBean implements FactoryBean, BeanNameAware { - - private String name; - - private int startLimit = Integer.MAX_VALUE; - - private boolean allowStartIfComplete; - - private ItemReader itemReader; - - private ItemWriter itemWriter; - - private PlatformTransactionManager transactionManager; - - private JobRepository jobRepository; - - private boolean singleton = true; - - /** - * - */ - public AbstractStepFactoryBean() { - super(); - } - - /** - * Set the bean name property, which will become the name of the - * {@link Step} when it is created. - * - * @see org.springframework.beans.factory.BeanNameAware#setBeanName(java.lang.String) - */ - public void setBeanName(String name) { - this.name = name; - } - - /** - * Public getter for the String. - * @return the name - */ - public String getName() { - return name; - } - - /** - * Public setter for the startLimit. - * - * @param startLimit the startLimit to set - */ - public void setStartLimit(int startLimit) { - this.startLimit = startLimit; - } - - /** - * Public setter for the shouldAllowStartIfComplete. - * - * @param allowStartIfComplete the shouldAllowStartIfComplete to set - */ - public void setAllowStartIfComplete(boolean allowStartIfComplete) { - this.allowStartIfComplete = allowStartIfComplete; - } - - /** - * @param itemReader the itemReader to set - */ - public void setItemReader(ItemReader itemReader) { - this.itemReader = itemReader; - } - - /** - * @param itemWriter the itemWriter to set - */ - public void setItemWriter(ItemWriter itemWriter) { - this.itemWriter = itemWriter; - } - - /** - * Protected getter for the {@link ItemReader} for subclasses to use. - * @return the itemReader - */ - protected ItemReader getItemReader() { - return itemReader; - } - - /** - * Protected getter for the {@link ItemWriter} for subclasses to use - * @return the itemWriter - */ - protected ItemWriter getItemWriter() { - return itemWriter; - } - - /** - * Public setter for {@link JobRepository}. - * - * @param jobRepository is a mandatory dependence (no default). - */ - public void setJobRepository(JobRepository jobRepository) { - this.jobRepository = jobRepository; - } - - /** - * Public setter for the {@link PlatformTransactionManager}. - * - * @param transactionManager the transaction manager to set - */ - public void setTransactionManager(PlatformTransactionManager transactionManager) { - this.transactionManager = transactionManager; - } - - /** - * Create a {@link Step} from the configuration provided. - * - * @see org.springframework.beans.factory.FactoryBean#getObject() - */ - public final Object getObject() throws Exception { - ItemOrientedStep step = new ItemOrientedStep(getName()); - applyConfiguration(step); - return step; - } - - /** - * @param step - * - */ - protected void applyConfiguration(ItemOrientedStep step) { - - Assert.notNull(getItemReader(), "ItemReader must be provided"); - Assert.notNull(getItemWriter(), "ItemWriter must be provided"); - Assert.notNull(jobRepository, "JobRepository must be provided"); - Assert.notNull(transactionManager, "TransactionManager must be provided"); - - step.setItemHandler(new SimpleItemHandler(itemReader, itemWriter)); - step.setTransactionManager(transactionManager); - step.setJobRepository(jobRepository); - step.setStartLimit(startLimit); - step.setAllowStartIfComplete(allowStartIfComplete); - - } - - public Class getObjectType() { - return Step.class; - } - - /** - * Returns true by default, but in most cases a {@link Step} should not be - * treated as thread safe. Clients are recommended to create a new step for - * each job execution. - * - * @see org.springframework.beans.factory.FactoryBean#isSingleton() - */ - public boolean isSingleton() { - return this.singleton; - } - - /** - * Public setter for the singleton flag. - * @param singleton the value to set. Defaults to true. - */ - public void setSingleton(boolean singleton) { - this.singleton = singleton; - } - +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.execution.step.support; + +import org.springframework.batch.core.domain.Step; +import org.springframework.batch.core.repository.JobRepository; +import org.springframework.batch.execution.step.ItemOrientedStep; +import org.springframework.batch.item.ItemReader; +import org.springframework.batch.item.ItemWriter; +import org.springframework.beans.factory.BeanNameAware; +import org.springframework.beans.factory.FactoryBean; +import org.springframework.transaction.PlatformTransactionManager; +import org.springframework.util.Assert; + +/** + * Base class for factory beans for {@link ItemOrientedStep}. Ensures that all + * the mandatory properties are set, and provides basic support for the + * {@link Step} interface responsibilities like start limit. + * + * @author Dave Syer + * + */ +public abstract class AbstractStepFactoryBean implements FactoryBean, BeanNameAware { + + private String name; + + private int startLimit = Integer.MAX_VALUE; + + private boolean allowStartIfComplete; + + private ItemReader itemReader; + + private ItemWriter itemWriter; + + private PlatformTransactionManager transactionManager; + + private JobRepository jobRepository; + + private boolean singleton = true; + + /** + * + */ + public AbstractStepFactoryBean() { + super(); + } + + /** + * Set the bean name property, which will become the name of the + * {@link Step} when it is created. + * + * @see org.springframework.beans.factory.BeanNameAware#setBeanName(java.lang.String) + */ + public void setBeanName(String name) { + this.name = name; + } + + /** + * Public getter for the String. + * @return the name + */ + public String getName() { + return name; + } + + /** + * Public setter for the startLimit. + * + * @param startLimit the startLimit to set + */ + public void setStartLimit(int startLimit) { + this.startLimit = startLimit; + } + + /** + * Public setter for the shouldAllowStartIfComplete. + * + * @param allowStartIfComplete the shouldAllowStartIfComplete to set + */ + public void setAllowStartIfComplete(boolean allowStartIfComplete) { + this.allowStartIfComplete = allowStartIfComplete; + } + + /** + * @param itemReader the itemReader to set + */ + public void setItemReader(ItemReader itemReader) { + this.itemReader = itemReader; + } + + /** + * @param itemWriter the itemWriter to set + */ + public void setItemWriter(ItemWriter itemWriter) { + this.itemWriter = itemWriter; + } + + /** + * Protected getter for the {@link ItemReader} for subclasses to use. + * @return the itemReader + */ + protected ItemReader getItemReader() { + return itemReader; + } + + /** + * Protected getter for the {@link ItemWriter} for subclasses to use + * @return the itemWriter + */ + protected ItemWriter getItemWriter() { + return itemWriter; + } + + /** + * Public setter for {@link JobRepository}. + * + * @param jobRepository is a mandatory dependence (no default). + */ + public void setJobRepository(JobRepository jobRepository) { + this.jobRepository = jobRepository; + } + + /** + * Public setter for the {@link PlatformTransactionManager}. + * + * @param transactionManager the transaction manager to set + */ + public void setTransactionManager(PlatformTransactionManager transactionManager) { + this.transactionManager = transactionManager; + } + + /** + * Create a {@link Step} from the configuration provided. + * + * @see org.springframework.beans.factory.FactoryBean#getObject() + */ + public final Object getObject() throws Exception { + ItemOrientedStep step = new ItemOrientedStep(getName()); + applyConfiguration(step); + return step; + } + + /** + * @param step + * + */ + protected void applyConfiguration(ItemOrientedStep step) { + + Assert.notNull(getItemReader(), "ItemReader must be provided"); + Assert.notNull(getItemWriter(), "ItemWriter must be provided"); + Assert.notNull(jobRepository, "JobRepository must be provided"); + Assert.notNull(transactionManager, "TransactionManager must be provided"); + + step.setItemHandler(new SimpleItemHandler(itemReader, itemWriter)); + step.setTransactionManager(transactionManager); + step.setJobRepository(jobRepository); + step.setStartLimit(startLimit); + step.setAllowStartIfComplete(allowStartIfComplete); + + } + + public Class getObjectType() { + return Step.class; + } + + /** + * Returns true by default, but in most cases a {@link Step} should not be + * treated as thread safe. Clients are recommended to create a new step for + * each job execution. + * + * @see org.springframework.beans.factory.FactoryBean#isSingleton() + */ + public boolean isSingleton() { + return this.singleton; + } + + /** + * Public setter for the singleton flag. + * @param singleton the value to set. Defaults to true. + */ + public void setSingleton(boolean singleton) { + this.singleton = singleton; + } + } \ No newline at end of file diff --git a/spring-batch-execution/src/main/java/org/springframework/batch/execution/step/support/ItemSkipPolicyItemHandler.java b/spring-batch-execution/src/main/java/org/springframework/batch/execution/step/support/ItemSkipPolicyItemHandler.java index 5768848992..32d0828836 100644 --- a/spring-batch-execution/src/main/java/org/springframework/batch/execution/step/support/ItemSkipPolicyItemHandler.java +++ b/spring-batch-execution/src/main/java/org/springframework/batch/execution/step/support/ItemSkipPolicyItemHandler.java @@ -1,102 +1,102 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.execution.step.support; - -import org.springframework.batch.core.domain.ItemSkipPolicy; -import org.springframework.batch.core.domain.StepContribution; -import org.springframework.batch.io.Skippable; -import org.springframework.batch.item.ItemReader; -import org.springframework.batch.item.ItemWriter; -import org.springframework.batch.repeat.ExitStatus; - -/** - * @author Dave Syer - * - */ -public class ItemSkipPolicyItemHandler extends SimpleItemHandler { - - private ItemSkipPolicy itemSkipPolicy = new NeverSkipItemSkipPolicy(); - - /** - * @param itemReader - * @param itemWriter - */ - public ItemSkipPolicyItemHandler(ItemReader itemReader, ItemWriter itemWriter) { - super(itemReader, itemWriter); - } - - /** - * @param itemSkipPolicy - */ - public void setItemSkipPolicy(ItemSkipPolicy itemSkipPolicy) { - this.itemSkipPolicy = itemSkipPolicy; - } - - /** - * Execute the business logic, delegating to the reader and writer. - * Subclasses could extend the behaviour as long as they always return the - * value of this method call in their superclass.
- * - * Read from the {@link ItemReader} and process (if not null) with the - * {@link ItemWriter}.
- * - * If there is an exception and the reader or writer implements - * {@link Skippable} then the skip method is called. - * - * @param contribution the current step - * @return {@link ExitStatus#CONTINUABLE} if there is more processing to do - * @throws Exception if there is an error - */ - public ExitStatus handle(StepContribution contribution) throws Exception { - ExitStatus exitStatus = ExitStatus.CONTINUABLE; - - try { - - exitStatus = super.handle(contribution); - - } - catch (Exception e) { - - if (itemSkipPolicy.shouldSkip(e, contribution.getSkipCount())) { - contribution.incrementSkipCount(); - skip(); - } - else { - // Rethrow so that outer transaction is rolled back properly - throw e; - } - - } - - return exitStatus; - } - - /** - * Mark the current item as skipped if possible. If the reader and / or - * writer are {@link Skippable} then delegate to them in that order. - * - * @see org.springframework.batch.io.Skippable#skip() - */ - private void skip() { - if (getItemReader() instanceof Skippable) { - ((Skippable) getItemReader()).skip(); - } - if (getItemWriter() instanceof Skippable) { - ((Skippable) getItemWriter()).skip(); - } - } - -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.execution.step.support; + +import org.springframework.batch.core.domain.ItemSkipPolicy; +import org.springframework.batch.core.domain.StepContribution; +import org.springframework.batch.io.Skippable; +import org.springframework.batch.item.ItemReader; +import org.springframework.batch.item.ItemWriter; +import org.springframework.batch.repeat.ExitStatus; + +/** + * @author Dave Syer + * + */ +public class ItemSkipPolicyItemHandler extends SimpleItemHandler { + + private ItemSkipPolicy itemSkipPolicy = new NeverSkipItemSkipPolicy(); + + /** + * @param itemReader + * @param itemWriter + */ + public ItemSkipPolicyItemHandler(ItemReader itemReader, ItemWriter itemWriter) { + super(itemReader, itemWriter); + } + + /** + * @param itemSkipPolicy + */ + public void setItemSkipPolicy(ItemSkipPolicy itemSkipPolicy) { + this.itemSkipPolicy = itemSkipPolicy; + } + + /** + * Execute the business logic, delegating to the reader and writer. + * Subclasses could extend the behaviour as long as they always return the + * value of this method call in their superclass.
+ * + * Read from the {@link ItemReader} and process (if not null) with the + * {@link ItemWriter}.
+ * + * If there is an exception and the reader or writer implements + * {@link Skippable} then the skip method is called. + * + * @param contribution the current step + * @return {@link ExitStatus#CONTINUABLE} if there is more processing to do + * @throws Exception if there is an error + */ + public ExitStatus handle(StepContribution contribution) throws Exception { + ExitStatus exitStatus = ExitStatus.CONTINUABLE; + + try { + + exitStatus = super.handle(contribution); + + } + catch (Exception e) { + + if (itemSkipPolicy.shouldSkip(e, contribution.getSkipCount())) { + contribution.incrementSkipCount(); + skip(); + } + else { + // Rethrow so that outer transaction is rolled back properly + throw e; + } + + } + + return exitStatus; + } + + /** + * Mark the current item as skipped if possible. If the reader and / or + * writer are {@link Skippable} then delegate to them in that order. + * + * @see org.springframework.batch.io.Skippable#skip() + */ + private void skip() { + if (getItemReader() instanceof Skippable) { + ((Skippable) getItemReader()).skip(); + } + if (getItemWriter() instanceof Skippable) { + ((Skippable) getItemWriter()).skip(); + } + } + +} diff --git a/spring-batch-execution/src/main/java/org/springframework/batch/execution/step/support/RepeatOperationsStepFactoryBean.java b/spring-batch-execution/src/main/java/org/springframework/batch/execution/step/support/RepeatOperationsStepFactoryBean.java index 81b7a6be30..c5a32fbc6b 100644 --- a/spring-batch-execution/src/main/java/org/springframework/batch/execution/step/support/RepeatOperationsStepFactoryBean.java +++ b/spring-batch-execution/src/main/java/org/springframework/batch/execution/step/support/RepeatOperationsStepFactoryBean.java @@ -1,140 +1,140 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.execution.step.support; - -import org.springframework.batch.core.domain.BatchListener; -import org.springframework.batch.core.domain.Step; -import org.springframework.batch.core.domain.StepListener; -import org.springframework.batch.execution.step.ItemOrientedStep; -import org.springframework.batch.item.ItemReader; -import org.springframework.batch.item.ItemStream; -import org.springframework.batch.item.ItemWriter; -import org.springframework.batch.repeat.RepeatOperations; -import org.springframework.batch.repeat.support.RepeatTemplate; - -/** - * Factory bean for {@link Step} implementations allowing registration of - * listeners and also direct injection of the {@link RepeatOperations} needed at - * step and chunk level. - * - * @author Dave Syer - * - */ -public class RepeatOperationsStepFactoryBean extends AbstractStepFactoryBean { - - private ItemStream[] streams = new ItemStream[0]; - - private BatchListener[] listeners = new BatchListener[0]; - - private RepeatOperations chunkOperations = new RepeatTemplate(); - - private RepeatOperations stepOperations = new RepeatTemplate(); - - /** - * The streams to inject into the {@link Step}. Any instance of - * {@link ItemStream} can be used, and will then receive callbacks at the - * appropriate stage in the step. - * - * @param streams an array of listeners - */ - public void setStreams(ItemStream[] streams) { - this.streams = streams; - } - - /** - * The listeners to inject into the {@link Step}. Any instance of - * {@link BatchListener} can be used, and will then receive callbacks at the - * appropriate stage in the step. - * - * @param listeners an array of listeners - */ - public void setListeners(BatchListener[] listeners) { - this.listeners = listeners; - } - - /** - * The {@link RepeatOperations} to use for the outer loop of the batch - * processing. Should be set up by the caller through a factory. Defaults to - * a plain {@link RepeatTemplate}. - * - * @param stepOperations a {@link RepeatOperations} instance. - */ - public void setStepOperations(RepeatOperations stepOperations) { - this.stepOperations = stepOperations; - } - - /** - * The {@link RepeatOperations} to use for the inner loop of the batch - * processing. should be set up by the caller through a factory. defaults to - * a plain {@link RepeatTemplate}. - * - * @param chunkOperations a {@link RepeatOperations} instance. - */ - public void setChunkOperations(RepeatOperations chunkOperations) { - this.chunkOperations = chunkOperations; - } - - /** - * @param step - * - */ - protected void applyConfiguration(ItemOrientedStep step) { - - super.applyConfiguration(step); - - step.setStreams(streams); - - ItemReader itemReader = getItemReader(); - ItemWriter itemWriter = getItemWriter(); - - /* - * Since we are going to wrap these things with listener callbacks we - * need to register them here because the step will not know we did - * that. - */ - if (itemReader instanceof ItemStream) { - step.registerStream((ItemStream) itemReader); - } - if (itemReader instanceof StepListener) { - step.registerStepListener((StepListener) itemReader); - } - if (itemWriter instanceof ItemStream) { - step.registerStream((ItemStream) itemWriter); - } - if (itemWriter instanceof StepListener) { - step.registerStepListener((StepListener) itemWriter); - } - - BatchListenerFactoryHelper helper = new BatchListenerFactoryHelper(); - - StepListener[] stepListeners = helper.getStepListeners(listeners); - itemReader = helper.getItemReader(itemReader, listeners); - itemWriter = helper.getItemWriter(itemWriter, listeners); - RepeatOperations stepOperations = helper.addChunkListeners(this.stepOperations, listeners); - - // In case they are used by subclasses: - setItemReader(itemReader); - setItemWriter(itemWriter); - - step.setStepListeners(stepListeners); - step.setItemHandler(new SimpleItemHandler(itemReader, itemWriter)); - - step.setChunkOperations(chunkOperations); - step.setStepOperations(stepOperations); - - } - -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.execution.step.support; + +import org.springframework.batch.core.domain.BatchListener; +import org.springframework.batch.core.domain.Step; +import org.springframework.batch.core.domain.StepListener; +import org.springframework.batch.execution.step.ItemOrientedStep; +import org.springframework.batch.item.ItemReader; +import org.springframework.batch.item.ItemStream; +import org.springframework.batch.item.ItemWriter; +import org.springframework.batch.repeat.RepeatOperations; +import org.springframework.batch.repeat.support.RepeatTemplate; + +/** + * Factory bean for {@link Step} implementations allowing registration of + * listeners and also direct injection of the {@link RepeatOperations} needed at + * step and chunk level. + * + * @author Dave Syer + * + */ +public class RepeatOperationsStepFactoryBean extends AbstractStepFactoryBean { + + private ItemStream[] streams = new ItemStream[0]; + + private BatchListener[] listeners = new BatchListener[0]; + + private RepeatOperations chunkOperations = new RepeatTemplate(); + + private RepeatOperations stepOperations = new RepeatTemplate(); + + /** + * The streams to inject into the {@link Step}. Any instance of + * {@link ItemStream} can be used, and will then receive callbacks at the + * appropriate stage in the step. + * + * @param streams an array of listeners + */ + public void setStreams(ItemStream[] streams) { + this.streams = streams; + } + + /** + * The listeners to inject into the {@link Step}. Any instance of + * {@link BatchListener} can be used, and will then receive callbacks at the + * appropriate stage in the step. + * + * @param listeners an array of listeners + */ + public void setListeners(BatchListener[] listeners) { + this.listeners = listeners; + } + + /** + * The {@link RepeatOperations} to use for the outer loop of the batch + * processing. Should be set up by the caller through a factory. Defaults to + * a plain {@link RepeatTemplate}. + * + * @param stepOperations a {@link RepeatOperations} instance. + */ + public void setStepOperations(RepeatOperations stepOperations) { + this.stepOperations = stepOperations; + } + + /** + * The {@link RepeatOperations} to use for the inner loop of the batch + * processing. should be set up by the caller through a factory. defaults to + * a plain {@link RepeatTemplate}. + * + * @param chunkOperations a {@link RepeatOperations} instance. + */ + public void setChunkOperations(RepeatOperations chunkOperations) { + this.chunkOperations = chunkOperations; + } + + /** + * @param step + * + */ + protected void applyConfiguration(ItemOrientedStep step) { + + super.applyConfiguration(step); + + step.setStreams(streams); + + ItemReader itemReader = getItemReader(); + ItemWriter itemWriter = getItemWriter(); + + /* + * Since we are going to wrap these things with listener callbacks we + * need to register them here because the step will not know we did + * that. + */ + if (itemReader instanceof ItemStream) { + step.registerStream((ItemStream) itemReader); + } + if (itemReader instanceof StepListener) { + step.registerStepListener((StepListener) itemReader); + } + if (itemWriter instanceof ItemStream) { + step.registerStream((ItemStream) itemWriter); + } + if (itemWriter instanceof StepListener) { + step.registerStepListener((StepListener) itemWriter); + } + + BatchListenerFactoryHelper helper = new BatchListenerFactoryHelper(); + + StepListener[] stepListeners = helper.getStepListeners(listeners); + itemReader = helper.getItemReader(itemReader, listeners); + itemWriter = helper.getItemWriter(itemWriter, listeners); + RepeatOperations stepOperations = helper.addChunkListeners(this.stepOperations, listeners); + + // In case they are used by subclasses: + setItemReader(itemReader); + setItemWriter(itemWriter); + + step.setStepListeners(stepListeners); + step.setItemHandler(new SimpleItemHandler(itemReader, itemWriter)); + + step.setChunkOperations(chunkOperations); + step.setStepOperations(stepOperations); + + } + +} diff --git a/spring-batch-execution/src/main/java/org/springframework/batch/execution/step/support/SimpleExitStatusExceptionClassifier.java b/spring-batch-execution/src/main/java/org/springframework/batch/execution/step/support/SimpleExitStatusExceptionClassifier.java index 9ec3e0c480..2df050afb3 100644 --- a/spring-batch-execution/src/main/java/org/springframework/batch/execution/step/support/SimpleExitStatusExceptionClassifier.java +++ b/spring-batch-execution/src/main/java/org/springframework/batch/execution/step/support/SimpleExitStatusExceptionClassifier.java @@ -1,79 +1,79 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.execution.step.support; - -import java.io.PrintWriter; -import java.io.StringWriter; - -import org.springframework.batch.core.domain.JobInterruptedException; -import org.springframework.batch.core.runtime.ExitStatusExceptionClassifier; -import org.springframework.batch.repeat.ExitStatus; - -/** - *

- * Simple implementation of {@link ExitStatusExceptionClassifier} that returns - * basic String exit codes, and defaults to the class name of the throwable for - * the message. Most users will want to write their own implementation that - * creates more specific exit codes for different exception types. - *

- * - * @author Lucas Ward - * - */ -public class SimpleExitStatusExceptionClassifier implements - ExitStatusExceptionClassifier { - - /* (non-Javadoc) - * @see org.springframework.batch.core.executor.ExitCodeExceptionClassifier#classifyForExitCode(java.lang.Throwable) - */ - public ExitStatus classifyForExitCode(Throwable throwable) { - return (ExitStatus) classify(throwable); - } - - /* (non-Javadoc) - * @see org.springframework.batch.common.ExceptionClassifier#classify(java.lang.Throwable) - */ - public Object classify(Throwable throwable) { - - ExitStatus exitStatus = ExitStatus.FAILED; - - if (throwable instanceof JobInterruptedException) { - exitStatus = new ExitStatus(false, JOB_INTERRUPTED, - JobInterruptedException.class.getName()); - } else { - String message = ""; - if (throwable!=null) { - StringWriter writer = new StringWriter(); - throwable.printStackTrace(new PrintWriter(writer)); - message = writer.toString(); - } - exitStatus = new ExitStatus(false, FATAL_EXCEPTION, message); - } - - return exitStatus; - } - - /* - * (non-Javadoc) - * - * @see org.springframework.batch.common.ExceptionClassifier#getDefault() - */ - public Object getDefault() { - // return without message since we don't know what the exception is - return new ExitStatus(false, FATAL_EXCEPTION); - } - -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.execution.step.support; + +import java.io.PrintWriter; +import java.io.StringWriter; + +import org.springframework.batch.core.domain.JobInterruptedException; +import org.springframework.batch.core.runtime.ExitStatusExceptionClassifier; +import org.springframework.batch.repeat.ExitStatus; + +/** + *

+ * Simple implementation of {@link ExitStatusExceptionClassifier} that returns + * basic String exit codes, and defaults to the class name of the throwable for + * the message. Most users will want to write their own implementation that + * creates more specific exit codes for different exception types. + *

+ * + * @author Lucas Ward + * + */ +public class SimpleExitStatusExceptionClassifier implements + ExitStatusExceptionClassifier { + + /* (non-Javadoc) + * @see org.springframework.batch.core.executor.ExitCodeExceptionClassifier#classifyForExitCode(java.lang.Throwable) + */ + public ExitStatus classifyForExitCode(Throwable throwable) { + return (ExitStatus) classify(throwable); + } + + /* (non-Javadoc) + * @see org.springframework.batch.common.ExceptionClassifier#classify(java.lang.Throwable) + */ + public Object classify(Throwable throwable) { + + ExitStatus exitStatus = ExitStatus.FAILED; + + if (throwable instanceof JobInterruptedException) { + exitStatus = new ExitStatus(false, JOB_INTERRUPTED, + JobInterruptedException.class.getName()); + } else { + String message = ""; + if (throwable!=null) { + StringWriter writer = new StringWriter(); + throwable.printStackTrace(new PrintWriter(writer)); + message = writer.toString(); + } + exitStatus = new ExitStatus(false, FATAL_EXCEPTION, message); + } + + return exitStatus; + } + + /* + * (non-Javadoc) + * + * @see org.springframework.batch.common.ExceptionClassifier#getDefault() + */ + public Object getDefault() { + // return without message since we don't know what the exception is + return new ExitStatus(false, FATAL_EXCEPTION); + } + +} diff --git a/spring-batch-execution/src/main/java/org/springframework/batch/execution/step/support/SimpleItemHandler.java b/spring-batch-execution/src/main/java/org/springframework/batch/execution/step/support/SimpleItemHandler.java index 3e2363f4d4..4ef8d85ac1 100644 --- a/spring-batch-execution/src/main/java/org/springframework/batch/execution/step/support/SimpleItemHandler.java +++ b/spring-batch-execution/src/main/java/org/springframework/batch/execution/step/support/SimpleItemHandler.java @@ -1,115 +1,115 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.execution.step.support; - -import org.springframework.batch.core.domain.StepContribution; -import org.springframework.batch.execution.step.ItemHandler; -import org.springframework.batch.item.ItemReader; -import org.springframework.batch.item.ItemWriter; -import org.springframework.batch.item.exception.ClearFailedException; -import org.springframework.batch.item.exception.FlushFailedException; -import org.springframework.batch.item.exception.MarkFailedException; -import org.springframework.batch.item.exception.ResetFailedException; -import org.springframework.batch.repeat.ExitStatus; - -/** - * Simplest possible implementation of {@link ItemHandler} with no skipping or - * recovering. Just delegates all calls to the provided {@link ItemReader} and - * {@link ItemWriter}. - * - * @author Dave Syer - * - */ -public class SimpleItemHandler implements ItemHandler { - - private ItemReader itemReader; - - private ItemWriter itemWriter; - - /** - * @param itemReader - * @param itemWriter - */ - public SimpleItemHandler(ItemReader itemReader, ItemWriter itemWriter) { - super(); - this.itemReader = itemReader; - this.itemWriter = itemWriter; - } - - /** - * Public getter for the ItemReader. - * @return the itemReader - */ - public ItemReader getItemReader() { - return itemReader; - } - - /** - * Public getter for the ItemWriter. - * @return the itemWriter - */ - public ItemWriter getItemWriter() { - return itemWriter; - } - - /** - * Read from the {@link ItemReader} and process (if not null) with the - * {@link ItemWriter}. - * - * @see org.springframework.batch.execution.step.ItemHandler#handle(org.springframework.batch.core.domain.StepContribution) - */ - public ExitStatus handle(StepContribution contribution) throws Exception { - Object item = itemReader.read(); - if (item == null) { - return ExitStatus.FINISHED; - } - itemWriter.write(item); - return ExitStatus.CONTINUABLE; - } - - /** - * @throws MarkFailedException - * @see org.springframework.batch.item.ItemReader#mark() - */ - public void mark() throws MarkFailedException { - itemReader.mark(); - } - - /** - * @throws ResetFailedException - * @see org.springframework.batch.item.ItemReader#reset() - */ - public void reset() throws ResetFailedException { - itemReader.reset(); - } - - /** - * @throws ClearFailedException - * @see org.springframework.batch.item.ItemWriter#clear() - */ - public void clear() throws ClearFailedException { - itemWriter.clear(); - } - - /** - * @throws FlushFailedException - * @see org.springframework.batch.item.ItemWriter#flush() - */ - public void flush() throws FlushFailedException { - itemWriter.flush(); - } - -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.execution.step.support; + +import org.springframework.batch.core.domain.StepContribution; +import org.springframework.batch.execution.step.ItemHandler; +import org.springframework.batch.item.ItemReader; +import org.springframework.batch.item.ItemWriter; +import org.springframework.batch.item.exception.ClearFailedException; +import org.springframework.batch.item.exception.FlushFailedException; +import org.springframework.batch.item.exception.MarkFailedException; +import org.springframework.batch.item.exception.ResetFailedException; +import org.springframework.batch.repeat.ExitStatus; + +/** + * Simplest possible implementation of {@link ItemHandler} with no skipping or + * recovering. Just delegates all calls to the provided {@link ItemReader} and + * {@link ItemWriter}. + * + * @author Dave Syer + * + */ +public class SimpleItemHandler implements ItemHandler { + + private ItemReader itemReader; + + private ItemWriter itemWriter; + + /** + * @param itemReader + * @param itemWriter + */ + public SimpleItemHandler(ItemReader itemReader, ItemWriter itemWriter) { + super(); + this.itemReader = itemReader; + this.itemWriter = itemWriter; + } + + /** + * Public getter for the ItemReader. + * @return the itemReader + */ + public ItemReader getItemReader() { + return itemReader; + } + + /** + * Public getter for the ItemWriter. + * @return the itemWriter + */ + public ItemWriter getItemWriter() { + return itemWriter; + } + + /** + * Read from the {@link ItemReader} and process (if not null) with the + * {@link ItemWriter}. + * + * @see org.springframework.batch.execution.step.ItemHandler#handle(org.springframework.batch.core.domain.StepContribution) + */ + public ExitStatus handle(StepContribution contribution) throws Exception { + Object item = itemReader.read(); + if (item == null) { + return ExitStatus.FINISHED; + } + itemWriter.write(item); + return ExitStatus.CONTINUABLE; + } + + /** + * @throws MarkFailedException + * @see org.springframework.batch.item.ItemReader#mark() + */ + public void mark() throws MarkFailedException { + itemReader.mark(); + } + + /** + * @throws ResetFailedException + * @see org.springframework.batch.item.ItemReader#reset() + */ + public void reset() throws ResetFailedException { + itemReader.reset(); + } + + /** + * @throws ClearFailedException + * @see org.springframework.batch.item.ItemWriter#clear() + */ + public void clear() throws ClearFailedException { + itemWriter.clear(); + } + + /** + * @throws FlushFailedException + * @see org.springframework.batch.item.ItemWriter#flush() + */ + public void flush() throws FlushFailedException { + itemWriter.flush(); + } + +} diff --git a/spring-batch-execution/src/main/java/org/springframework/batch/execution/step/support/StatefulRetryStepFactoryBean.java b/spring-batch-execution/src/main/java/org/springframework/batch/execution/step/support/StatefulRetryStepFactoryBean.java index 44010ed1ce..4521567f1e 100644 --- a/spring-batch-execution/src/main/java/org/springframework/batch/execution/step/support/StatefulRetryStepFactoryBean.java +++ b/spring-batch-execution/src/main/java/org/springframework/batch/execution/step/support/StatefulRetryStepFactoryBean.java @@ -1,197 +1,197 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.execution.step.support; - -import org.springframework.batch.core.domain.Step; -import org.springframework.batch.core.domain.StepContribution; -import org.springframework.batch.execution.step.ItemOrientedStep; -import org.springframework.batch.item.ItemKeyGenerator; -import org.springframework.batch.item.ItemReader; -import org.springframework.batch.item.ItemRecoverer; -import org.springframework.batch.item.ItemWriter; -import org.springframework.batch.repeat.ExitStatus; -import org.springframework.batch.retry.RetryOperations; -import org.springframework.batch.retry.RetryPolicy; -import org.springframework.batch.retry.backoff.BackOffPolicy; -import org.springframework.batch.retry.callback.ItemReaderRetryCallback; -import org.springframework.batch.retry.policy.ItemReaderRetryPolicy; -import org.springframework.batch.retry.policy.SimpleRetryPolicy; -import org.springframework.batch.retry.support.RetryTemplate; - -/** - * Factory bean for step that executes its item processing with a stateful - * retry. Failed items are never skipped, but always cause a rollback. Before a - * rollback, the {@link Step} makes a record of the failed item, caching it - * under a key given by the {@link ItemKeyGenerator}. Then when it is - * re-presented by the {@link ItemReader} it is recognised and retried up to a - * limit given by the {@link RetryPolicy}. When the retry is exhausted instead - * of the item being skipped it is handled by an {@link ItemRecoverer}.
- * - * The skipLimit property is still used to control the overall exception - * handling policy. Only exhausted retries count against the exception handler, - * instead of counting all exceptions. - * - * @author Dave Syer - * - */ -public class StatefulRetryStepFactoryBean extends DefaultStepFactoryBean { - - private ItemKeyGenerator itemKeyGenerator; - - private ItemRecoverer itemRecoverer; - - private int retryLimit; - - private Class[] retryableExceptionClasses; - - private BackOffPolicy backOffPolicy; - - /** - * Public setter for the retry limit. Each item can be retried up to this - * limit. - * @param retryLimit the retry limit to set - */ - public void setRetryLimit(int retryLimit) { - this.retryLimit = retryLimit; - } - - /** - * Public setter for the Class[]. - * @param retryableExceptionClasses the retryableExceptionClasses to set - */ - public void setRetryableExceptionClasses(Class[] retryableExceptionClasses) { - this.retryableExceptionClasses = retryableExceptionClasses; - } - - /** - * Public setter for the {@link BackOffPolicy}. - * @param backOffPolicy the {@link BackOffPolicy} to set - */ - public void setBackOffPolicy(BackOffPolicy backOffPolicy) { - this.backOffPolicy = backOffPolicy; - } - - /** - * Public setter for the {@link ItemKeyGenerator} which will be used to - * cache failed items between transactions. If it is not injected but the - * reader or writer implement {@link ItemKeyGenerator}, one of those will - * be used instead (preferring the reader to the writer if both would be - * appropriate). If neither can be used, then the default will be to just - * use the item itself as a cache key. - * - * @param itemKeyGenerator the {@link ItemKeyGenerator} to set - */ - public void setItemKeyGenerator(ItemKeyGenerator itemKeyGenerator) { - this.itemKeyGenerator = itemKeyGenerator; - } - - /** - * Public setter for the {@link ItemRecoverer}. If this is set the - * {@link ItemRecoverer#recover(Object, Throwable)} will be called when - * retry is exhausted, and within the business transaction (which will not - * roll back because of any other item-related errors). - * - * @param itemRecoverer the {@link ItemRecoverer} to set - */ - public void setItemRecoverer(ItemRecoverer itemRecoverer) { - this.itemRecoverer = itemRecoverer; - } - - /** - * @param step - * - */ - protected void applyConfiguration(ItemOrientedStep step) { - - super.applyConfiguration(step); - - if (retryLimit > 0) { - - SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy(retryLimit); - if (retryableExceptionClasses != null) { - retryPolicy.setRetryableExceptionClasses(retryableExceptionClasses); - } - - // Co-ordinate the retry policy with the exception handler: - getStepOperations() - .setExceptionHandler(new SimpleRetryExceptionHandler(retryPolicy, getExceptionHandler())); - - ItemReaderRetryCallback retryCallback = new ItemReaderRetryCallback(getItemReader(), itemKeyGenerator, - getItemWriter()); - retryCallback.setRecoverer(itemRecoverer); - ItemReaderRetryPolicy itemProviderRetryPolicy = new ItemReaderRetryPolicy(retryPolicy); - - RetryTemplate retryTemplate = new RetryTemplate(); - retryTemplate.setRetryPolicy(itemProviderRetryPolicy); - if (backOffPolicy != null) { - retryTemplate.setBackOffPolicy(backOffPolicy); - } - - StatefulRetryItemHandler itemProcessor = new StatefulRetryItemHandler(getItemReader(), getItemWriter(), - retryTemplate, retryCallback); - - step.setItemHandler(itemProcessor); - - } - - } - - private static class StatefulRetryItemHandler extends SimpleItemHandler { - - final private RetryOperations retryOperations; - - final private ItemReaderRetryCallback retryCallback; - - /** - * @param itemReader - * @param itemWriter - * @param retryCallback - * @param retryTemplate - */ - public StatefulRetryItemHandler(ItemReader itemReader, ItemWriter itemWriter, RetryOperations retryTemplate, - ItemReaderRetryCallback retryCallback) { - super(itemReader, itemWriter); - this.retryOperations = retryTemplate; - this.retryCallback = retryCallback; - } - - /** - * Execute the business logic, delegating to the reader and writer. - * Subclasses could extend the behaviour as long as they always return - * the value of this method call in their superclass.
- * - * Read from the {@link ItemReader} and process (if not null) with the - * {@link ItemWriter}. The call to {@link ItemWriter} is wrapped in a - * stateful retry. In that case the {@link ItemRecoverer} is used (if - * provided) in the case of an exception to apply alternate processing - * to the item. If the stateful retry is in place then the recovery will - * happen in the next transaction automatically, otherwise it might be - * necessary for clients to make the recover method transactional with - * appropriate propagation behaviour (probably REQUIRES_NEW because the - * call will happen in the context of a transaction that is about to - * rollback).
- * - * @param contribution the current step - * @return {@link ExitStatus#CONTINUABLE} if there is more processing to - * do - * @throws Exception if there is an error - */ - public ExitStatus handle(StepContribution contribution) throws Exception { - return new ExitStatus(retryOperations.execute(retryCallback) != null); - } - - } -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.execution.step.support; + +import org.springframework.batch.core.domain.Step; +import org.springframework.batch.core.domain.StepContribution; +import org.springframework.batch.execution.step.ItemOrientedStep; +import org.springframework.batch.item.ItemKeyGenerator; +import org.springframework.batch.item.ItemReader; +import org.springframework.batch.item.ItemRecoverer; +import org.springframework.batch.item.ItemWriter; +import org.springframework.batch.repeat.ExitStatus; +import org.springframework.batch.retry.RetryOperations; +import org.springframework.batch.retry.RetryPolicy; +import org.springframework.batch.retry.backoff.BackOffPolicy; +import org.springframework.batch.retry.callback.ItemReaderRetryCallback; +import org.springframework.batch.retry.policy.ItemReaderRetryPolicy; +import org.springframework.batch.retry.policy.SimpleRetryPolicy; +import org.springframework.batch.retry.support.RetryTemplate; + +/** + * Factory bean for step that executes its item processing with a stateful + * retry. Failed items are never skipped, but always cause a rollback. Before a + * rollback, the {@link Step} makes a record of the failed item, caching it + * under a key given by the {@link ItemKeyGenerator}. Then when it is + * re-presented by the {@link ItemReader} it is recognised and retried up to a + * limit given by the {@link RetryPolicy}. When the retry is exhausted instead + * of the item being skipped it is handled by an {@link ItemRecoverer}.
+ * + * The skipLimit property is still used to control the overall exception + * handling policy. Only exhausted retries count against the exception handler, + * instead of counting all exceptions. + * + * @author Dave Syer + * + */ +public class StatefulRetryStepFactoryBean extends DefaultStepFactoryBean { + + private ItemKeyGenerator itemKeyGenerator; + + private ItemRecoverer itemRecoverer; + + private int retryLimit; + + private Class[] retryableExceptionClasses; + + private BackOffPolicy backOffPolicy; + + /** + * Public setter for the retry limit. Each item can be retried up to this + * limit. + * @param retryLimit the retry limit to set + */ + public void setRetryLimit(int retryLimit) { + this.retryLimit = retryLimit; + } + + /** + * Public setter for the Class[]. + * @param retryableExceptionClasses the retryableExceptionClasses to set + */ + public void setRetryableExceptionClasses(Class[] retryableExceptionClasses) { + this.retryableExceptionClasses = retryableExceptionClasses; + } + + /** + * Public setter for the {@link BackOffPolicy}. + * @param backOffPolicy the {@link BackOffPolicy} to set + */ + public void setBackOffPolicy(BackOffPolicy backOffPolicy) { + this.backOffPolicy = backOffPolicy; + } + + /** + * Public setter for the {@link ItemKeyGenerator} which will be used to + * cache failed items between transactions. If it is not injected but the + * reader or writer implement {@link ItemKeyGenerator}, one of those will + * be used instead (preferring the reader to the writer if both would be + * appropriate). If neither can be used, then the default will be to just + * use the item itself as a cache key. + * + * @param itemKeyGenerator the {@link ItemKeyGenerator} to set + */ + public void setItemKeyGenerator(ItemKeyGenerator itemKeyGenerator) { + this.itemKeyGenerator = itemKeyGenerator; + } + + /** + * Public setter for the {@link ItemRecoverer}. If this is set the + * {@link ItemRecoverer#recover(Object, Throwable)} will be called when + * retry is exhausted, and within the business transaction (which will not + * roll back because of any other item-related errors). + * + * @param itemRecoverer the {@link ItemRecoverer} to set + */ + public void setItemRecoverer(ItemRecoverer itemRecoverer) { + this.itemRecoverer = itemRecoverer; + } + + /** + * @param step + * + */ + protected void applyConfiguration(ItemOrientedStep step) { + + super.applyConfiguration(step); + + if (retryLimit > 0) { + + SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy(retryLimit); + if (retryableExceptionClasses != null) { + retryPolicy.setRetryableExceptionClasses(retryableExceptionClasses); + } + + // Co-ordinate the retry policy with the exception handler: + getStepOperations() + .setExceptionHandler(new SimpleRetryExceptionHandler(retryPolicy, getExceptionHandler())); + + ItemReaderRetryCallback retryCallback = new ItemReaderRetryCallback(getItemReader(), itemKeyGenerator, + getItemWriter()); + retryCallback.setRecoverer(itemRecoverer); + ItemReaderRetryPolicy itemProviderRetryPolicy = new ItemReaderRetryPolicy(retryPolicy); + + RetryTemplate retryTemplate = new RetryTemplate(); + retryTemplate.setRetryPolicy(itemProviderRetryPolicy); + if (backOffPolicy != null) { + retryTemplate.setBackOffPolicy(backOffPolicy); + } + + StatefulRetryItemHandler itemProcessor = new StatefulRetryItemHandler(getItemReader(), getItemWriter(), + retryTemplate, retryCallback); + + step.setItemHandler(itemProcessor); + + } + + } + + private static class StatefulRetryItemHandler extends SimpleItemHandler { + + final private RetryOperations retryOperations; + + final private ItemReaderRetryCallback retryCallback; + + /** + * @param itemReader + * @param itemWriter + * @param retryCallback + * @param retryTemplate + */ + public StatefulRetryItemHandler(ItemReader itemReader, ItemWriter itemWriter, RetryOperations retryTemplate, + ItemReaderRetryCallback retryCallback) { + super(itemReader, itemWriter); + this.retryOperations = retryTemplate; + this.retryCallback = retryCallback; + } + + /** + * Execute the business logic, delegating to the reader and writer. + * Subclasses could extend the behaviour as long as they always return + * the value of this method call in their superclass.
+ * + * Read from the {@link ItemReader} and process (if not null) with the + * {@link ItemWriter}. The call to {@link ItemWriter} is wrapped in a + * stateful retry. In that case the {@link ItemRecoverer} is used (if + * provided) in the case of an exception to apply alternate processing + * to the item. If the stateful retry is in place then the recovery will + * happen in the next transaction automatically, otherwise it might be + * necessary for clients to make the recover method transactional with + * appropriate propagation behaviour (probably REQUIRES_NEW because the + * call will happen in the context of a transaction that is about to + * rollback).
+ * + * @param contribution the current step + * @return {@link ExitStatus#CONTINUABLE} if there is more processing to + * do + * @throws Exception if there is an error + */ + public ExitStatus handle(StepContribution contribution) throws Exception { + return new ExitStatus(retryOperations.execute(retryCallback) != null); + } + + } +} diff --git a/spring-batch-execution/src/main/sql/db2.properties b/spring-batch-execution/src/main/sql/db2.properties index 79b46a64c9..e667f21b82 100644 --- a/spring-batch-execution/src/main/sql/db2.properties +++ b/spring-batch-execution/src/main/sql/db2.properties @@ -1,8 +1,8 @@ -platform=db2 -# SQL language oddities -BIGINT = BIGINT -IDENTITY = -DOUBLE = DOUBLE PRECISION -BLOB = BLOB -# for generating drop statements... -SEQUENCE = SEQUENCE +platform=db2 +# SQL language oddities +BIGINT = BIGINT +IDENTITY = +DOUBLE = DOUBLE PRECISION +BLOB = BLOB +# for generating drop statements... +SEQUENCE = SEQUENCE diff --git a/spring-batch-execution/src/main/sql/db2.vpp b/spring-batch-execution/src/main/sql/db2.vpp index 3713aa6f5d..56bd1c6e38 100644 --- a/spring-batch-execution/src/main/sql/db2.vpp +++ b/spring-batch-execution/src/main/sql/db2.vpp @@ -1,2 +1,2 @@ -#macro (sequence $name)CREATE SEQUENCE ${name}; -#end +#macro (sequence $name)CREATE SEQUENCE ${name}; +#end diff --git a/spring-batch-execution/src/main/sql/derby.properties b/spring-batch-execution/src/main/sql/derby.properties index 506d250c88..562b023215 100644 --- a/spring-batch-execution/src/main/sql/derby.properties +++ b/spring-batch-execution/src/main/sql/derby.properties @@ -1,9 +1,9 @@ -platform=db2 -# SQL language oddities -BIGINT = BIGINT -IDENTITY = -GENERATED = GENERATED BY DEFAULT AS IDENTITY -DOUBLE = DOUBLE PRECISION -BLOB = BLOB -# for generating drop statements... -SEQUENCE = TABLE +platform=db2 +# SQL language oddities +BIGINT = BIGINT +IDENTITY = +GENERATED = GENERATED BY DEFAULT AS IDENTITY +DOUBLE = DOUBLE PRECISION +BLOB = BLOB +# for generating drop statements... +SEQUENCE = TABLE diff --git a/spring-batch-execution/src/main/sql/derby.vpp b/spring-batch-execution/src/main/sql/derby.vpp index 00645d2a75..95d9c397ac 100644 --- a/spring-batch-execution/src/main/sql/derby.vpp +++ b/spring-batch-execution/src/main/sql/derby.vpp @@ -1,2 +1,2 @@ -#macro (sequence $name)CREATE TABLE ${name} (ID BIGINT PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY, DUMMY VARCHAR(1)); -#end +#macro (sequence $name)CREATE TABLE ${name} (ID BIGINT PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY, DUMMY VARCHAR(1)); +#end diff --git a/spring-batch-execution/src/main/sql/hsqldb.properties b/spring-batch-execution/src/main/sql/hsqldb.properties index 5304a4aa89..18c45fd0d3 100644 --- a/spring-batch-execution/src/main/sql/hsqldb.properties +++ b/spring-batch-execution/src/main/sql/hsqldb.properties @@ -1,9 +1,9 @@ -platform=hsqldb -# SQL language oddities -BIGINT = BIGINT -IDENTITY = IDENTITY -IFEXISTS = IF EXISTS -DOUBLE = DOUBLE PRECISION -BLOB = LONGVARBINARY -# for generating drop statements... -SEQUENCE = TABLE +platform=hsqldb +# SQL language oddities +BIGINT = BIGINT +IDENTITY = IDENTITY +IFEXISTS = IF EXISTS +DOUBLE = DOUBLE PRECISION +BLOB = LONGVARBINARY +# for generating drop statements... +SEQUENCE = TABLE diff --git a/spring-batch-execution/src/main/sql/hsqldb.vpp b/spring-batch-execution/src/main/sql/hsqldb.vpp index 6259ee1244..9fbc68564f 100644 --- a/spring-batch-execution/src/main/sql/hsqldb.vpp +++ b/spring-batch-execution/src/main/sql/hsqldb.vpp @@ -1,4 +1,4 @@ -#macro (sequence $name)CREATE TABLE ${name} ( - ID BIGINT IDENTITY -); -#end +#macro (sequence $name)CREATE TABLE ${name} ( + ID BIGINT IDENTITY +); +#end diff --git a/spring-batch-execution/src/main/sql/mysql.properties b/spring-batch-execution/src/main/sql/mysql.properties index efe4a06fec..435f465f2e 100644 --- a/spring-batch-execution/src/main/sql/mysql.properties +++ b/spring-batch-execution/src/main/sql/mysql.properties @@ -1,10 +1,10 @@ -platform=oracle10g -# SQL language oddities -BIGINT = BIGINT -IDENTITY = unsigned -GENERATED = -IFEXISTSBEFORE = IF EXISTS -DOUBLE = DOUBLE PRECISION -BLOB = BLOB -# for generating drop statements... -SEQUENCE = TABLE +platform=oracle10g +# SQL language oddities +BIGINT = BIGINT +IDENTITY = unsigned +GENERATED = +IFEXISTSBEFORE = IF EXISTS +DOUBLE = DOUBLE PRECISION +BLOB = BLOB +# for generating drop statements... +SEQUENCE = TABLE diff --git a/spring-batch-execution/src/main/sql/mysql.vpp b/spring-batch-execution/src/main/sql/mysql.vpp index 5e4dd6446a..1812fa9776 100644 --- a/spring-batch-execution/src/main/sql/mysql.vpp +++ b/spring-batch-execution/src/main/sql/mysql.vpp @@ -1,3 +1,3 @@ -#macro (sequence $name)CREATE TABLE ${name} (ID BIGINT NOT NULL) type=MYISAM; -INSERT INTO ${name} values(0); -#end +#macro (sequence $name)CREATE TABLE ${name} (ID BIGINT NOT NULL) type=MYISAM; +INSERT INTO ${name} values(0); +#end diff --git a/spring-batch-execution/src/main/sql/oracle10g.properties b/spring-batch-execution/src/main/sql/oracle10g.properties index b31cbc1da7..8642f67c14 100644 --- a/spring-batch-execution/src/main/sql/oracle10g.properties +++ b/spring-batch-execution/src/main/sql/oracle10g.properties @@ -1,9 +1,9 @@ -platform=oracle10g -# SQL language oddities -BIGINT = NUMBER(38) -IDENTITY = -GENERATED = -DOUBLE = DOUBLE PRECISION -BLOB = BLOB -# for generating drop statements... -SEQUENCE = SEQUENCE +platform=oracle10g +# SQL language oddities +BIGINT = NUMBER(38) +IDENTITY = +GENERATED = +DOUBLE = DOUBLE PRECISION +BLOB = BLOB +# for generating drop statements... +SEQUENCE = SEQUENCE diff --git a/spring-batch-execution/src/main/sql/oracle10g.vpp b/spring-batch-execution/src/main/sql/oracle10g.vpp index 3713aa6f5d..56bd1c6e38 100644 --- a/spring-batch-execution/src/main/sql/oracle10g.vpp +++ b/spring-batch-execution/src/main/sql/oracle10g.vpp @@ -1,2 +1,2 @@ -#macro (sequence $name)CREATE SEQUENCE ${name}; -#end +#macro (sequence $name)CREATE SEQUENCE ${name}; +#end diff --git a/spring-batch-execution/src/main/sql/postgresql.properties b/spring-batch-execution/src/main/sql/postgresql.properties index d5a9bb493a..236e3de723 100644 --- a/spring-batch-execution/src/main/sql/postgresql.properties +++ b/spring-batch-execution/src/main/sql/postgresql.properties @@ -1,9 +1,9 @@ -platform=postgresql -# SQL language oddities -BIGINT = BIGINT -IDENTITY = -GENERATED = -DOUBLE = DOUBLE PRECISION -BLOB = BYTEA -# for generating drop statements... -SEQUENCE = SEQUENCE +platform=postgresql +# SQL language oddities +BIGINT = BIGINT +IDENTITY = +GENERATED = +DOUBLE = DOUBLE PRECISION +BLOB = BYTEA +# for generating drop statements... +SEQUENCE = SEQUENCE diff --git a/spring-batch-execution/src/main/sql/postgresql.vpp b/spring-batch-execution/src/main/sql/postgresql.vpp index 3713aa6f5d..56bd1c6e38 100644 --- a/spring-batch-execution/src/main/sql/postgresql.vpp +++ b/spring-batch-execution/src/main/sql/postgresql.vpp @@ -1,2 +1,2 @@ -#macro (sequence $name)CREATE SEQUENCE ${name}; -#end +#macro (sequence $name)CREATE SEQUENCE ${name}; +#end diff --git a/spring-batch-execution/src/test/java/org/springframework/batch/execution/configuration/JobRegistryBeanPostProcessorTests.java b/spring-batch-execution/src/test/java/org/springframework/batch/execution/configuration/JobRegistryBeanPostProcessorTests.java index 548934cbcf..38faf37179 100644 --- a/spring-batch-execution/src/test/java/org/springframework/batch/execution/configuration/JobRegistryBeanPostProcessorTests.java +++ b/spring-batch-execution/src/test/java/org/springframework/batch/execution/configuration/JobRegistryBeanPostProcessorTests.java @@ -1,131 +1,131 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.execution.configuration; - -import java.util.Collection; - -import junit.framework.TestCase; - -import org.springframework.batch.core.repository.DuplicateJobException; -import org.springframework.batch.core.repository.NoSuchJobException; -import org.springframework.batch.execution.job.JobSupport; -import org.springframework.beans.FatalBeanException; -import org.springframework.context.support.ClassPathXmlApplicationContext; - -/** - * @author Dave Syer - * - */ -public class JobRegistryBeanPostProcessorTests extends TestCase { - - private JobRegistryBeanPostProcessor processor = new JobRegistryBeanPostProcessor(); - - public void testInitialization() throws Exception { - try { - processor.afterPropertiesSet(); - fail("Expected IllegalArgumentException"); - } catch (IllegalArgumentException e) { - // expected - assertTrue(e.getMessage().indexOf("JobConfigurationRegistry") >= 0); - } - } - - public void testBeforeInitialization() throws Exception { - // should be a no-op - assertEquals("foo", processor.postProcessAfterInitialization("foo", - "bar")); - } - - public void testAfterInitializationWithWrongType() throws Exception { - // should be a no-op - assertEquals("foo", processor.postProcessAfterInitialization("foo", - "bar")); - } - - public void testAfterInitializationWithCorrectType() throws Exception { - MapJobRegistry registry = new MapJobRegistry(); - processor.setJobRegistry(registry); - JobSupport configuration = new JobSupport(); - configuration.setBeanName("foo"); - assertEquals(configuration, processor.postProcessAfterInitialization( - configuration, "bar")); - assertEquals(configuration, registry.getJob("foo")); - } - - public void testAfterInitializationWithDuplicate() throws Exception { - MapJobRegistry registry = new MapJobRegistry(); - processor.setJobRegistry(registry); - JobSupport configuration = new JobSupport(); - configuration.setBeanName("foo"); - processor.postProcessAfterInitialization(configuration, "bar"); - try { - processor.postProcessAfterInitialization(configuration, "spam"); - fail("Expected FatalBeanException"); - } catch (FatalBeanException e) { - // Expected - assertTrue(e.getCause() instanceof DuplicateJobException); - } - } - - public void testUnregisterOnDestroy() throws Exception { - MapJobRegistry registry = new MapJobRegistry(); - processor.setJobRegistry(registry); - JobSupport configuration = new JobSupport(); - configuration.setBeanName("foo"); - assertEquals(configuration, processor.postProcessAfterInitialization( - configuration, "bar")); - processor.destroy(); - try { - assertEquals(null, registry.getJob("foo")); - fail("Expected NoSuchJobConfigurationException"); - } catch (NoSuchJobException e) { - // expected - } - } - - public void testExecutionWithApplicationContext() throws Exception { - ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext( - "test-context.xml", getClass()); - MapJobRegistry registry = (MapJobRegistry) context - .getBean("registry"); - Collection configurations = registry.getJobNames(); - // System.err.println(configurations); - String[] names = context.getBeanNamesForType(JobSupport.class); - int count = names.length; - // Each concrete bean of type JobConfiguration is registered... - assertEquals(count, configurations.size()); - // N.B. there is a failure / wonky mode where a parent bean is given an - // explicit name or beanName (using property setter): in this case then - // child beans will have the same name and will be re-registered (and - // override, if the registry supports that). - assertNotNull(registry.getJob("test-job")); - assertEquals(context.getBean("test-job-with-name"), registry - .getJob("foo")); - assertEquals(context.getBean("test-job-with-bean-name"), registry - .getJob("bar")); - assertEquals(context.getBean("test-job-with-parent-and-name"), registry - .getJob("spam")); - assertEquals(context.getBean("test-job-with-parent-and-bean-name"), - registry.getJob("bucket")); - assertEquals(context.getBean("test-job-with-concrete-parent"), registry - .getJob("maps")); - assertEquals(context.getBean("test-job-with-concrete-parent-and-name"), - registry.getJob("oof")); - assertEquals(context - .getBean("test-job-with-concrete-parent-and-bean-name"), - registry.getJob("rab")); - } -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.execution.configuration; + +import java.util.Collection; + +import junit.framework.TestCase; + +import org.springframework.batch.core.repository.DuplicateJobException; +import org.springframework.batch.core.repository.NoSuchJobException; +import org.springframework.batch.execution.job.JobSupport; +import org.springframework.beans.FatalBeanException; +import org.springframework.context.support.ClassPathXmlApplicationContext; + +/** + * @author Dave Syer + * + */ +public class JobRegistryBeanPostProcessorTests extends TestCase { + + private JobRegistryBeanPostProcessor processor = new JobRegistryBeanPostProcessor(); + + public void testInitialization() throws Exception { + try { + processor.afterPropertiesSet(); + fail("Expected IllegalArgumentException"); + } catch (IllegalArgumentException e) { + // expected + assertTrue(e.getMessage().indexOf("JobConfigurationRegistry") >= 0); + } + } + + public void testBeforeInitialization() throws Exception { + // should be a no-op + assertEquals("foo", processor.postProcessAfterInitialization("foo", + "bar")); + } + + public void testAfterInitializationWithWrongType() throws Exception { + // should be a no-op + assertEquals("foo", processor.postProcessAfterInitialization("foo", + "bar")); + } + + public void testAfterInitializationWithCorrectType() throws Exception { + MapJobRegistry registry = new MapJobRegistry(); + processor.setJobRegistry(registry); + JobSupport configuration = new JobSupport(); + configuration.setBeanName("foo"); + assertEquals(configuration, processor.postProcessAfterInitialization( + configuration, "bar")); + assertEquals(configuration, registry.getJob("foo")); + } + + public void testAfterInitializationWithDuplicate() throws Exception { + MapJobRegistry registry = new MapJobRegistry(); + processor.setJobRegistry(registry); + JobSupport configuration = new JobSupport(); + configuration.setBeanName("foo"); + processor.postProcessAfterInitialization(configuration, "bar"); + try { + processor.postProcessAfterInitialization(configuration, "spam"); + fail("Expected FatalBeanException"); + } catch (FatalBeanException e) { + // Expected + assertTrue(e.getCause() instanceof DuplicateJobException); + } + } + + public void testUnregisterOnDestroy() throws Exception { + MapJobRegistry registry = new MapJobRegistry(); + processor.setJobRegistry(registry); + JobSupport configuration = new JobSupport(); + configuration.setBeanName("foo"); + assertEquals(configuration, processor.postProcessAfterInitialization( + configuration, "bar")); + processor.destroy(); + try { + assertEquals(null, registry.getJob("foo")); + fail("Expected NoSuchJobConfigurationException"); + } catch (NoSuchJobException e) { + // expected + } + } + + public void testExecutionWithApplicationContext() throws Exception { + ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext( + "test-context.xml", getClass()); + MapJobRegistry registry = (MapJobRegistry) context + .getBean("registry"); + Collection configurations = registry.getJobNames(); + // System.err.println(configurations); + String[] names = context.getBeanNamesForType(JobSupport.class); + int count = names.length; + // Each concrete bean of type JobConfiguration is registered... + assertEquals(count, configurations.size()); + // N.B. there is a failure / wonky mode where a parent bean is given an + // explicit name or beanName (using property setter): in this case then + // child beans will have the same name and will be re-registered (and + // override, if the registry supports that). + assertNotNull(registry.getJob("test-job")); + assertEquals(context.getBean("test-job-with-name"), registry + .getJob("foo")); + assertEquals(context.getBean("test-job-with-bean-name"), registry + .getJob("bar")); + assertEquals(context.getBean("test-job-with-parent-and-name"), registry + .getJob("spam")); + assertEquals(context.getBean("test-job-with-parent-and-bean-name"), + registry.getJob("bucket")); + assertEquals(context.getBean("test-job-with-concrete-parent"), registry + .getJob("maps")); + assertEquals(context.getBean("test-job-with-concrete-parent-and-name"), + registry.getJob("oof")); + assertEquals(context + .getBean("test-job-with-concrete-parent-and-bean-name"), + registry.getJob("rab")); + } +} diff --git a/spring-batch-execution/src/test/java/org/springframework/batch/execution/configuration/MapJobRegistryTests.java b/spring-batch-execution/src/test/java/org/springframework/batch/execution/configuration/MapJobRegistryTests.java index 2c97d8ccaa..9f79ff3e39 100644 --- a/spring-batch-execution/src/test/java/org/springframework/batch/execution/configuration/MapJobRegistryTests.java +++ b/spring-batch-execution/src/test/java/org/springframework/batch/execution/configuration/MapJobRegistryTests.java @@ -1,95 +1,95 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.execution.configuration; - -import java.util.Collection; - -import junit.framework.TestCase; - -import org.springframework.batch.core.configuration.JobFactory; -import org.springframework.batch.core.repository.DuplicateJobException; -import org.springframework.batch.core.repository.NoSuchJobException; -import org.springframework.batch.execution.job.JobSupport; - -/** - * @author Dave Syer - * - */ -public class MapJobRegistryTests extends TestCase { - - private MapJobRegistry registry = new MapJobRegistry(); - - /** - * Test method for {@link org.springframework.batch.execution.configuration.MapJobRegistry#unregister(String)}. - * @throws Exception - */ - public void testUnregister() throws Exception { - registry.register(new ReferenceJobFactory(new JobSupport("foo"))); - assertNotNull(registry.getJob("foo")); - registry.unregister("foo"); - try { - assertNull(registry.getJob("foo")); - fail("Expected NoSuchJobConfigurationException"); - } - catch (NoSuchJobException e) { - // expected - assertTrue(e.getMessage().indexOf("foo")>=0); - } - } - - /** - * Test method for {@link org.springframework.batch.execution.configuration.MapJobRegistry#getJob(java.lang.String)}. - */ - public void testReplaceDuplicateConfiguration() throws Exception { - registry.register(new ReferenceJobFactory(new JobSupport("foo"))); - try { - registry.register(new ReferenceJobFactory(new JobSupport("foo"))); - fail("Expected DuplicateJobConfigurationException"); - } catch (DuplicateJobException e) { - // unexpected: even if the job is different we want a DuplicateJobException - assertTrue(e.getMessage().indexOf("foo")>=0); - } - } - - /** - * Test method for {@link org.springframework.batch.execution.configuration.MapJobRegistry#getJob(java.lang.String)}. - */ - public void testRealDuplicateConfiguration() throws Exception { - JobFactory jobFactory = new ReferenceJobFactory(new JobSupport("foo")); - registry.register(jobFactory); - try { - registry.register(jobFactory); - fail("Unexpected DuplicateJobConfigurationException"); - } catch (DuplicateJobException e) { - // expected - assertTrue(e.getMessage().indexOf("foo")>=0); - } - } - - /** - * Test method for {@link org.springframework.batch.execution.configuration.MapJobRegistry#getJobNames()}. - * @throws Exception - */ - public void testGetJobConfigurations() throws Exception { - JobFactory jobFactory = new ReferenceJobFactory(new JobSupport("foo")); - registry.register(jobFactory); - registry.register(new ReferenceJobFactory(new JobSupport("bar"))); - Collection configurations = registry.getJobNames(); - assertEquals(2, configurations.size()); - assertTrue(configurations.contains(jobFactory.getJobName())); - } - -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.execution.configuration; + +import java.util.Collection; + +import junit.framework.TestCase; + +import org.springframework.batch.core.configuration.JobFactory; +import org.springframework.batch.core.repository.DuplicateJobException; +import org.springframework.batch.core.repository.NoSuchJobException; +import org.springframework.batch.execution.job.JobSupport; + +/** + * @author Dave Syer + * + */ +public class MapJobRegistryTests extends TestCase { + + private MapJobRegistry registry = new MapJobRegistry(); + + /** + * Test method for {@link org.springframework.batch.execution.configuration.MapJobRegistry#unregister(String)}. + * @throws Exception + */ + public void testUnregister() throws Exception { + registry.register(new ReferenceJobFactory(new JobSupport("foo"))); + assertNotNull(registry.getJob("foo")); + registry.unregister("foo"); + try { + assertNull(registry.getJob("foo")); + fail("Expected NoSuchJobConfigurationException"); + } + catch (NoSuchJobException e) { + // expected + assertTrue(e.getMessage().indexOf("foo")>=0); + } + } + + /** + * Test method for {@link org.springframework.batch.execution.configuration.MapJobRegistry#getJob(java.lang.String)}. + */ + public void testReplaceDuplicateConfiguration() throws Exception { + registry.register(new ReferenceJobFactory(new JobSupport("foo"))); + try { + registry.register(new ReferenceJobFactory(new JobSupport("foo"))); + fail("Expected DuplicateJobConfigurationException"); + } catch (DuplicateJobException e) { + // unexpected: even if the job is different we want a DuplicateJobException + assertTrue(e.getMessage().indexOf("foo")>=0); + } + } + + /** + * Test method for {@link org.springframework.batch.execution.configuration.MapJobRegistry#getJob(java.lang.String)}. + */ + public void testRealDuplicateConfiguration() throws Exception { + JobFactory jobFactory = new ReferenceJobFactory(new JobSupport("foo")); + registry.register(jobFactory); + try { + registry.register(jobFactory); + fail("Unexpected DuplicateJobConfigurationException"); + } catch (DuplicateJobException e) { + // expected + assertTrue(e.getMessage().indexOf("foo")>=0); + } + } + + /** + * Test method for {@link org.springframework.batch.execution.configuration.MapJobRegistry#getJobNames()}. + * @throws Exception + */ + public void testGetJobConfigurations() throws Exception { + JobFactory jobFactory = new ReferenceJobFactory(new JobSupport("foo")); + registry.register(jobFactory); + registry.register(new ReferenceJobFactory(new JobSupport("bar"))); + Collection configurations = registry.getJobNames(); + assertEquals(2, configurations.size()); + assertTrue(configurations.contains(jobFactory.getJobName())); + } + +} diff --git a/spring-batch-execution/src/test/java/org/springframework/batch/execution/job/AbstractJobTests.java b/spring-batch-execution/src/test/java/org/springframework/batch/execution/job/AbstractJobTests.java index ba001e4b20..4aaeb16aed 100644 --- a/spring-batch-execution/src/test/java/org/springframework/batch/execution/job/AbstractJobTests.java +++ b/spring-batch-execution/src/test/java/org/springframework/batch/execution/job/AbstractJobTests.java @@ -1,115 +1,115 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.execution.job; - -import java.util.Collections; - -import org.springframework.batch.execution.step.StepSupport; - - -import junit.framework.TestCase; - -/** - * @author Dave Syer - * - */ -public class AbstractJobTests extends TestCase { - - JobSupport job = new JobSupport("job"); - - /** - * Test method for - * {@link org.springframework.batch.execution.job.AbstractJob#JobConfiguration()}. - */ - public void testJobConfiguration() { - job = new JobSupport(); - assertNull(job.getName()); - } - - /** - * Test method for - * {@link org.springframework.batch.execution.job.AbstractJob#setBeanName(java.lang.String)}. - */ - public void testSetBeanName() { - job.setBeanName("foo"); - assertEquals("job", job.getName()); - } - - /** - * Test method for - * {@link org.springframework.batch.execution.job.AbstractJob#setBeanName(java.lang.String)}. - */ - public void testSetBeanNameWithNullName() { - job = new JobSupport(null); - assertEquals(null, job.getName()); - job.setBeanName("foo"); - assertEquals("foo", job.getName()); - } - - /** - * Test method for - * {@link org.springframework.batch.execution.job.AbstractJob#setStepNames(java.util.List)}. - */ - public void testSetSteps() { - job.setSteps(Collections.singletonList(new StepSupport("step"))); - assertEquals(1, job.getSteps().size()); - } - - /** - * Test method for - * {@link org.springframework.batch.execution.job.AbstractJob#addStepName(org.springframework.batch.core.configuration.StepConfiguration)}. - */ - public void testAddStep() { - job.addStep(new StepSupport("step")); - assertEquals(1, job.getSteps().size()); - } - - /** - * Test method for - * {@link org.springframework.batch.execution.job.AbstractJob#setStartLimit(int)}. - */ - public void testSetStartLimit() { - assertEquals(Integer.MAX_VALUE, job.getStartLimit()); - job.setStartLimit(10); - assertEquals(10, job.getStartLimit()); - } - - /** - * Test method for - * {@link org.springframework.batch.execution.job.AbstractJob#setRestartable(boolean)}. - */ - public void testSetRestartable() { - assertFalse(job.isRestartable()); - job.setRestartable(true); - assertTrue(job.isRestartable()); - } - - public void testToString() throws Exception { - String value = job.toString(); - assertTrue("Should contain name: "+value, value.indexOf("name=")>=0); - } - - public void testRunNotSupported() throws Exception { - try { - job.execute(null); - } catch (UnsupportedOperationException e) { - // expected - String message = e.getMessage(); - assertTrue("Message should contain JobSupport: "+message, message.contains("JobSupport")); - } - } - -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.execution.job; + +import java.util.Collections; + +import org.springframework.batch.execution.step.StepSupport; + + +import junit.framework.TestCase; + +/** + * @author Dave Syer + * + */ +public class AbstractJobTests extends TestCase { + + JobSupport job = new JobSupport("job"); + + /** + * Test method for + * {@link org.springframework.batch.execution.job.AbstractJob#JobConfiguration()}. + */ + public void testJobConfiguration() { + job = new JobSupport(); + assertNull(job.getName()); + } + + /** + * Test method for + * {@link org.springframework.batch.execution.job.AbstractJob#setBeanName(java.lang.String)}. + */ + public void testSetBeanName() { + job.setBeanName("foo"); + assertEquals("job", job.getName()); + } + + /** + * Test method for + * {@link org.springframework.batch.execution.job.AbstractJob#setBeanName(java.lang.String)}. + */ + public void testSetBeanNameWithNullName() { + job = new JobSupport(null); + assertEquals(null, job.getName()); + job.setBeanName("foo"); + assertEquals("foo", job.getName()); + } + + /** + * Test method for + * {@link org.springframework.batch.execution.job.AbstractJob#setStepNames(java.util.List)}. + */ + public void testSetSteps() { + job.setSteps(Collections.singletonList(new StepSupport("step"))); + assertEquals(1, job.getSteps().size()); + } + + /** + * Test method for + * {@link org.springframework.batch.execution.job.AbstractJob#addStepName(org.springframework.batch.core.configuration.StepConfiguration)}. + */ + public void testAddStep() { + job.addStep(new StepSupport("step")); + assertEquals(1, job.getSteps().size()); + } + + /** + * Test method for + * {@link org.springframework.batch.execution.job.AbstractJob#setStartLimit(int)}. + */ + public void testSetStartLimit() { + assertEquals(Integer.MAX_VALUE, job.getStartLimit()); + job.setStartLimit(10); + assertEquals(10, job.getStartLimit()); + } + + /** + * Test method for + * {@link org.springframework.batch.execution.job.AbstractJob#setRestartable(boolean)}. + */ + public void testSetRestartable() { + assertFalse(job.isRestartable()); + job.setRestartable(true); + assertTrue(job.isRestartable()); + } + + public void testToString() throws Exception { + String value = job.toString(); + assertTrue("Should contain name: "+value, value.indexOf("name=")>=0); + } + + public void testRunNotSupported() throws Exception { + try { + job.execute(null); + } catch (UnsupportedOperationException e) { + // expected + String message = e.getMessage(); + assertTrue("Message should contain JobSupport: "+message, message.contains("JobSupport")); + } + } + +} diff --git a/spring-batch-execution/src/test/java/org/springframework/batch/execution/launch/support/SimpleJvmExitCodeMapperTests.java b/spring-batch-execution/src/test/java/org/springframework/batch/execution/launch/support/SimpleJvmExitCodeMapperTests.java index 4d0600aae4..4ac89e4477 100644 --- a/spring-batch-execution/src/test/java/org/springframework/batch/execution/launch/support/SimpleJvmExitCodeMapperTests.java +++ b/spring-batch-execution/src/test/java/org/springframework/batch/execution/launch/support/SimpleJvmExitCodeMapperTests.java @@ -1,90 +1,90 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.batch.execution.launch.support; - -import java.util.HashMap; -import java.util.Map; - -import junit.framework.TestCase; - -import org.springframework.batch.execution.launch.support.ExitCodeMapper; -import org.springframework.batch.execution.launch.support.SimpleJvmExitCodeMapper; -import org.springframework.batch.repeat.ExitStatus; - -public class SimpleJvmExitCodeMapperTests extends TestCase { - - private SimpleJvmExitCodeMapper ecm; - private SimpleJvmExitCodeMapper ecm2; - - protected void setUp() throws Exception { - ecm = new SimpleJvmExitCodeMapper(); - Map ecmMap = new HashMap(); - ecmMap.put("MY_CUSTOM_CODE", new Integer(3)); - ecm.setMapping(ecmMap); - - ecm2 = new SimpleJvmExitCodeMapper(); - Map ecm2Map = new HashMap(); - ecm2Map.put(ExitStatus.FINISHED.getExitCode(), new Integer(-1)); - ecm2Map.put(ExitStatus.FAILED.getExitCode(), new Integer(-2)); - ecm2Map.put(ExitCodeMapper.JOB_NOT_PROVIDED, new Integer(-3)); - ecm2Map.put(ExitCodeMapper.NO_SUCH_JOB, new Integer(-3)); - ecm2.setMapping(ecm2Map); - } - - protected void tearDown() throws Exception { - super.tearDown(); - } - - public void testGetExitCodeWithpPredefinedCodes() { - assertEquals( - ecm.getExitCode(ExitStatus.FINISHED.getExitCode()), - ExitCodeMapper.JVM_EXITCODE_COMPLETED); - assertEquals( - ecm.getExitCode(ExitStatus.FAILED.getExitCode()), - ExitCodeMapper.JVM_EXITCODE_GENERIC_ERROR); - assertEquals( - ecm.getExitCode(ExitCodeMapper.JOB_NOT_PROVIDED), - ExitCodeMapper.JVM_EXITCODE_JOB_ERROR); - assertEquals( - ecm.getExitCode(ExitCodeMapper.NO_SUCH_JOB), - ExitCodeMapper.JVM_EXITCODE_JOB_ERROR); - } - - public void testGetExitCodeWithPredefinedCodesOverridden() { - System.out.println(ecm2.getExitCode(ExitStatus.FINISHED.getExitCode())); - assertEquals( - ecm2.getExitCode(ExitStatus.FINISHED.getExitCode()), -1); - assertEquals( - ecm2.getExitCode(ExitStatus.FAILED.getExitCode()), -2); - assertEquals( - ecm2.getExitCode(ExitCodeMapper.JOB_NOT_PROVIDED), -3); - assertEquals( - ecm2.getExitCode(ExitCodeMapper.NO_SUCH_JOB), -3); - } - - public void testGetExitCodeWithCustomCode() { - assertEquals(ecm.getExitCode("MY_CUSTOM_CODE"),3); - } - - public void testGetExitCodeWithDefaultCode() { - assertEquals( - ecm.getExitCode("UNDEFINED_CUSTOM_CODE"), - ExitCodeMapper.JVM_EXITCODE_GENERIC_ERROR); - } - - -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.batch.execution.launch.support; + +import java.util.HashMap; +import java.util.Map; + +import junit.framework.TestCase; + +import org.springframework.batch.execution.launch.support.ExitCodeMapper; +import org.springframework.batch.execution.launch.support.SimpleJvmExitCodeMapper; +import org.springframework.batch.repeat.ExitStatus; + +public class SimpleJvmExitCodeMapperTests extends TestCase { + + private SimpleJvmExitCodeMapper ecm; + private SimpleJvmExitCodeMapper ecm2; + + protected void setUp() throws Exception { + ecm = new SimpleJvmExitCodeMapper(); + Map ecmMap = new HashMap(); + ecmMap.put("MY_CUSTOM_CODE", new Integer(3)); + ecm.setMapping(ecmMap); + + ecm2 = new SimpleJvmExitCodeMapper(); + Map ecm2Map = new HashMap(); + ecm2Map.put(ExitStatus.FINISHED.getExitCode(), new Integer(-1)); + ecm2Map.put(ExitStatus.FAILED.getExitCode(), new Integer(-2)); + ecm2Map.put(ExitCodeMapper.JOB_NOT_PROVIDED, new Integer(-3)); + ecm2Map.put(ExitCodeMapper.NO_SUCH_JOB, new Integer(-3)); + ecm2.setMapping(ecm2Map); + } + + protected void tearDown() throws Exception { + super.tearDown(); + } + + public void testGetExitCodeWithpPredefinedCodes() { + assertEquals( + ecm.getExitCode(ExitStatus.FINISHED.getExitCode()), + ExitCodeMapper.JVM_EXITCODE_COMPLETED); + assertEquals( + ecm.getExitCode(ExitStatus.FAILED.getExitCode()), + ExitCodeMapper.JVM_EXITCODE_GENERIC_ERROR); + assertEquals( + ecm.getExitCode(ExitCodeMapper.JOB_NOT_PROVIDED), + ExitCodeMapper.JVM_EXITCODE_JOB_ERROR); + assertEquals( + ecm.getExitCode(ExitCodeMapper.NO_SUCH_JOB), + ExitCodeMapper.JVM_EXITCODE_JOB_ERROR); + } + + public void testGetExitCodeWithPredefinedCodesOverridden() { + System.out.println(ecm2.getExitCode(ExitStatus.FINISHED.getExitCode())); + assertEquals( + ecm2.getExitCode(ExitStatus.FINISHED.getExitCode()), -1); + assertEquals( + ecm2.getExitCode(ExitStatus.FAILED.getExitCode()), -2); + assertEquals( + ecm2.getExitCode(ExitCodeMapper.JOB_NOT_PROVIDED), -3); + assertEquals( + ecm2.getExitCode(ExitCodeMapper.NO_SUCH_JOB), -3); + } + + public void testGetExitCodeWithCustomCode() { + assertEquals(ecm.getExitCode("MY_CUSTOM_CODE"),3); + } + + public void testGetExitCodeWithDefaultCode() { + assertEquals( + ecm.getExitCode("UNDEFINED_CUSTOM_CODE"), + ExitCodeMapper.JVM_EXITCODE_GENERIC_ERROR); + } + + +} diff --git a/spring-batch-execution/src/test/java/org/springframework/batch/execution/launch/support/StubJobLauncher.java b/spring-batch-execution/src/test/java/org/springframework/batch/execution/launch/support/StubJobLauncher.java index 9c817ef799..f517e3a17f 100644 --- a/spring-batch-execution/src/test/java/org/springframework/batch/execution/launch/support/StubJobLauncher.java +++ b/spring-batch-execution/src/test/java/org/springframework/batch/execution/launch/support/StubJobLauncher.java @@ -1,54 +1,54 @@ -package org.springframework.batch.execution.launch.support; - -import org.springframework.batch.core.domain.Job; -import org.springframework.batch.core.domain.JobExecution; -import org.springframework.batch.core.domain.JobParameters; -import org.springframework.batch.core.repository.JobExecutionAlreadyRunningException; -import org.springframework.batch.execution.launch.JobLauncher; - -/** - * Mock Job Launcher. Normally, something like EasyMock would - * be used to mock an interface, however, because of the nature - * of launching a batch job from the command line, the mocked - * class cannot be injected. - * - * @author Lucas Ward - * - */ -public class StubJobLauncher implements JobLauncher { - - public static final int RUN_NO_ARGS = 0; - public static final int RUN_JOB_NAME = 1; - public static final int RUN_JOB_IDENTIFIER =2 ; - - private int lastRunCalled = RUN_NO_ARGS; - private JobExecution returnValue = null; - - private boolean isRunning = false; - - public boolean isRunning() { - return isRunning; - } - - public JobExecution run(Job job, JobParameters jobParameters) - throws JobExecutionAlreadyRunningException { - lastRunCalled = RUN_JOB_IDENTIFIER; - return returnValue; - } - - public void stop() { - - } - - public void setReturnValue(JobExecution returnValue){ - this.returnValue = returnValue; - } - - public void setIsRunning(boolean isRunning){ - this.isRunning = isRunning; - } - - public int getLastRunCalled(){ - return lastRunCalled; - } -} +package org.springframework.batch.execution.launch.support; + +import org.springframework.batch.core.domain.Job; +import org.springframework.batch.core.domain.JobExecution; +import org.springframework.batch.core.domain.JobParameters; +import org.springframework.batch.core.repository.JobExecutionAlreadyRunningException; +import org.springframework.batch.execution.launch.JobLauncher; + +/** + * Mock Job Launcher. Normally, something like EasyMock would + * be used to mock an interface, however, because of the nature + * of launching a batch job from the command line, the mocked + * class cannot be injected. + * + * @author Lucas Ward + * + */ +public class StubJobLauncher implements JobLauncher { + + public static final int RUN_NO_ARGS = 0; + public static final int RUN_JOB_NAME = 1; + public static final int RUN_JOB_IDENTIFIER =2 ; + + private int lastRunCalled = RUN_NO_ARGS; + private JobExecution returnValue = null; + + private boolean isRunning = false; + + public boolean isRunning() { + return isRunning; + } + + public JobExecution run(Job job, JobParameters jobParameters) + throws JobExecutionAlreadyRunningException { + lastRunCalled = RUN_JOB_IDENTIFIER; + return returnValue; + } + + public void stop() { + + } + + public void setReturnValue(JobExecution returnValue){ + this.returnValue = returnValue; + } + + public void setIsRunning(boolean isRunning){ + this.isRunning = isRunning; + } + + public int getLastRunCalled(){ + return lastRunCalled; + } +} diff --git a/spring-batch-execution/src/test/java/org/springframework/batch/execution/repository/dao/AbstractStepDaoTests.java b/spring-batch-execution/src/test/java/org/springframework/batch/execution/repository/dao/AbstractStepDaoTests.java index 9da7b78aad..a871988184 100644 --- a/spring-batch-execution/src/test/java/org/springframework/batch/execution/repository/dao/AbstractStepDaoTests.java +++ b/spring-batch-execution/src/test/java/org/springframework/batch/execution/repository/dao/AbstractStepDaoTests.java @@ -1,224 +1,224 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.batch.execution.repository.dao; - -import java.util.Date; -import org.springframework.batch.core.domain.BatchStatus; -import org.springframework.batch.core.domain.Job; -import org.springframework.batch.core.domain.JobExecution; -import org.springframework.batch.core.domain.JobInstance; -import org.springframework.batch.core.domain.JobParameters; -import org.springframework.batch.core.domain.Step; -import org.springframework.batch.core.domain.StepExecution; -import org.springframework.batch.core.runtime.ExitStatusExceptionClassifier; -import org.springframework.batch.execution.job.JobSupport; -import org.springframework.batch.execution.step.StepSupport; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.repeat.ExitStatus; -import org.springframework.dao.OptimisticLockingFailureException; -import org.springframework.test.AbstractTransactionalDataSourceSpringContextTests; -import org.springframework.util.ClassUtils; - -/** - * Tests for step persistence (StepInstanceDao and StepExecutionDao). Because it is very reasonable to assume that there is a - * foreign key constraint on the JobId of a step, the JobDao is used to create - * jobs, to have an id for creating steps. - * - * @author Lucas Ward - * @author Dave Syer - */ -public abstract class AbstractStepDaoTests extends AbstractTransactionalDataSourceSpringContextTests { - - protected JobInstanceDao jobInstanceDao; - - protected StepExecutionDao stepExecutionDao; - - protected JobExecutionDao jobExecutionDao; - - protected JobInstance jobInstance; - - protected Step step1; - - protected Step step2; - - protected StepExecution stepExecution; - - protected JobExecution jobExecution; - - protected JobParameters jobParameters = new JobParameters(); - - protected ExecutionContext executionContext; - - public void setJobInstanceDao(JobInstanceDao jobInstanceDao) { - this.jobInstanceDao = jobInstanceDao; - } - - public void setStepExecutionDao(StepExecutionDao stepExecutionDao) { - this.stepExecutionDao = stepExecutionDao; - } - - public void setJobExecutionDao(JobExecutionDao jobExecutionDao) { - this.jobExecutionDao = jobExecutionDao; - } - - /* - * (non-Javadoc) - * @see org.springframework.test.AbstractSingleSpringContextTests#getConfigLocations() - */ - protected String[] getConfigLocations() { - return new String[] { ClassUtils.addResourcePathToPackagePath(getClass(), "sql-dao-test.xml") }; - } - - /* - * (non-Javadoc) - * @see org.springframework.test.AbstractTransactionalSpringContextTests#onSetUpInTransaction() - */ - protected void onSetUpInTransaction() throws Exception { - Job job = new JobSupport("TestJob"); - jobInstance = jobInstanceDao.createJobInstance(job, jobParameters); - step1 = new StepSupport("TestStep1"); - step2 = new StepSupport("TestStep2"); - jobExecution = new JobExecution(jobInstance); - jobExecutionDao.saveJobExecution(jobExecution); - - stepExecution = new StepExecution(step1, jobExecution, new Long(1)); - stepExecution.setStatus(BatchStatus.STARTED); - stepExecution.setStartTime(new Date(System.currentTimeMillis())); - stepExecutionDao.saveStepExecution(stepExecution); - - executionContext = new ExecutionContext(); - executionContext.putString("1", "testString1"); - executionContext.putString("2", "testString2"); - executionContext.putLong("3", 3); - executionContext.putDouble("4", 4.4); - - - } - - public void testVersionIsNotNullForStepExecution() throws Exception { - int version = jdbcTemplate.queryForInt("select version from BATCH_STEP_EXECUTION where STEP_EXECUTION_ID=" - + stepExecution.getId()); - assertEquals(0, version); - } - - public void testUpdateStepWithExecutionContext() { - stepExecution.setExecutionContext(executionContext); - stepExecutionDao.saveOrUpdateExecutionContext(stepExecution); - ExecutionContext tempAttributes = stepExecutionDao.findExecutionContext(stepExecution); - assertEquals(executionContext, tempAttributes); - } - - public void testSaveStepExecution() { - StepExecution execution = new StepExecution(step2, jobExecution, null); - execution.setStatus(BatchStatus.STARTED); - execution.setStartTime(new Date(System.currentTimeMillis())); - execution.setExitStatus(new ExitStatus(false, ExitStatusExceptionClassifier.FATAL_EXCEPTION, - "java.lang.Exception")); - stepExecutionDao.saveStepExecution(execution); - StepExecution retrievedExecution = stepExecutionDao.getStepExecution(jobExecution, step2); - assertNotNull(retrievedExecution); - assertEquals(execution, retrievedExecution); - assertEquals(execution.getExitStatus(), retrievedExecution.getExitStatus()); - } - - public void testSaveStepExecutionAndExecutionContext() { - StepExecution execution = new StepExecution(step2, jobExecution, null); - execution.setStatus(BatchStatus.STARTED); - execution.setStartTime(new Date(System.currentTimeMillis())); - execution.setExecutionContext(executionContext); - execution.setExitStatus(new ExitStatus(false, ExitStatusExceptionClassifier.FATAL_EXCEPTION, - "java.lang.Exception")); - stepExecutionDao.saveStepExecution(execution); - stepExecutionDao.saveOrUpdateExecutionContext(execution); - StepExecution retrievedExecution = stepExecutionDao.getStepExecution(jobExecution, step2); - assertNotNull(retrievedExecution); - assertEquals(execution, retrievedExecution); - assertEquals(execution.getExecutionContext().getString("1"), retrievedExecution.getExecutionContext().getString("1")); - assertEquals(execution.getExecutionContext().getLong("3"), retrievedExecution.getExecutionContext().getLong("3")); - assertEquals(execution.getExitStatus(), retrievedExecution.getExitStatus()); - } - - public void testUpdateStepExecution() { - - stepExecution.setStatus(BatchStatus.COMPLETED); - stepExecution.setEndTime(new Date(System.currentTimeMillis())); - stepExecution.setCommitCount(5); - stepExecution.setTaskCount(5); - stepExecution.setExecutionContext(new ExecutionContext()); - stepExecution.setExitStatus(new ExitStatus(false, ExitStatusExceptionClassifier.FATAL_EXCEPTION, - "java.lang.Exception")); - stepExecutionDao.updateStepExecution(stepExecution); - StepExecution retrievedExecution = stepExecutionDao.getStepExecution(jobExecution, step1); - assertNotNull(retrievedExecution); - assertEquals(stepExecution, retrievedExecution); - assertEquals(stepExecution.getExitStatus(), retrievedExecution.getExitStatus()); - } - - public void testUpdateStepExecutionWithNullId() { - StepExecution stepExecution = new StepExecution(new StepSupport("testStep"), null, null); - try { - stepExecutionDao.updateStepExecution(stepExecution); - fail("Expected IllegalArgumentException"); - } - catch (IllegalArgumentException ex) { - // expected - } - } - - public void testUpdateStepExecutionVersion() throws Exception { - int before = stepExecution.getVersion().intValue(); - stepExecutionDao.updateStepExecution(stepExecution); - int after = stepExecution.getVersion().intValue(); - assertEquals("StepExecution version not updated", before + 1, after); - } - - public void testUpdateStepExecutionOptimisticLocking() throws Exception { - stepExecution.incrementVersion(); // not really allowed outside dao - // code - try { - stepExecutionDao.updateStepExecution(stepExecution); - fail("Expected OptimisticLockingFailureException"); - } - catch (OptimisticLockingFailureException e) { - // expected - assertTrue("Exception message should contain step execution id: " + e.getMessage(), e.getMessage().indexOf( - "" + stepExecution.getId()) >= 0); - assertTrue("Exception message should contain step execution version: " + e.getMessage(), e.getMessage() - .indexOf("" + stepExecution.getVersion()) >= 0); - } - } - - public void testSaveExecutionContext(){ - - stepExecution.setExecutionContext(executionContext); - stepExecutionDao.saveOrUpdateExecutionContext(stepExecution); - ExecutionContext attributes = stepExecutionDao.findExecutionContext(stepExecution); - assertEquals(executionContext, attributes); - executionContext.putString("newString", "newString"); - executionContext.putLong("newLong", 1); - executionContext.putDouble("newDouble", 2.5); - executionContext.put("newSerializable", "serializableValue"); - stepExecutionDao.saveOrUpdateExecutionContext(stepExecution); - attributes = stepExecutionDao.findExecutionContext(stepExecution); - assertEquals(executionContext, attributes); - } - - public void testGetStepExecution() { - assertEquals(stepExecution, stepExecutionDao.getStepExecution(jobExecution, step1)); - } - -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.batch.execution.repository.dao; + +import java.util.Date; +import org.springframework.batch.core.domain.BatchStatus; +import org.springframework.batch.core.domain.Job; +import org.springframework.batch.core.domain.JobExecution; +import org.springframework.batch.core.domain.JobInstance; +import org.springframework.batch.core.domain.JobParameters; +import org.springframework.batch.core.domain.Step; +import org.springframework.batch.core.domain.StepExecution; +import org.springframework.batch.core.runtime.ExitStatusExceptionClassifier; +import org.springframework.batch.execution.job.JobSupport; +import org.springframework.batch.execution.step.StepSupport; +import org.springframework.batch.item.ExecutionContext; +import org.springframework.batch.repeat.ExitStatus; +import org.springframework.dao.OptimisticLockingFailureException; +import org.springframework.test.AbstractTransactionalDataSourceSpringContextTests; +import org.springframework.util.ClassUtils; + +/** + * Tests for step persistence (StepInstanceDao and StepExecutionDao). Because it is very reasonable to assume that there is a + * foreign key constraint on the JobId of a step, the JobDao is used to create + * jobs, to have an id for creating steps. + * + * @author Lucas Ward + * @author Dave Syer + */ +public abstract class AbstractStepDaoTests extends AbstractTransactionalDataSourceSpringContextTests { + + protected JobInstanceDao jobInstanceDao; + + protected StepExecutionDao stepExecutionDao; + + protected JobExecutionDao jobExecutionDao; + + protected JobInstance jobInstance; + + protected Step step1; + + protected Step step2; + + protected StepExecution stepExecution; + + protected JobExecution jobExecution; + + protected JobParameters jobParameters = new JobParameters(); + + protected ExecutionContext executionContext; + + public void setJobInstanceDao(JobInstanceDao jobInstanceDao) { + this.jobInstanceDao = jobInstanceDao; + } + + public void setStepExecutionDao(StepExecutionDao stepExecutionDao) { + this.stepExecutionDao = stepExecutionDao; + } + + public void setJobExecutionDao(JobExecutionDao jobExecutionDao) { + this.jobExecutionDao = jobExecutionDao; + } + + /* + * (non-Javadoc) + * @see org.springframework.test.AbstractSingleSpringContextTests#getConfigLocations() + */ + protected String[] getConfigLocations() { + return new String[] { ClassUtils.addResourcePathToPackagePath(getClass(), "sql-dao-test.xml") }; + } + + /* + * (non-Javadoc) + * @see org.springframework.test.AbstractTransactionalSpringContextTests#onSetUpInTransaction() + */ + protected void onSetUpInTransaction() throws Exception { + Job job = new JobSupport("TestJob"); + jobInstance = jobInstanceDao.createJobInstance(job, jobParameters); + step1 = new StepSupport("TestStep1"); + step2 = new StepSupport("TestStep2"); + jobExecution = new JobExecution(jobInstance); + jobExecutionDao.saveJobExecution(jobExecution); + + stepExecution = new StepExecution(step1, jobExecution, new Long(1)); + stepExecution.setStatus(BatchStatus.STARTED); + stepExecution.setStartTime(new Date(System.currentTimeMillis())); + stepExecutionDao.saveStepExecution(stepExecution); + + executionContext = new ExecutionContext(); + executionContext.putString("1", "testString1"); + executionContext.putString("2", "testString2"); + executionContext.putLong("3", 3); + executionContext.putDouble("4", 4.4); + + + } + + public void testVersionIsNotNullForStepExecution() throws Exception { + int version = jdbcTemplate.queryForInt("select version from BATCH_STEP_EXECUTION where STEP_EXECUTION_ID=" + + stepExecution.getId()); + assertEquals(0, version); + } + + public void testUpdateStepWithExecutionContext() { + stepExecution.setExecutionContext(executionContext); + stepExecutionDao.saveOrUpdateExecutionContext(stepExecution); + ExecutionContext tempAttributes = stepExecutionDao.findExecutionContext(stepExecution); + assertEquals(executionContext, tempAttributes); + } + + public void testSaveStepExecution() { + StepExecution execution = new StepExecution(step2, jobExecution, null); + execution.setStatus(BatchStatus.STARTED); + execution.setStartTime(new Date(System.currentTimeMillis())); + execution.setExitStatus(new ExitStatus(false, ExitStatusExceptionClassifier.FATAL_EXCEPTION, + "java.lang.Exception")); + stepExecutionDao.saveStepExecution(execution); + StepExecution retrievedExecution = stepExecutionDao.getStepExecution(jobExecution, step2); + assertNotNull(retrievedExecution); + assertEquals(execution, retrievedExecution); + assertEquals(execution.getExitStatus(), retrievedExecution.getExitStatus()); + } + + public void testSaveStepExecutionAndExecutionContext() { + StepExecution execution = new StepExecution(step2, jobExecution, null); + execution.setStatus(BatchStatus.STARTED); + execution.setStartTime(new Date(System.currentTimeMillis())); + execution.setExecutionContext(executionContext); + execution.setExitStatus(new ExitStatus(false, ExitStatusExceptionClassifier.FATAL_EXCEPTION, + "java.lang.Exception")); + stepExecutionDao.saveStepExecution(execution); + stepExecutionDao.saveOrUpdateExecutionContext(execution); + StepExecution retrievedExecution = stepExecutionDao.getStepExecution(jobExecution, step2); + assertNotNull(retrievedExecution); + assertEquals(execution, retrievedExecution); + assertEquals(execution.getExecutionContext().getString("1"), retrievedExecution.getExecutionContext().getString("1")); + assertEquals(execution.getExecutionContext().getLong("3"), retrievedExecution.getExecutionContext().getLong("3")); + assertEquals(execution.getExitStatus(), retrievedExecution.getExitStatus()); + } + + public void testUpdateStepExecution() { + + stepExecution.setStatus(BatchStatus.COMPLETED); + stepExecution.setEndTime(new Date(System.currentTimeMillis())); + stepExecution.setCommitCount(5); + stepExecution.setTaskCount(5); + stepExecution.setExecutionContext(new ExecutionContext()); + stepExecution.setExitStatus(new ExitStatus(false, ExitStatusExceptionClassifier.FATAL_EXCEPTION, + "java.lang.Exception")); + stepExecutionDao.updateStepExecution(stepExecution); + StepExecution retrievedExecution = stepExecutionDao.getStepExecution(jobExecution, step1); + assertNotNull(retrievedExecution); + assertEquals(stepExecution, retrievedExecution); + assertEquals(stepExecution.getExitStatus(), retrievedExecution.getExitStatus()); + } + + public void testUpdateStepExecutionWithNullId() { + StepExecution stepExecution = new StepExecution(new StepSupport("testStep"), null, null); + try { + stepExecutionDao.updateStepExecution(stepExecution); + fail("Expected IllegalArgumentException"); + } + catch (IllegalArgumentException ex) { + // expected + } + } + + public void testUpdateStepExecutionVersion() throws Exception { + int before = stepExecution.getVersion().intValue(); + stepExecutionDao.updateStepExecution(stepExecution); + int after = stepExecution.getVersion().intValue(); + assertEquals("StepExecution version not updated", before + 1, after); + } + + public void testUpdateStepExecutionOptimisticLocking() throws Exception { + stepExecution.incrementVersion(); // not really allowed outside dao + // code + try { + stepExecutionDao.updateStepExecution(stepExecution); + fail("Expected OptimisticLockingFailureException"); + } + catch (OptimisticLockingFailureException e) { + // expected + assertTrue("Exception message should contain step execution id: " + e.getMessage(), e.getMessage().indexOf( + "" + stepExecution.getId()) >= 0); + assertTrue("Exception message should contain step execution version: " + e.getMessage(), e.getMessage() + .indexOf("" + stepExecution.getVersion()) >= 0); + } + } + + public void testSaveExecutionContext(){ + + stepExecution.setExecutionContext(executionContext); + stepExecutionDao.saveOrUpdateExecutionContext(stepExecution); + ExecutionContext attributes = stepExecutionDao.findExecutionContext(stepExecution); + assertEquals(executionContext, attributes); + executionContext.putString("newString", "newString"); + executionContext.putLong("newLong", 1); + executionContext.putDouble("newDouble", 2.5); + executionContext.put("newSerializable", "serializableValue"); + stepExecutionDao.saveOrUpdateExecutionContext(stepExecution); + attributes = stepExecutionDao.findExecutionContext(stepExecution); + assertEquals(executionContext, attributes); + } + + public void testGetStepExecution() { + assertEquals(stepExecution, stepExecutionDao.getStepExecution(jobExecution, step1)); + } + +} diff --git a/spring-batch-execution/src/test/java/org/springframework/batch/execution/repository/dao/JdbcJobDaoQueryTests.java b/spring-batch-execution/src/test/java/org/springframework/batch/execution/repository/dao/JdbcJobDaoQueryTests.java index 304a636a8b..47e263207a 100644 --- a/spring-batch-execution/src/test/java/org/springframework/batch/execution/repository/dao/JdbcJobDaoQueryTests.java +++ b/spring-batch-execution/src/test/java/org/springframework/batch/execution/repository/dao/JdbcJobDaoQueryTests.java @@ -1,82 +1,82 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.execution.repository.dao; - -import java.util.ArrayList; -import java.util.List; - -import junit.framework.TestCase; - -import org.springframework.batch.core.domain.JobExecution; -import org.springframework.batch.core.domain.JobInstance; -import org.springframework.batch.core.domain.JobParameters; -import org.springframework.batch.execution.job.JobSupport; -import org.springframework.dao.DataAccessException; -import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.jdbc.support.incrementer.DataFieldMaxValueIncrementer; - -/** - * @author Dave Syer - * - */ -public class JdbcJobDaoQueryTests extends TestCase { - - JdbcJobExecutionDao jobExecutionDao; - - List list = new ArrayList(); - - /* - * (non-Javadoc) - * @see junit.framework.TestCase#setUp() - */ - protected void setUp() throws Exception { - - jobExecutionDao = new JdbcJobExecutionDao(); - jobExecutionDao.setJobExecutionIncrementer(new DataFieldMaxValueIncrementer() { - - public int nextIntValue() throws DataAccessException { - return 0; - } - - public long nextLongValue() throws DataAccessException { - return 0; - } - - public String nextStringValue() throws DataAccessException { - return "bar"; - } - - }); - } - - public void testTablePrefix() throws Exception { - jobExecutionDao.setTablePrefix("FOO_"); - jobExecutionDao.setJdbcTemplate(new JdbcTemplate() { - public int update(String sql, Object[] args, int[] argTypes) throws DataAccessException { - list.add(sql); - return 1; - } - }); - JobExecution jobExecution = new JobExecution(new JobInstance(new Long(11), new JobParameters(), new JobSupport( - "testJob"))); - - jobExecutionDao.saveJobExecution(jobExecution); - assertEquals(1, list.size()); - String query = (String) list.get(0); - assertTrue("Query did not contain FOO_:" + query, query.indexOf("FOO_") >= 0); - } - -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.execution.repository.dao; + +import java.util.ArrayList; +import java.util.List; + +import junit.framework.TestCase; + +import org.springframework.batch.core.domain.JobExecution; +import org.springframework.batch.core.domain.JobInstance; +import org.springframework.batch.core.domain.JobParameters; +import org.springframework.batch.execution.job.JobSupport; +import org.springframework.dao.DataAccessException; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.support.incrementer.DataFieldMaxValueIncrementer; + +/** + * @author Dave Syer + * + */ +public class JdbcJobDaoQueryTests extends TestCase { + + JdbcJobExecutionDao jobExecutionDao; + + List list = new ArrayList(); + + /* + * (non-Javadoc) + * @see junit.framework.TestCase#setUp() + */ + protected void setUp() throws Exception { + + jobExecutionDao = new JdbcJobExecutionDao(); + jobExecutionDao.setJobExecutionIncrementer(new DataFieldMaxValueIncrementer() { + + public int nextIntValue() throws DataAccessException { + return 0; + } + + public long nextLongValue() throws DataAccessException { + return 0; + } + + public String nextStringValue() throws DataAccessException { + return "bar"; + } + + }); + } + + public void testTablePrefix() throws Exception { + jobExecutionDao.setTablePrefix("FOO_"); + jobExecutionDao.setJdbcTemplate(new JdbcTemplate() { + public int update(String sql, Object[] args, int[] argTypes) throws DataAccessException { + list.add(sql); + return 1; + } + }); + JobExecution jobExecution = new JobExecution(new JobInstance(new Long(11), new JobParameters(), new JobSupport( + "testJob"))); + + jobExecutionDao.saveJobExecution(jobExecution); + assertEquals(1, list.size()); + String query = (String) list.get(0); + assertTrue("Query did not contain FOO_:" + query, query.indexOf("FOO_") >= 0); + } + +} diff --git a/spring-batch-execution/src/test/java/org/springframework/batch/execution/repository/dao/JdbcJobDaoTests.java b/spring-batch-execution/src/test/java/org/springframework/batch/execution/repository/dao/JdbcJobDaoTests.java index 6befe0b54f..a86df022ae 100644 --- a/spring-batch-execution/src/test/java/org/springframework/batch/execution/repository/dao/JdbcJobDaoTests.java +++ b/spring-batch-execution/src/test/java/org/springframework/batch/execution/repository/dao/JdbcJobDaoTests.java @@ -1,32 +1,32 @@ -package org.springframework.batch.execution.repository.dao; - -import java.util.List; -import java.util.Map; - -import org.springframework.batch.repeat.ExitStatus; - -public class JdbcJobDaoTests extends AbstractJobDaoTests { - - public static final String LONG_STRING = "A very long String A very long String A very long String A very long String A very long String A very long String A very long String A very long String A very long String A very long String A very long String A very long String A very long String A very long String A very long String A very long String A very long String A very long String A very long String "; - - protected void onSetUpBeforeTransaction() throws Exception { - ((JdbcJobInstanceDao) jobInstanceDao).setTablePrefix(AbstractJdbcBatchMetadataDao.DEFAULT_TABLE_PREFIX); - ((JdbcJobExecutionDao) jobExecutionDao).setTablePrefix(AbstractJdbcBatchMetadataDao.DEFAULT_TABLE_PREFIX); - } - - public void testUpdateJobExecutionWithLongExitCode() { - - assertTrue(LONG_STRING.length() > 250); - jobExecution.setExitStatus(ExitStatus.FINISHED - .addExitDescription(LONG_STRING)); - jobExecutionDao.updateJobExecution(jobExecution); - - List executions = jdbcTemplate.queryForList( - "SELECT * FROM BATCH_JOB_EXECUTION where JOB_INSTANCE_ID=?", - new Object[] { jobInstance.getId() }); - assertEquals(1, executions.size()); - assertEquals(LONG_STRING.substring(0, 250), ((Map) executions.get(0)) - .get("EXIT_MESSAGE")); - } - -} +package org.springframework.batch.execution.repository.dao; + +import java.util.List; +import java.util.Map; + +import org.springframework.batch.repeat.ExitStatus; + +public class JdbcJobDaoTests extends AbstractJobDaoTests { + + public static final String LONG_STRING = "A very long String A very long String A very long String A very long String A very long String A very long String A very long String A very long String A very long String A very long String A very long String A very long String A very long String A very long String A very long String A very long String A very long String A very long String A very long String "; + + protected void onSetUpBeforeTransaction() throws Exception { + ((JdbcJobInstanceDao) jobInstanceDao).setTablePrefix(AbstractJdbcBatchMetadataDao.DEFAULT_TABLE_PREFIX); + ((JdbcJobExecutionDao) jobExecutionDao).setTablePrefix(AbstractJdbcBatchMetadataDao.DEFAULT_TABLE_PREFIX); + } + + public void testUpdateJobExecutionWithLongExitCode() { + + assertTrue(LONG_STRING.length() > 250); + jobExecution.setExitStatus(ExitStatus.FINISHED + .addExitDescription(LONG_STRING)); + jobExecutionDao.updateJobExecution(jobExecution); + + List executions = jdbcTemplate.queryForList( + "SELECT * FROM BATCH_JOB_EXECUTION where JOB_INSTANCE_ID=?", + new Object[] { jobInstance.getId() }); + assertEquals(1, executions.size()); + assertEquals(LONG_STRING.substring(0, 250), ((Map) executions.get(0)) + .get("EXIT_MESSAGE")); + } + +} diff --git a/spring-batch-execution/src/test/java/org/springframework/batch/execution/repository/dao/JdbcStepDaoPrefixTests.java b/spring-batch-execution/src/test/java/org/springframework/batch/execution/repository/dao/JdbcStepDaoPrefixTests.java index 667b0c4639..c678cc1f6e 100644 --- a/spring-batch-execution/src/test/java/org/springframework/batch/execution/repository/dao/JdbcStepDaoPrefixTests.java +++ b/spring-batch-execution/src/test/java/org/springframework/batch/execution/repository/dao/JdbcStepDaoPrefixTests.java @@ -1,111 +1,111 @@ -package org.springframework.batch.execution.repository.dao; - -import java.util.List; - -import junit.framework.TestCase; - -import org.easymock.MockControl; -import org.springframework.batch.core.domain.JobExecution; -import org.springframework.batch.core.domain.JobInstance; -import org.springframework.batch.core.domain.JobParameters; -import org.springframework.batch.core.domain.Step; -import org.springframework.batch.core.domain.StepExecution; -import org.springframework.batch.execution.job.JobSupport; -import org.springframework.batch.execution.step.StepSupport; -import org.springframework.dao.DataAccessException; -import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.jdbc.core.RowMapper; -import org.springframework.jdbc.support.incrementer.DataFieldMaxValueIncrementer; - -/** - * Unit Test of SqlStepDao that only tests prefix matching. A - * separate test is needed because all other tests hit hsql, - * while this test needs to mock JdbcTemplate to analyze the - * Sql passed in. - * - * @author Lucas Ward - * - */ -public class JdbcStepDaoPrefixTests extends TestCase { - - private JdbcStepExecutionDao stepExecutionDao; - - MockJdbcTemplate jdbcTemplate = new MockJdbcTemplate(); - - JobInstance job = new JobInstance(new Long(1), new JobParameters(), new JobSupport("testJob")); - Step step = new StepSupport("foo"); - StepExecution stepExecution = new StepExecution(step, new JobExecution(job), null); - - MockControl stepExecutionIncrementerControl = MockControl.createControl(DataFieldMaxValueIncrementer.class); - DataFieldMaxValueIncrementer stepExecutionIncrementer; - MockControl stepIncrementerControl = MockControl.createControl(DataFieldMaxValueIncrementer.class); - DataFieldMaxValueIncrementer stepIncrementer; - - protected void setUp() throws Exception { - super.setUp(); - - stepExecutionDao = new JdbcStepExecutionDao(); - stepExecutionIncrementer = (DataFieldMaxValueIncrementer)stepExecutionIncrementerControl.getMock(); - stepIncrementer = (DataFieldMaxValueIncrementer)stepIncrementerControl.getMock(); - - stepExecutionDao.setJdbcTemplate(jdbcTemplate); - stepExecutionDao.setStepExecutionIncrementer(stepExecutionIncrementer); - stepExecution.setId(new Long(1)); - stepExecution.incrementVersion(); - - } - - public void testModifiedUpdateStepExecution(){ - stepExecutionDao.setTablePrefix("FOO_"); - stepExecutionDao.updateStepExecution(stepExecution); - assertTrue(jdbcTemplate.getSqlStatement().indexOf("FOO_STEP_EXECUTION") != -1); - } - - public void testModifiedSaveStepExecution(){ - stepExecutionDao.setTablePrefix("FOO_"); - stepExecutionIncrementer.nextLongValue(); - stepExecutionIncrementerControl.setReturnValue(1); - stepExecutionIncrementerControl.replay(); - stepExecutionDao.saveStepExecution(stepExecution); - assertTrue(jdbcTemplate.getSqlStatement().indexOf("FOO_STEP_EXECUTION") != -1); - } - - public void testDefaultSaveStepExecution(){ - stepExecutionIncrementer.nextLongValue(); - stepExecutionIncrementerControl.setReturnValue(1); - stepExecutionIncrementerControl.replay(); - stepExecutionDao.saveStepExecution(stepExecution); - assertTrue(jdbcTemplate.getSqlStatement().indexOf("BATCH_STEP_EXECUTION") != -1); - } - - public void testDefaultUpdateStepExecution(){ - stepExecutionDao.updateStepExecution(stepExecution); - assertTrue(jdbcTemplate.getSqlStatement().indexOf("BATCH_STEP_EXECUTION") != -1); - } - - private class MockJdbcTemplate extends JdbcTemplate { - - private String sql; - - public int update(String sql, Object[] args) throws DataAccessException { - this.sql = sql; - return 1; - } - - public int update(String sql, Object[] args, int[] argTypes) throws DataAccessException { - this.sql = sql; - return 1; - } - - public List query(String sql, Object[] args, RowMapper rowMapper) throws DataAccessException { - this.sql = sql; - return null; - } - - public String getSqlStatement() { - return sql; - } - - } - -} +package org.springframework.batch.execution.repository.dao; + +import java.util.List; + +import junit.framework.TestCase; + +import org.easymock.MockControl; +import org.springframework.batch.core.domain.JobExecution; +import org.springframework.batch.core.domain.JobInstance; +import org.springframework.batch.core.domain.JobParameters; +import org.springframework.batch.core.domain.Step; +import org.springframework.batch.core.domain.StepExecution; +import org.springframework.batch.execution.job.JobSupport; +import org.springframework.batch.execution.step.StepSupport; +import org.springframework.dao.DataAccessException; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.RowMapper; +import org.springframework.jdbc.support.incrementer.DataFieldMaxValueIncrementer; + +/** + * Unit Test of SqlStepDao that only tests prefix matching. A + * separate test is needed because all other tests hit hsql, + * while this test needs to mock JdbcTemplate to analyze the + * Sql passed in. + * + * @author Lucas Ward + * + */ +public class JdbcStepDaoPrefixTests extends TestCase { + + private JdbcStepExecutionDao stepExecutionDao; + + MockJdbcTemplate jdbcTemplate = new MockJdbcTemplate(); + + JobInstance job = new JobInstance(new Long(1), new JobParameters(), new JobSupport("testJob")); + Step step = new StepSupport("foo"); + StepExecution stepExecution = new StepExecution(step, new JobExecution(job), null); + + MockControl stepExecutionIncrementerControl = MockControl.createControl(DataFieldMaxValueIncrementer.class); + DataFieldMaxValueIncrementer stepExecutionIncrementer; + MockControl stepIncrementerControl = MockControl.createControl(DataFieldMaxValueIncrementer.class); + DataFieldMaxValueIncrementer stepIncrementer; + + protected void setUp() throws Exception { + super.setUp(); + + stepExecutionDao = new JdbcStepExecutionDao(); + stepExecutionIncrementer = (DataFieldMaxValueIncrementer)stepExecutionIncrementerControl.getMock(); + stepIncrementer = (DataFieldMaxValueIncrementer)stepIncrementerControl.getMock(); + + stepExecutionDao.setJdbcTemplate(jdbcTemplate); + stepExecutionDao.setStepExecutionIncrementer(stepExecutionIncrementer); + stepExecution.setId(new Long(1)); + stepExecution.incrementVersion(); + + } + + public void testModifiedUpdateStepExecution(){ + stepExecutionDao.setTablePrefix("FOO_"); + stepExecutionDao.updateStepExecution(stepExecution); + assertTrue(jdbcTemplate.getSqlStatement().indexOf("FOO_STEP_EXECUTION") != -1); + } + + public void testModifiedSaveStepExecution(){ + stepExecutionDao.setTablePrefix("FOO_"); + stepExecutionIncrementer.nextLongValue(); + stepExecutionIncrementerControl.setReturnValue(1); + stepExecutionIncrementerControl.replay(); + stepExecutionDao.saveStepExecution(stepExecution); + assertTrue(jdbcTemplate.getSqlStatement().indexOf("FOO_STEP_EXECUTION") != -1); + } + + public void testDefaultSaveStepExecution(){ + stepExecutionIncrementer.nextLongValue(); + stepExecutionIncrementerControl.setReturnValue(1); + stepExecutionIncrementerControl.replay(); + stepExecutionDao.saveStepExecution(stepExecution); + assertTrue(jdbcTemplate.getSqlStatement().indexOf("BATCH_STEP_EXECUTION") != -1); + } + + public void testDefaultUpdateStepExecution(){ + stepExecutionDao.updateStepExecution(stepExecution); + assertTrue(jdbcTemplate.getSqlStatement().indexOf("BATCH_STEP_EXECUTION") != -1); + } + + private class MockJdbcTemplate extends JdbcTemplate { + + private String sql; + + public int update(String sql, Object[] args) throws DataAccessException { + this.sql = sql; + return 1; + } + + public int update(String sql, Object[] args, int[] argTypes) throws DataAccessException { + this.sql = sql; + return 1; + } + + public List query(String sql, Object[] args, RowMapper rowMapper) throws DataAccessException { + this.sql = sql; + return null; + } + + public String getSqlStatement() { + return sql; + } + + } + +} diff --git a/spring-batch-execution/src/test/java/org/springframework/batch/execution/repository/dao/JdbcStepDaoTests.java b/spring-batch-execution/src/test/java/org/springframework/batch/execution/repository/dao/JdbcStepDaoTests.java index 04e11a99fc..bb762732bf 100644 --- a/spring-batch-execution/src/test/java/org/springframework/batch/execution/repository/dao/JdbcStepDaoTests.java +++ b/spring-batch-execution/src/test/java/org/springframework/batch/execution/repository/dao/JdbcStepDaoTests.java @@ -1,41 +1,41 @@ -package org.springframework.batch.execution.repository.dao; - -import java.util.List; -import java.util.Map; - -import org.springframework.batch.repeat.ExitStatus; - -public class JdbcStepDaoTests extends AbstractStepDaoTests { - - private static final String LONG_STRING = JdbcJobDaoTests.LONG_STRING; - - protected void onSetUpBeforeTransaction() throws Exception { - ((JdbcStepExecutionDao) stepExecutionDao).setTablePrefix(AbstractJdbcBatchMetadataDao.DEFAULT_TABLE_PREFIX); - } - - public void testTablePrefix() throws Exception { -// ((JdbcStepInstanceDao) stepInstanceDao).setTablePrefix("FOO_"); -// ((JdbcStepExecutionDao) stepExecutionDao).setTablePrefix("FOO_"); -// try { -// testCreateStep(); -// fail("Expected DataAccessException"); -// } catch (DataAccessException e) { -// // expected -// } - } - - public void testUpdateStepExecutionWithLongExitCode() { - - assertTrue(LONG_STRING.length()>250); - stepExecution.setExitStatus(ExitStatus.FINISHED.addExitDescription(LONG_STRING)); - stepExecutionDao.updateStepExecution(stepExecution); - - List executions = jdbcTemplate.queryForList( - "SELECT * FROM BATCH_STEP_EXECUTION where STEP_NAME=?", - new Object[] { step1.getName() }); - assertEquals(1, executions.size()); - assertEquals(LONG_STRING.substring(0, 250), ((Map) executions.get(0)) - .get("EXIT_MESSAGE")); - } - -} +package org.springframework.batch.execution.repository.dao; + +import java.util.List; +import java.util.Map; + +import org.springframework.batch.repeat.ExitStatus; + +public class JdbcStepDaoTests extends AbstractStepDaoTests { + + private static final String LONG_STRING = JdbcJobDaoTests.LONG_STRING; + + protected void onSetUpBeforeTransaction() throws Exception { + ((JdbcStepExecutionDao) stepExecutionDao).setTablePrefix(AbstractJdbcBatchMetadataDao.DEFAULT_TABLE_PREFIX); + } + + public void testTablePrefix() throws Exception { +// ((JdbcStepInstanceDao) stepInstanceDao).setTablePrefix("FOO_"); +// ((JdbcStepExecutionDao) stepExecutionDao).setTablePrefix("FOO_"); +// try { +// testCreateStep(); +// fail("Expected DataAccessException"); +// } catch (DataAccessException e) { +// // expected +// } + } + + public void testUpdateStepExecutionWithLongExitCode() { + + assertTrue(LONG_STRING.length()>250); + stepExecution.setExitStatus(ExitStatus.FINISHED.addExitDescription(LONG_STRING)); + stepExecutionDao.updateStepExecution(stepExecution); + + List executions = jdbcTemplate.queryForList( + "SELECT * FROM BATCH_STEP_EXECUTION where STEP_NAME=?", + new Object[] { step1.getName() }); + assertEquals(1, executions.size()); + assertEquals(LONG_STRING.substring(0, 250), ((Map) executions.get(0)) + .get("EXIT_MESSAGE")); + } + +} diff --git a/spring-batch-execution/src/test/java/org/springframework/batch/execution/repository/dao/MapJobExecutionDaoTests.java b/spring-batch-execution/src/test/java/org/springframework/batch/execution/repository/dao/MapJobExecutionDaoTests.java index 7d5fe2ba6c..b829304a8d 100644 --- a/spring-batch-execution/src/test/java/org/springframework/batch/execution/repository/dao/MapJobExecutionDaoTests.java +++ b/spring-batch-execution/src/test/java/org/springframework/batch/execution/repository/dao/MapJobExecutionDaoTests.java @@ -1,94 +1,94 @@ -package org.springframework.batch.execution.repository.dao; - -import java.util.Date; -import java.util.List; - -import junit.framework.TestCase; - -import org.springframework.batch.core.domain.BatchStatus; -import org.springframework.batch.core.domain.JobExecution; -import org.springframework.batch.core.domain.JobInstance; -import org.springframework.batch.core.domain.JobParameters; -import org.springframework.batch.execution.job.JobSupport; - -public class MapJobExecutionDaoTests extends TestCase { - - JobExecutionDao dao = new MapJobExecutionDao(); - - JobInstance jobInstance = new JobInstance(new Long(1), new JobParameters(), new JobSupport("execTestJob")); - - JobExecution execution = new JobExecution(jobInstance); - - protected void setUp() throws Exception { - MapJobExecutionDao.clear(); - } - - /** - * Save and find a job execution. - */ - public void testSaveAndFind() { - - dao.saveJobExecution(execution); - - List executions = dao.findJobExecutions(jobInstance); - assertTrue(executions.size() == 1); - assertEquals(execution, executions.get(0)); - } - - /** - * Saving sets id to the entity. - */ - public void testSaveAddsId() { - - assertNull(execution.getId()); - dao.saveJobExecution(execution); - assertNotNull(execution.getId()); - } - - /** - * Execution count increases by one with every save for the same job - * instance. - */ - public void testGetExecutionCount() { - - JobExecution exec1 = new JobExecution(jobInstance); - JobExecution exec2 = new JobExecution(jobInstance); - - dao.saveJobExecution(exec1); - assertEquals(1, dao.getJobExecutionCount(jobInstance)); - - dao.saveJobExecution(exec2); - assertEquals(2, dao.getJobExecutionCount(jobInstance)); - } - - /** - * Update and retrieve job execution - check attributes have changed as - * expected. - */ - public void testUpdateExecution() { - execution.setStatus(BatchStatus.STARTED); - dao.saveJobExecution(execution); - - execution.setStatus(BatchStatus.COMPLETED); - dao.updateJobExecution(execution); - - JobExecution updated = (JobExecution) dao.findJobExecutions(jobInstance).get(0); - assertEquals(execution, updated); - assertEquals(BatchStatus.COMPLETED, updated.getStatus()); - } - - /** - * Check the execution with most recent start time is returned - */ - public void testGetLastExecution() { - JobExecution exec1 = new JobExecution(jobInstance); - exec1.setStartTime(new Date(0)); - JobExecution exec2 = new JobExecution(jobInstance); - exec2.setStartTime(new Date(1)); - - dao.saveJobExecution(exec1); - dao.saveJobExecution(exec2); - - assertEquals(exec2, dao.getLastJobExecution(jobInstance)); - } -} +package org.springframework.batch.execution.repository.dao; + +import java.util.Date; +import java.util.List; + +import junit.framework.TestCase; + +import org.springframework.batch.core.domain.BatchStatus; +import org.springframework.batch.core.domain.JobExecution; +import org.springframework.batch.core.domain.JobInstance; +import org.springframework.batch.core.domain.JobParameters; +import org.springframework.batch.execution.job.JobSupport; + +public class MapJobExecutionDaoTests extends TestCase { + + JobExecutionDao dao = new MapJobExecutionDao(); + + JobInstance jobInstance = new JobInstance(new Long(1), new JobParameters(), new JobSupport("execTestJob")); + + JobExecution execution = new JobExecution(jobInstance); + + protected void setUp() throws Exception { + MapJobExecutionDao.clear(); + } + + /** + * Save and find a job execution. + */ + public void testSaveAndFind() { + + dao.saveJobExecution(execution); + + List executions = dao.findJobExecutions(jobInstance); + assertTrue(executions.size() == 1); + assertEquals(execution, executions.get(0)); + } + + /** + * Saving sets id to the entity. + */ + public void testSaveAddsId() { + + assertNull(execution.getId()); + dao.saveJobExecution(execution); + assertNotNull(execution.getId()); + } + + /** + * Execution count increases by one with every save for the same job + * instance. + */ + public void testGetExecutionCount() { + + JobExecution exec1 = new JobExecution(jobInstance); + JobExecution exec2 = new JobExecution(jobInstance); + + dao.saveJobExecution(exec1); + assertEquals(1, dao.getJobExecutionCount(jobInstance)); + + dao.saveJobExecution(exec2); + assertEquals(2, dao.getJobExecutionCount(jobInstance)); + } + + /** + * Update and retrieve job execution - check attributes have changed as + * expected. + */ + public void testUpdateExecution() { + execution.setStatus(BatchStatus.STARTED); + dao.saveJobExecution(execution); + + execution.setStatus(BatchStatus.COMPLETED); + dao.updateJobExecution(execution); + + JobExecution updated = (JobExecution) dao.findJobExecutions(jobInstance).get(0); + assertEquals(execution, updated); + assertEquals(BatchStatus.COMPLETED, updated.getStatus()); + } + + /** + * Check the execution with most recent start time is returned + */ + public void testGetLastExecution() { + JobExecution exec1 = new JobExecution(jobInstance); + exec1.setStartTime(new Date(0)); + JobExecution exec2 = new JobExecution(jobInstance); + exec2.setStartTime(new Date(1)); + + dao.saveJobExecution(exec1); + dao.saveJobExecution(exec2); + + assertEquals(exec2, dao.getLastJobExecution(jobInstance)); + } +} diff --git a/spring-batch-execution/src/test/java/org/springframework/batch/execution/repository/dao/MapJobInstanceDaoTests.java b/spring-batch-execution/src/test/java/org/springframework/batch/execution/repository/dao/MapJobInstanceDaoTests.java index 4167a0a93a..4dba3166c0 100644 --- a/spring-batch-execution/src/test/java/org/springframework/batch/execution/repository/dao/MapJobInstanceDaoTests.java +++ b/spring-batch-execution/src/test/java/org/springframework/batch/execution/repository/dao/MapJobInstanceDaoTests.java @@ -1,56 +1,56 @@ -package org.springframework.batch.execution.repository.dao; - -import junit.framework.TestCase; - -import org.springframework.batch.core.domain.Job; -import org.springframework.batch.core.domain.JobInstance; -import org.springframework.batch.core.domain.JobParameters; -import org.springframework.batch.core.domain.JobParametersBuilder; -import org.springframework.batch.execution.job.JobSupport; - -public class MapJobInstanceDaoTests extends TestCase { - - private JobInstanceDao dao = new MapJobInstanceDao(); - - private Job fooJob = new JobSupport("foo"); - - private JobParameters fooParams = new JobParametersBuilder().addString("fooKey", "fooValue").toJobParameters(); - - protected void setUp() throws Exception { - MapJobInstanceDao.clear(); - } - - protected void tearDown() throws Exception { - MapJobInstanceDao.clear(); - } - - /** - * Create and retrieve a job instance. - */ - public void testCreateAndRetrieve() throws Exception { - - JobInstance fooInstance = dao.createJobInstance(fooJob, fooParams); - assertNotNull(fooInstance.getId()); - assertEquals(fooJob, fooInstance.getJob()); - assertEquals(fooParams, fooInstance.getJobParameters()); - - JobInstance retrievedInstance = dao.getJobInstance(fooJob, fooParams); - assertEquals(fooInstance, retrievedInstance); - } - - /** - * Trying to create instance twice for the same job+parameters causes error - */ - public void testCreateDuplicateInstance() { - - dao.createJobInstance(fooJob, fooParams); - - try { - dao.createJobInstance(fooJob, fooParams); - fail(); - } - catch (IllegalStateException e) { - // expected - } - } -} +package org.springframework.batch.execution.repository.dao; + +import junit.framework.TestCase; + +import org.springframework.batch.core.domain.Job; +import org.springframework.batch.core.domain.JobInstance; +import org.springframework.batch.core.domain.JobParameters; +import org.springframework.batch.core.domain.JobParametersBuilder; +import org.springframework.batch.execution.job.JobSupport; + +public class MapJobInstanceDaoTests extends TestCase { + + private JobInstanceDao dao = new MapJobInstanceDao(); + + private Job fooJob = new JobSupport("foo"); + + private JobParameters fooParams = new JobParametersBuilder().addString("fooKey", "fooValue").toJobParameters(); + + protected void setUp() throws Exception { + MapJobInstanceDao.clear(); + } + + protected void tearDown() throws Exception { + MapJobInstanceDao.clear(); + } + + /** + * Create and retrieve a job instance. + */ + public void testCreateAndRetrieve() throws Exception { + + JobInstance fooInstance = dao.createJobInstance(fooJob, fooParams); + assertNotNull(fooInstance.getId()); + assertEquals(fooJob, fooInstance.getJob()); + assertEquals(fooParams, fooInstance.getJobParameters()); + + JobInstance retrievedInstance = dao.getJobInstance(fooJob, fooParams); + assertEquals(fooInstance, retrievedInstance); + } + + /** + * Trying to create instance twice for the same job+parameters causes error + */ + public void testCreateDuplicateInstance() { + + dao.createJobInstance(fooJob, fooParams); + + try { + dao.createJobInstance(fooJob, fooParams); + fail(); + } + catch (IllegalStateException e) { + // expected + } + } +} diff --git a/spring-batch-execution/src/test/java/org/springframework/batch/execution/repository/dao/NoSuchBatchDomainObjectExceptionTests.java b/spring-batch-execution/src/test/java/org/springframework/batch/execution/repository/dao/NoSuchBatchDomainObjectExceptionTests.java index 2386a27137..9a0f2a13a6 100644 --- a/spring-batch-execution/src/test/java/org/springframework/batch/execution/repository/dao/NoSuchBatchDomainObjectExceptionTests.java +++ b/spring-batch-execution/src/test/java/org/springframework/batch/execution/repository/dao/NoSuchBatchDomainObjectExceptionTests.java @@ -1,32 +1,32 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.execution.repository.dao; - -import org.springframework.batch.execution.repository.dao.NoSuchObjectException; - -import junit.framework.TestCase; - -/** - * @author Dave Syer - * - */ -public class NoSuchBatchDomainObjectExceptionTests extends TestCase { - - public void testCreateException() throws Exception { - NoSuchObjectException e = new NoSuchObjectException("Foo"); - assertEquals("Foo", e.getMessage()); - } -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.execution.repository.dao; + +import org.springframework.batch.execution.repository.dao.NoSuchObjectException; + +import junit.framework.TestCase; + +/** + * @author Dave Syer + * + */ +public class NoSuchBatchDomainObjectExceptionTests extends TestCase { + + public void testCreateException() throws Exception { + NoSuchObjectException e = new NoSuchObjectException("Foo"); + assertEquals("Foo", e.getMessage()); + } +} diff --git a/spring-batch-execution/src/test/java/org/springframework/batch/execution/step/ItemOrientedStepTests.java b/spring-batch-execution/src/test/java/org/springframework/batch/execution/step/ItemOrientedStepTests.java index cbf2ea1474..8a252515e9 100644 --- a/spring-batch-execution/src/test/java/org/springframework/batch/execution/step/ItemOrientedStepTests.java +++ b/spring-batch-execution/src/test/java/org/springframework/batch/execution/step/ItemOrientedStepTests.java @@ -1,715 +1,715 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.batch.execution.step; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import junit.framework.TestCase; - -import org.springframework.batch.core.domain.BatchStatus; -import org.springframework.batch.core.domain.JobExecution; -import org.springframework.batch.core.domain.JobInstance; -import org.springframework.batch.core.domain.JobInterruptedException; -import org.springframework.batch.core.domain.JobParameters; -import org.springframework.batch.core.domain.StepContribution; -import org.springframework.batch.core.domain.StepExecution; -import org.springframework.batch.core.domain.StepListener; -import org.springframework.batch.core.listener.StepListenerSupport; -import org.springframework.batch.execution.job.JobSupport; -import org.springframework.batch.execution.repository.SimpleJobRepository; -import org.springframework.batch.execution.repository.dao.MapJobExecutionDao; -import org.springframework.batch.execution.repository.dao.MapJobInstanceDao; -import org.springframework.batch.execution.repository.dao.MapStepExecutionDao; -import org.springframework.batch.execution.step.support.JobRepositorySupport; -import org.springframework.batch.execution.step.support.SimpleItemHandler; -import org.springframework.batch.execution.step.support.StepInterruptionPolicy; -import org.springframework.batch.io.exception.InfrastructureException; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.item.ItemReader; -import org.springframework.batch.item.ItemStream; -import org.springframework.batch.item.ItemWriter; -import org.springframework.batch.item.exception.MarkFailedException; -import org.springframework.batch.item.exception.ResetFailedException; -import org.springframework.batch.item.exception.StreamException; -import org.springframework.batch.item.reader.AbstractItemReader; -import org.springframework.batch.item.reader.ListItemReader; -import org.springframework.batch.item.stream.ItemStreamSupport; -import org.springframework.batch.item.writer.AbstractItemWriter; -import org.springframework.batch.repeat.ExitStatus; -import org.springframework.batch.repeat.RepeatContext; -import org.springframework.batch.repeat.policy.SimpleCompletionPolicy; -import org.springframework.batch.repeat.support.RepeatTemplate; -import org.springframework.batch.support.PropertiesConverter; -import org.springframework.batch.support.transaction.ResourcelessTransactionManager; -import org.springframework.transaction.TransactionException; -import org.springframework.transaction.support.DefaultTransactionStatus; - -public class ItemOrientedStepTests extends TestCase { - - ArrayList processed = new ArrayList(); - - private List list = new ArrayList(); - - ItemWriter itemWriter = new AbstractItemWriter() { - public void write(Object data) throws Exception { - processed.add((String) data); - } - }; - - private ItemOrientedStep itemOrientedStep; - - private RepeatTemplate template; - - private JobInstance jobInstance; - - private ResourcelessTransactionManager transactionManager; - - private ItemReader getReader(String[] args) { - return new ListItemReader(Arrays.asList(args)); - } - - private AbstractStep getStep(String[] strings) throws Exception { - ItemOrientedStep step = new ItemOrientedStep("stepName"); - step.setItemHandler(new SimpleItemHandler(getReader(strings), itemWriter)); - step.setJobRepository(new JobRepositorySupport()); - step.setTransactionManager(transactionManager); - return step; - } - - protected void setUp() throws Exception { - transactionManager = new ResourcelessTransactionManager(); - - itemOrientedStep = (ItemOrientedStep) getStep(new String[] { "foo", "bar", "spam" }); - template = new RepeatTemplate(); - template.setCompletionPolicy(new SimpleCompletionPolicy(1)); - itemOrientedStep.setStepOperations(template); - // Only process one item: - template = new RepeatTemplate(); - template.setCompletionPolicy(new SimpleCompletionPolicy(1)); - itemOrientedStep.setChunkOperations(template); - - jobInstance = new JobInstance(new Long(0), new JobParameters(), new JobSupport("FOO")); - - itemOrientedStep.setTransactionManager(transactionManager); - - } - - public void testStepExecutor() throws Exception { - - JobExecution jobExecutionContext = new JobExecution(jobInstance); - StepExecution stepExecution = new StepExecution(itemOrientedStep, jobExecutionContext); - - itemOrientedStep.execute(stepExecution); - assertEquals(1, processed.size()); - assertEquals(1, stepExecution.getTaskCount().intValue()); - } - - public void testChunkExecutor() throws Exception { - - template = new RepeatTemplate(); - - // Only process one item: - template.setCompletionPolicy(new SimpleCompletionPolicy(1)); - itemOrientedStep.setChunkOperations(template); - - JobExecution jobExecution = new JobExecution(jobInstance); - - StepExecution stepExecution = new StepExecution(itemOrientedStep, jobExecution); - StepContribution contribution = stepExecution.createStepContribution(); - itemOrientedStep.processChunk(contribution); - assertEquals(1, processed.size()); - assertEquals(0, stepExecution.getTaskCount().intValue()); - assertEquals(1, contribution.getTaskCount()); - - } - - public void testRepository() throws Exception { - - SimpleJobRepository repository = new SimpleJobRepository(new MapJobInstanceDao(), new MapJobExecutionDao(), new MapStepExecutionDao()); - itemOrientedStep.setJobRepository(repository); - - JobExecution jobExecution = repository.createJobExecution(jobInstance.getJob(), jobInstance.getJobParameters()); - StepExecution stepExecution = new StepExecution(itemOrientedStep, jobExecution); - - itemOrientedStep.execute(stepExecution); - assertEquals(1, processed.size()); - } - - public void testIncrementRollbackCount() { - - ItemReader itemReader = new AbstractItemReader() { - - public Object read() throws Exception { - int counter = 0; - counter++; - - if (counter == 1) { - throw new RuntimeException(); - } - - return ExitStatus.CONTINUABLE; - } - - }; - - itemOrientedStep.setItemHandler(new SimpleItemHandler(itemReader, itemWriter)); - JobExecution jobExecutionContext = new JobExecution(jobInstance); - StepExecution stepExecution = new StepExecution(itemOrientedStep, jobExecutionContext); - - try { - itemOrientedStep.execute(stepExecution); - } - catch (Exception ex) { - assertEquals(stepExecution.getRollbackCount(), new Integer(1)); - } - - } - - public void testExitCodeDefaultClassification() throws Exception { - - ItemReader itemReader = new AbstractItemReader() { - - public Object read() throws Exception { - int counter = 0; - counter++; - - if (counter == 1) { - throw new RuntimeException(); - } - - return ExitStatus.CONTINUABLE; - } - - }; - - itemOrientedStep.setItemHandler(new SimpleItemHandler(itemReader, itemWriter)); - JobExecution jobExecutionContext = new JobExecution(jobInstance); - StepExecution stepExecution = new StepExecution(itemOrientedStep, jobExecutionContext); - - try { - itemOrientedStep.execute(stepExecution); - } - catch (Exception ex) { - ExitStatus status = stepExecution.getExitStatus(); - assertFalse(status.isContinuable()); - } - } - - /* - * make sure a job that has never been executed before, but does have - * saveExecutionAttributes = true, doesn't have restoreFrom called on it. - */ - public void testNonRestartedJob() throws Exception { - MockRestartableItemReader tasklet = new MockRestartableItemReader(); - itemOrientedStep.setItemHandler(new SimpleItemHandler(tasklet, itemWriter)); - itemOrientedStep.registerStream(tasklet); - JobExecution jobExecutionContext = new JobExecution(jobInstance); - StepExecution stepExecution = new StepExecution(itemOrientedStep, jobExecutionContext); - - itemOrientedStep.execute(stepExecution); - - assertFalse(tasklet.isRestoreFromCalled()); - assertTrue(tasklet.isGetExecutionAttributesCalled()); - } - - public void testSuccessfulExecutionWithExecutionContext() throws Exception { - final JobExecution jobExecution = new JobExecution(jobInstance); - final StepExecution stepExecution = new StepExecution(itemOrientedStep, jobExecution); - itemOrientedStep.setJobRepository(new JobRepositorySupport() { - public void saveOrUpdateExecutionContext(StepExecution stepExecution) { - list.add(stepExecution); - } - }); - itemOrientedStep.execute(stepExecution); - assertEquals(1, list.size()); - } - - public void testSuccessfulExecutionWithFailureOnSaveOfExecutionContext() throws Exception { - final JobExecution jobExecution = new JobExecution(jobInstance); - final StepExecution stepExecution = new StepExecution(itemOrientedStep, jobExecution); - itemOrientedStep.setJobRepository(new JobRepositorySupport() { - public void saveOrUpdateExecutionContext(StepExecution stepExecution) { - throw new RuntimeException("foo"); - } - }); - try { - itemOrientedStep.execute(stepExecution); - fail("Expected BatchCriticalException"); - } - catch (InfrastructureException e) { - assertEquals("foo", e.getCause().getMessage()); - } - assertEquals(BatchStatus.UNKNOWN, stepExecution.getStatus()); - } - - /* - * make sure a job that has been executed before, and is therefore being - * restarted, is restored. - */ - // public void testRestartedJob() throws Exception { - // String step = "stepName"; - // // step.setStepExecutionCount(1); - // MockRestartableItemReader tasklet = new MockRestartableItemReader(); - // stepExecutor.setItemReader(tasklet); - // stepConfiguration.setSaveExecutionContext(true); - // JobExecution jobExecution = new JobExecution(jobInstance); - // StepExecution stepExecution = new StepExecution(step, jobExecution); - // - // stepExecution - // .setExecutionContext(new - // ExecutionContext(PropertiesConverter.stringToProperties("foo=bar"))); - // // step.setLastExecution(stepExecution); - // stepExecutor.execute(stepExecution); - // - // assertTrue(tasklet.isRestoreFromCalled()); - // assertTrue(tasklet.isRestoreFromCalledWithSomeContext()); - // assertTrue(tasklet.isGetExecutionAttributesCalled()); - // } - /* - * Test that a job that is being restarted, but has saveExecutionAttributes - * set to false, doesn't have restore or getExecutionAttributes called on - * it. - */ - public void testNoSaveExecutionAttributesRestartableJob() { - MockRestartableItemReader tasklet = new MockRestartableItemReader(); - itemOrientedStep.setItemHandler(new SimpleItemHandler(tasklet, itemWriter)); - JobExecution jobExecutionContext = new JobExecution(jobInstance); - StepExecution stepExecution = new StepExecution(itemOrientedStep, jobExecutionContext); - - try { - itemOrientedStep.execute(stepExecution); - } - catch (Throwable t) { - fail(); - } - - assertFalse(tasklet.isRestoreFromCalled()); - } - - /* - * Even though the job is restarted, and saveExecutionAttributes is true, - * nothing will be restored because the Tasklet does not implement - * Restartable. - */ - public void testRestartJobOnNonRestartableTasklet() throws Exception { - itemOrientedStep.setItemHandler(new SimpleItemHandler(new AbstractItemReader() { - public Object read() throws Exception { - return "foo"; - } - }, itemWriter)); - JobExecution jobExecution = new JobExecution(jobInstance); - StepExecution stepExecution = new StepExecution(itemOrientedStep, jobExecution); - - itemOrientedStep.execute(stepExecution); - } - - public void testStreamManager() throws Exception { - MockRestartableItemReader reader = new MockRestartableItemReader() { - public Object read() throws Exception { - return "foo"; - } - public void update(ExecutionContext executionContext) { - // TODO Auto-generated method stub - executionContext.putString("foo", "bar"); - } - }; - itemOrientedStep.setItemHandler(new SimpleItemHandler(reader, itemWriter)); - itemOrientedStep.registerStream(reader); - JobExecution jobExecution = new JobExecution(jobInstance); - StepExecution stepExecution = new StepExecution(itemOrientedStep, jobExecution); - - assertEquals(false, stepExecution.getExecutionContext().containsKey("foo")); - - itemOrientedStep.execute(stepExecution); - - // At least once in that process the statistics service was asked for - // statistics... - assertEquals("bar", stepExecution.getExecutionContext().getString("foo")); - } - - public void testDirectlyInjectedItemStream() throws Exception { - itemOrientedStep.setStreams(new ItemStream[] {new ItemStreamSupport() { - public void update(ExecutionContext executionContext) { - executionContext.putString("foo", "bar"); - } - }}); - JobExecution jobExecution = new JobExecution(jobInstance); - StepExecution stepExecution = new StepExecution(itemOrientedStep, jobExecution); - - assertEquals(false, stepExecution.getExecutionContext().containsKey("foo")); - - itemOrientedStep.execute(stepExecution); - - assertEquals("bar", stepExecution.getExecutionContext().getString("foo")); - } - - public void testDirectlyInjectedListener() throws Exception { - itemOrientedStep.registerStepListener(new StepListenerSupport() { - public void beforeStep(StepExecution stepExecution) { - list.add("foo"); - } - public ExitStatus afterStep(StepExecution stepExecution) { - list.add("bar"); - return null; - } - }); - JobExecution jobExecution = new JobExecution(jobInstance); - StepExecution stepExecution = new StepExecution(itemOrientedStep, jobExecution); - itemOrientedStep.execute(stepExecution); - assertEquals(2, list.size()); - } - - public void testListenerCalledBeforeStreamOpened() throws Exception { - MockRestartableItemReader reader = new MockRestartableItemReader() { - public void beforeStep(StepExecution stepExecution) { - list.add("foo"); - } - public void open(ExecutionContext executionContext) throws StreamException { - assertEquals(1, list.size()); - } - }; - itemOrientedStep.setStreams(new ItemStream[] {reader}); - itemOrientedStep.registerStepListener(reader); - StepExecution stepExecution = new StepExecution(itemOrientedStep, new JobExecution(jobInstance)); - itemOrientedStep.execute(stepExecution); - assertEquals(1, list.size()); - } - - public void testAfterStep() throws Exception{ - - final ExitStatus customStatus = new ExitStatus(false, "custom code"); - - itemOrientedStep.setStepListeners(new StepListener[] {new StepListenerSupport() { - public ExitStatus afterStep(StepExecution stepExecution) { - list.add("afterStepCalled"); - return customStatus; - } - }}); - - RepeatTemplate stepTemplate = new RepeatTemplate(); - stepTemplate.setCompletionPolicy(new SimpleCompletionPolicy(5)); - itemOrientedStep.setStepOperations(stepTemplate); - - JobExecution jobExecution = new JobExecution(jobInstance); - StepExecution stepExecution = new StepExecution(itemOrientedStep, jobExecution); - itemOrientedStep.execute(stepExecution); - assertEquals(1, list.size()); - ExitStatus returnedStatus = stepExecution.getExitStatus(); - assertEquals(customStatus.getExitCode(), returnedStatus.getExitCode()); - assertEquals(customStatus.getExitDescription(), returnedStatus.getExitDescription()); - } - - public void testDirectlyInjectedListenerOnError() throws Exception { - itemOrientedStep.registerStepListener(new StepListenerSupport() { - public ExitStatus onErrorInStep(StepExecution stepExecution, Throwable e) { - list.add(e); - return null; - } - }); - itemOrientedStep.setItemHandler(new SimpleItemHandler(new MockRestartableItemReader() { - public Object read() throws Exception { - throw new RuntimeException("FOO"); - } - }, itemWriter)); - JobExecution jobExecution = new JobExecution(jobInstance); - StepExecution stepExecution = new StepExecution(itemOrientedStep, jobExecution); - try { - itemOrientedStep.execute(stepExecution); - fail("Expected RuntimeException"); - } catch (RuntimeException e) { - assertEquals("FOO", e.getMessage()); - } - assertEquals(1, list.size()); - } - - public void testDirectlyInjectedStreamWhichIsAlsoReader() throws Exception { - MockRestartableItemReader reader = new MockRestartableItemReader() { - public Object read() throws Exception { - return "foo"; - } - public void update(ExecutionContext executionContext) { - // TODO Auto-generated method stub - executionContext.putString("foo", "bar"); - } - }; - itemOrientedStep.setItemHandler(new SimpleItemHandler(reader, itemWriter)); - itemOrientedStep.setStreams(new ItemStream[] {reader}); - JobExecution jobExecution = new JobExecution(jobInstance); - StepExecution stepExecution = new StepExecution(itemOrientedStep, jobExecution); - - assertEquals(false, stepExecution.getExecutionContext().containsKey("foo")); - - itemOrientedStep.execute(stepExecution); - - // At least once in that process the statistics service was asked for - // statistics... - assertEquals("bar", stepExecution.getExecutionContext().getString("foo")); - } - - public void testStatusForInterruptedException() { - - StepInterruptionPolicy interruptionPolicy = new StepInterruptionPolicy() { - - public void checkInterrupted(RepeatContext context) throws JobInterruptedException { - throw new JobInterruptedException(""); - } - }; - - itemOrientedStep.setInterruptionPolicy(interruptionPolicy); - - ItemReader itemReader = new AbstractItemReader() { - - public Object read() throws Exception { - int counter = 0; - counter++; - - if (counter == 1) { - throw new RuntimeException(); - } - - return ExitStatus.CONTINUABLE; - } - - }; - - itemOrientedStep.setItemHandler(new SimpleItemHandler(itemReader, itemWriter)); - - JobExecution jobExecutionContext = new JobExecution(jobInstance); - StepExecution stepExecution = new StepExecution(itemOrientedStep, jobExecutionContext); - - stepExecution.setExecutionContext(new ExecutionContext(PropertiesConverter.stringToProperties("foo=bar"))); - // step.setLastExecution(stepExecution); - - try { - itemOrientedStep.execute(stepExecution); - fail("Expected StepInterruptedException"); - } - catch (JobInterruptedException ex) { - assertEquals(BatchStatus.STOPPED, stepExecution.getStatus()); - String msg = stepExecution.getExitStatus().getExitDescription(); - assertTrue("Message does not contain JobInterruptedException: " + msg, msg - .contains("JobInterruptedException")); - } - } - - public void testStatusForNormalFailure() throws Exception { - - ItemReader itemReader = new AbstractItemReader() { - public Object read() throws Exception { - // Trigger a rollback - throw new RuntimeException("Foo"); - } - }; - itemOrientedStep.setItemHandler(new SimpleItemHandler(itemReader, itemWriter)); - - JobExecution jobExecutionContext = new JobExecution(jobInstance); - StepExecution stepExecution = new StepExecution(itemOrientedStep, jobExecutionContext); - - stepExecution.setExecutionContext(new ExecutionContext(PropertiesConverter.stringToProperties("foo=bar"))); - // step.setLastExecution(stepExecution); - - try { - itemOrientedStep.execute(stepExecution); - fail("Expected RuntimeException"); - } - catch (RuntimeException ex) { - assertEquals(BatchStatus.FAILED, stepExecution.getStatus()); - // The original rollback was caused by this one: - assertEquals("Foo", ex.getMessage()); - } - } - - public void testStatusForResetFailedException() throws Exception { - - ItemReader itemReader = new AbstractItemReader() { - public Object read() throws Exception { - // Trigger a rollback - throw new RuntimeException("Foo"); - } - }; - itemOrientedStep.setItemHandler(new SimpleItemHandler(itemReader, itemWriter)); - itemOrientedStep.setTransactionManager(new ResourcelessTransactionManager() { - protected void doRollback(DefaultTransactionStatus status) throws TransactionException { - // Simulate failure on rollback when stream resets - throw new ResetFailedException("Bar"); - } - }); - - JobExecution jobExecutionContext = new JobExecution(jobInstance); - StepExecution stepExecution = new StepExecution(itemOrientedStep, jobExecutionContext); - - stepExecution.setExecutionContext(new ExecutionContext(PropertiesConverter.stringToProperties("foo=bar"))); - // step.setLastExecution(stepExecution); - - try { - itemOrientedStep.execute(stepExecution); - fail("Expected BatchCriticalException"); - } - catch (InfrastructureException ex) { - assertEquals(BatchStatus.UNKNOWN, stepExecution.getStatus()); - String msg = stepExecution.getExitStatus().getExitDescription(); - assertTrue("Message does not contain ResetFailedException: " + msg, msg.contains("ResetFailedException")); - // The original rollback was caused by this one: - assertEquals("Bar", ex.getCause().getMessage()); - } - } - - public void testStatusForCommitFailedException() throws Exception { - - itemOrientedStep.setTransactionManager(new ResourcelessTransactionManager() { - protected void doCommit(DefaultTransactionStatus status) throws TransactionException { - // Simulate failure on rollback when stream resets - throw new RuntimeException("Bar"); - } - }); - - JobExecution jobExecutionContext = new JobExecution(jobInstance); - StepExecution stepExecution = new StepExecution(itemOrientedStep, jobExecutionContext); - - stepExecution.setExecutionContext(new ExecutionContext(PropertiesConverter.stringToProperties("foo=bar"))); - // step.setLastExecution(stepExecution); - - try { - itemOrientedStep.execute(stepExecution); - fail("Expected BatchCriticalException"); - } - catch (InfrastructureException ex) { - assertEquals(BatchStatus.UNKNOWN, stepExecution.getStatus()); - String msg = stepExecution.getExitStatus().getExitDescription(); - assertEquals("", msg); - msg = ex.getMessage(); - assertTrue("Message does not contain 'saving': " + msg, msg.contains("saving")); - // The original rollback was caused by this one: - assertEquals("Bar", ex.getCause().getMessage()); - } - } - - public void testStatusForFinalUpdateFailedException() throws Exception { - - itemOrientedStep.setJobRepository(new JobRepositorySupport() { - public void saveOrUpdate(StepExecution stepExecution) { - if (stepExecution.getEndTime()!=null) { - throw new RuntimeException("Bar"); - } - super.saveOrUpdate(stepExecution); - } - }); - - JobExecution jobExecutionContext = new JobExecution(jobInstance); - StepExecution stepExecution = new StepExecution(itemOrientedStep, jobExecutionContext); - - try { - itemOrientedStep.execute(stepExecution); - fail("Expected RuntimeException"); - } - catch (RuntimeException ex) { - // The job actually completeed, but teh streams couldn't be closed. - assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); - String msg = stepExecution.getExitStatus().getExitDescription(); - assertEquals("", msg); - msg = ex.getMessage(); - assertTrue("Message does not contain 'final': " + msg, msg.contains("final")); - // The original rollback was caused by this one: - assertEquals("Bar", ex.getCause().getMessage()); - } - } - - public void testStatusForCloseFailedException() throws Exception { - - MockRestartableItemReader itemReader = new MockRestartableItemReader() { - public void close(ExecutionContext executionContext) throws StreamException { - super.close(executionContext); - // Simulate failure on rollback when stream resets - throw new RuntimeException("Bar"); - } - }; - itemOrientedStep.setItemHandler(new SimpleItemHandler(itemReader, itemWriter)); - itemOrientedStep.registerStream(itemReader); - - JobExecution jobExecutionContext = new JobExecution(jobInstance); - StepExecution stepExecution = new StepExecution(itemOrientedStep, jobExecutionContext); - - stepExecution.setExecutionContext(new ExecutionContext(PropertiesConverter.stringToProperties("foo=bar"))); - // step.setLastExecution(stepExecution); - - try { - itemOrientedStep.execute(stepExecution); - fail("Expected InfrastructureException"); - } - catch (InfrastructureException ex) { - // The job actually completeed, but the streams couldn't be closed. - assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); - String msg = stepExecution.getExitStatus().getExitDescription(); - assertEquals("", msg); - msg = ex.getMessage(); - assertTrue("Message does not contain 'close': " + msg, msg.contains("close")); - // The original rollback was caused by this one: - assertEquals("Bar", ex.getCause().getMessage()); - } - } - - private class MockRestartableItemReader extends ItemStreamSupport implements ItemReader, StepListener { - - private boolean getExecutionAttributesCalled = false; - - private boolean restoreFromCalled = false; - - private boolean restoreFromCalledWithSomeContext = false; - - public Object read() throws Exception { - return "item"; - } - - public boolean isRestoreFromCalledWithSomeContext() { - return restoreFromCalledWithSomeContext; - } - - public void update(ExecutionContext executionContext) { - getExecutionAttributesCalled = true; - executionContext.putString("spam", "bucket"); - } - - public boolean isGetExecutionAttributesCalled() { - return getExecutionAttributesCalled; - } - - public boolean isRestoreFromCalled() { - return restoreFromCalled; - } - - public void mark() throws MarkFailedException { - } - - public void reset() throws ResetFailedException { - } - - public ExitStatus afterStep(StepExecution stepExecution) { - return null; - } - - public void beforeStep(StepExecution stepExecution) { - } - - public ExitStatus onErrorInStep(StepExecution stepExecution, Throwable e) { - return null; - } - - } - -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.batch.execution.step; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import junit.framework.TestCase; + +import org.springframework.batch.core.domain.BatchStatus; +import org.springframework.batch.core.domain.JobExecution; +import org.springframework.batch.core.domain.JobInstance; +import org.springframework.batch.core.domain.JobInterruptedException; +import org.springframework.batch.core.domain.JobParameters; +import org.springframework.batch.core.domain.StepContribution; +import org.springframework.batch.core.domain.StepExecution; +import org.springframework.batch.core.domain.StepListener; +import org.springframework.batch.core.listener.StepListenerSupport; +import org.springframework.batch.execution.job.JobSupport; +import org.springframework.batch.execution.repository.SimpleJobRepository; +import org.springframework.batch.execution.repository.dao.MapJobExecutionDao; +import org.springframework.batch.execution.repository.dao.MapJobInstanceDao; +import org.springframework.batch.execution.repository.dao.MapStepExecutionDao; +import org.springframework.batch.execution.step.support.JobRepositorySupport; +import org.springframework.batch.execution.step.support.SimpleItemHandler; +import org.springframework.batch.execution.step.support.StepInterruptionPolicy; +import org.springframework.batch.io.exception.InfrastructureException; +import org.springframework.batch.item.ExecutionContext; +import org.springframework.batch.item.ItemReader; +import org.springframework.batch.item.ItemStream; +import org.springframework.batch.item.ItemWriter; +import org.springframework.batch.item.exception.MarkFailedException; +import org.springframework.batch.item.exception.ResetFailedException; +import org.springframework.batch.item.exception.StreamException; +import org.springframework.batch.item.reader.AbstractItemReader; +import org.springframework.batch.item.reader.ListItemReader; +import org.springframework.batch.item.stream.ItemStreamSupport; +import org.springframework.batch.item.writer.AbstractItemWriter; +import org.springframework.batch.repeat.ExitStatus; +import org.springframework.batch.repeat.RepeatContext; +import org.springframework.batch.repeat.policy.SimpleCompletionPolicy; +import org.springframework.batch.repeat.support.RepeatTemplate; +import org.springframework.batch.support.PropertiesConverter; +import org.springframework.batch.support.transaction.ResourcelessTransactionManager; +import org.springframework.transaction.TransactionException; +import org.springframework.transaction.support.DefaultTransactionStatus; + +public class ItemOrientedStepTests extends TestCase { + + ArrayList processed = new ArrayList(); + + private List list = new ArrayList(); + + ItemWriter itemWriter = new AbstractItemWriter() { + public void write(Object data) throws Exception { + processed.add((String) data); + } + }; + + private ItemOrientedStep itemOrientedStep; + + private RepeatTemplate template; + + private JobInstance jobInstance; + + private ResourcelessTransactionManager transactionManager; + + private ItemReader getReader(String[] args) { + return new ListItemReader(Arrays.asList(args)); + } + + private AbstractStep getStep(String[] strings) throws Exception { + ItemOrientedStep step = new ItemOrientedStep("stepName"); + step.setItemHandler(new SimpleItemHandler(getReader(strings), itemWriter)); + step.setJobRepository(new JobRepositorySupport()); + step.setTransactionManager(transactionManager); + return step; + } + + protected void setUp() throws Exception { + transactionManager = new ResourcelessTransactionManager(); + + itemOrientedStep = (ItemOrientedStep) getStep(new String[] { "foo", "bar", "spam" }); + template = new RepeatTemplate(); + template.setCompletionPolicy(new SimpleCompletionPolicy(1)); + itemOrientedStep.setStepOperations(template); + // Only process one item: + template = new RepeatTemplate(); + template.setCompletionPolicy(new SimpleCompletionPolicy(1)); + itemOrientedStep.setChunkOperations(template); + + jobInstance = new JobInstance(new Long(0), new JobParameters(), new JobSupport("FOO")); + + itemOrientedStep.setTransactionManager(transactionManager); + + } + + public void testStepExecutor() throws Exception { + + JobExecution jobExecutionContext = new JobExecution(jobInstance); + StepExecution stepExecution = new StepExecution(itemOrientedStep, jobExecutionContext); + + itemOrientedStep.execute(stepExecution); + assertEquals(1, processed.size()); + assertEquals(1, stepExecution.getTaskCount().intValue()); + } + + public void testChunkExecutor() throws Exception { + + template = new RepeatTemplate(); + + // Only process one item: + template.setCompletionPolicy(new SimpleCompletionPolicy(1)); + itemOrientedStep.setChunkOperations(template); + + JobExecution jobExecution = new JobExecution(jobInstance); + + StepExecution stepExecution = new StepExecution(itemOrientedStep, jobExecution); + StepContribution contribution = stepExecution.createStepContribution(); + itemOrientedStep.processChunk(contribution); + assertEquals(1, processed.size()); + assertEquals(0, stepExecution.getTaskCount().intValue()); + assertEquals(1, contribution.getTaskCount()); + + } + + public void testRepository() throws Exception { + + SimpleJobRepository repository = new SimpleJobRepository(new MapJobInstanceDao(), new MapJobExecutionDao(), new MapStepExecutionDao()); + itemOrientedStep.setJobRepository(repository); + + JobExecution jobExecution = repository.createJobExecution(jobInstance.getJob(), jobInstance.getJobParameters()); + StepExecution stepExecution = new StepExecution(itemOrientedStep, jobExecution); + + itemOrientedStep.execute(stepExecution); + assertEquals(1, processed.size()); + } + + public void testIncrementRollbackCount() { + + ItemReader itemReader = new AbstractItemReader() { + + public Object read() throws Exception { + int counter = 0; + counter++; + + if (counter == 1) { + throw new RuntimeException(); + } + + return ExitStatus.CONTINUABLE; + } + + }; + + itemOrientedStep.setItemHandler(new SimpleItemHandler(itemReader, itemWriter)); + JobExecution jobExecutionContext = new JobExecution(jobInstance); + StepExecution stepExecution = new StepExecution(itemOrientedStep, jobExecutionContext); + + try { + itemOrientedStep.execute(stepExecution); + } + catch (Exception ex) { + assertEquals(stepExecution.getRollbackCount(), new Integer(1)); + } + + } + + public void testExitCodeDefaultClassification() throws Exception { + + ItemReader itemReader = new AbstractItemReader() { + + public Object read() throws Exception { + int counter = 0; + counter++; + + if (counter == 1) { + throw new RuntimeException(); + } + + return ExitStatus.CONTINUABLE; + } + + }; + + itemOrientedStep.setItemHandler(new SimpleItemHandler(itemReader, itemWriter)); + JobExecution jobExecutionContext = new JobExecution(jobInstance); + StepExecution stepExecution = new StepExecution(itemOrientedStep, jobExecutionContext); + + try { + itemOrientedStep.execute(stepExecution); + } + catch (Exception ex) { + ExitStatus status = stepExecution.getExitStatus(); + assertFalse(status.isContinuable()); + } + } + + /* + * make sure a job that has never been executed before, but does have + * saveExecutionAttributes = true, doesn't have restoreFrom called on it. + */ + public void testNonRestartedJob() throws Exception { + MockRestartableItemReader tasklet = new MockRestartableItemReader(); + itemOrientedStep.setItemHandler(new SimpleItemHandler(tasklet, itemWriter)); + itemOrientedStep.registerStream(tasklet); + JobExecution jobExecutionContext = new JobExecution(jobInstance); + StepExecution stepExecution = new StepExecution(itemOrientedStep, jobExecutionContext); + + itemOrientedStep.execute(stepExecution); + + assertFalse(tasklet.isRestoreFromCalled()); + assertTrue(tasklet.isGetExecutionAttributesCalled()); + } + + public void testSuccessfulExecutionWithExecutionContext() throws Exception { + final JobExecution jobExecution = new JobExecution(jobInstance); + final StepExecution stepExecution = new StepExecution(itemOrientedStep, jobExecution); + itemOrientedStep.setJobRepository(new JobRepositorySupport() { + public void saveOrUpdateExecutionContext(StepExecution stepExecution) { + list.add(stepExecution); + } + }); + itemOrientedStep.execute(stepExecution); + assertEquals(1, list.size()); + } + + public void testSuccessfulExecutionWithFailureOnSaveOfExecutionContext() throws Exception { + final JobExecution jobExecution = new JobExecution(jobInstance); + final StepExecution stepExecution = new StepExecution(itemOrientedStep, jobExecution); + itemOrientedStep.setJobRepository(new JobRepositorySupport() { + public void saveOrUpdateExecutionContext(StepExecution stepExecution) { + throw new RuntimeException("foo"); + } + }); + try { + itemOrientedStep.execute(stepExecution); + fail("Expected BatchCriticalException"); + } + catch (InfrastructureException e) { + assertEquals("foo", e.getCause().getMessage()); + } + assertEquals(BatchStatus.UNKNOWN, stepExecution.getStatus()); + } + + /* + * make sure a job that has been executed before, and is therefore being + * restarted, is restored. + */ + // public void testRestartedJob() throws Exception { + // String step = "stepName"; + // // step.setStepExecutionCount(1); + // MockRestartableItemReader tasklet = new MockRestartableItemReader(); + // stepExecutor.setItemReader(tasklet); + // stepConfiguration.setSaveExecutionContext(true); + // JobExecution jobExecution = new JobExecution(jobInstance); + // StepExecution stepExecution = new StepExecution(step, jobExecution); + // + // stepExecution + // .setExecutionContext(new + // ExecutionContext(PropertiesConverter.stringToProperties("foo=bar"))); + // // step.setLastExecution(stepExecution); + // stepExecutor.execute(stepExecution); + // + // assertTrue(tasklet.isRestoreFromCalled()); + // assertTrue(tasklet.isRestoreFromCalledWithSomeContext()); + // assertTrue(tasklet.isGetExecutionAttributesCalled()); + // } + /* + * Test that a job that is being restarted, but has saveExecutionAttributes + * set to false, doesn't have restore or getExecutionAttributes called on + * it. + */ + public void testNoSaveExecutionAttributesRestartableJob() { + MockRestartableItemReader tasklet = new MockRestartableItemReader(); + itemOrientedStep.setItemHandler(new SimpleItemHandler(tasklet, itemWriter)); + JobExecution jobExecutionContext = new JobExecution(jobInstance); + StepExecution stepExecution = new StepExecution(itemOrientedStep, jobExecutionContext); + + try { + itemOrientedStep.execute(stepExecution); + } + catch (Throwable t) { + fail(); + } + + assertFalse(tasklet.isRestoreFromCalled()); + } + + /* + * Even though the job is restarted, and saveExecutionAttributes is true, + * nothing will be restored because the Tasklet does not implement + * Restartable. + */ + public void testRestartJobOnNonRestartableTasklet() throws Exception { + itemOrientedStep.setItemHandler(new SimpleItemHandler(new AbstractItemReader() { + public Object read() throws Exception { + return "foo"; + } + }, itemWriter)); + JobExecution jobExecution = new JobExecution(jobInstance); + StepExecution stepExecution = new StepExecution(itemOrientedStep, jobExecution); + + itemOrientedStep.execute(stepExecution); + } + + public void testStreamManager() throws Exception { + MockRestartableItemReader reader = new MockRestartableItemReader() { + public Object read() throws Exception { + return "foo"; + } + public void update(ExecutionContext executionContext) { + // TODO Auto-generated method stub + executionContext.putString("foo", "bar"); + } + }; + itemOrientedStep.setItemHandler(new SimpleItemHandler(reader, itemWriter)); + itemOrientedStep.registerStream(reader); + JobExecution jobExecution = new JobExecution(jobInstance); + StepExecution stepExecution = new StepExecution(itemOrientedStep, jobExecution); + + assertEquals(false, stepExecution.getExecutionContext().containsKey("foo")); + + itemOrientedStep.execute(stepExecution); + + // At least once in that process the statistics service was asked for + // statistics... + assertEquals("bar", stepExecution.getExecutionContext().getString("foo")); + } + + public void testDirectlyInjectedItemStream() throws Exception { + itemOrientedStep.setStreams(new ItemStream[] {new ItemStreamSupport() { + public void update(ExecutionContext executionContext) { + executionContext.putString("foo", "bar"); + } + }}); + JobExecution jobExecution = new JobExecution(jobInstance); + StepExecution stepExecution = new StepExecution(itemOrientedStep, jobExecution); + + assertEquals(false, stepExecution.getExecutionContext().containsKey("foo")); + + itemOrientedStep.execute(stepExecution); + + assertEquals("bar", stepExecution.getExecutionContext().getString("foo")); + } + + public void testDirectlyInjectedListener() throws Exception { + itemOrientedStep.registerStepListener(new StepListenerSupport() { + public void beforeStep(StepExecution stepExecution) { + list.add("foo"); + } + public ExitStatus afterStep(StepExecution stepExecution) { + list.add("bar"); + return null; + } + }); + JobExecution jobExecution = new JobExecution(jobInstance); + StepExecution stepExecution = new StepExecution(itemOrientedStep, jobExecution); + itemOrientedStep.execute(stepExecution); + assertEquals(2, list.size()); + } + + public void testListenerCalledBeforeStreamOpened() throws Exception { + MockRestartableItemReader reader = new MockRestartableItemReader() { + public void beforeStep(StepExecution stepExecution) { + list.add("foo"); + } + public void open(ExecutionContext executionContext) throws StreamException { + assertEquals(1, list.size()); + } + }; + itemOrientedStep.setStreams(new ItemStream[] {reader}); + itemOrientedStep.registerStepListener(reader); + StepExecution stepExecution = new StepExecution(itemOrientedStep, new JobExecution(jobInstance)); + itemOrientedStep.execute(stepExecution); + assertEquals(1, list.size()); + } + + public void testAfterStep() throws Exception{ + + final ExitStatus customStatus = new ExitStatus(false, "custom code"); + + itemOrientedStep.setStepListeners(new StepListener[] {new StepListenerSupport() { + public ExitStatus afterStep(StepExecution stepExecution) { + list.add("afterStepCalled"); + return customStatus; + } + }}); + + RepeatTemplate stepTemplate = new RepeatTemplate(); + stepTemplate.setCompletionPolicy(new SimpleCompletionPolicy(5)); + itemOrientedStep.setStepOperations(stepTemplate); + + JobExecution jobExecution = new JobExecution(jobInstance); + StepExecution stepExecution = new StepExecution(itemOrientedStep, jobExecution); + itemOrientedStep.execute(stepExecution); + assertEquals(1, list.size()); + ExitStatus returnedStatus = stepExecution.getExitStatus(); + assertEquals(customStatus.getExitCode(), returnedStatus.getExitCode()); + assertEquals(customStatus.getExitDescription(), returnedStatus.getExitDescription()); + } + + public void testDirectlyInjectedListenerOnError() throws Exception { + itemOrientedStep.registerStepListener(new StepListenerSupport() { + public ExitStatus onErrorInStep(StepExecution stepExecution, Throwable e) { + list.add(e); + return null; + } + }); + itemOrientedStep.setItemHandler(new SimpleItemHandler(new MockRestartableItemReader() { + public Object read() throws Exception { + throw new RuntimeException("FOO"); + } + }, itemWriter)); + JobExecution jobExecution = new JobExecution(jobInstance); + StepExecution stepExecution = new StepExecution(itemOrientedStep, jobExecution); + try { + itemOrientedStep.execute(stepExecution); + fail("Expected RuntimeException"); + } catch (RuntimeException e) { + assertEquals("FOO", e.getMessage()); + } + assertEquals(1, list.size()); + } + + public void testDirectlyInjectedStreamWhichIsAlsoReader() throws Exception { + MockRestartableItemReader reader = new MockRestartableItemReader() { + public Object read() throws Exception { + return "foo"; + } + public void update(ExecutionContext executionContext) { + // TODO Auto-generated method stub + executionContext.putString("foo", "bar"); + } + }; + itemOrientedStep.setItemHandler(new SimpleItemHandler(reader, itemWriter)); + itemOrientedStep.setStreams(new ItemStream[] {reader}); + JobExecution jobExecution = new JobExecution(jobInstance); + StepExecution stepExecution = new StepExecution(itemOrientedStep, jobExecution); + + assertEquals(false, stepExecution.getExecutionContext().containsKey("foo")); + + itemOrientedStep.execute(stepExecution); + + // At least once in that process the statistics service was asked for + // statistics... + assertEquals("bar", stepExecution.getExecutionContext().getString("foo")); + } + + public void testStatusForInterruptedException() { + + StepInterruptionPolicy interruptionPolicy = new StepInterruptionPolicy() { + + public void checkInterrupted(RepeatContext context) throws JobInterruptedException { + throw new JobInterruptedException(""); + } + }; + + itemOrientedStep.setInterruptionPolicy(interruptionPolicy); + + ItemReader itemReader = new AbstractItemReader() { + + public Object read() throws Exception { + int counter = 0; + counter++; + + if (counter == 1) { + throw new RuntimeException(); + } + + return ExitStatus.CONTINUABLE; + } + + }; + + itemOrientedStep.setItemHandler(new SimpleItemHandler(itemReader, itemWriter)); + + JobExecution jobExecutionContext = new JobExecution(jobInstance); + StepExecution stepExecution = new StepExecution(itemOrientedStep, jobExecutionContext); + + stepExecution.setExecutionContext(new ExecutionContext(PropertiesConverter.stringToProperties("foo=bar"))); + // step.setLastExecution(stepExecution); + + try { + itemOrientedStep.execute(stepExecution); + fail("Expected StepInterruptedException"); + } + catch (JobInterruptedException ex) { + assertEquals(BatchStatus.STOPPED, stepExecution.getStatus()); + String msg = stepExecution.getExitStatus().getExitDescription(); + assertTrue("Message does not contain JobInterruptedException: " + msg, msg + .contains("JobInterruptedException")); + } + } + + public void testStatusForNormalFailure() throws Exception { + + ItemReader itemReader = new AbstractItemReader() { + public Object read() throws Exception { + // Trigger a rollback + throw new RuntimeException("Foo"); + } + }; + itemOrientedStep.setItemHandler(new SimpleItemHandler(itemReader, itemWriter)); + + JobExecution jobExecutionContext = new JobExecution(jobInstance); + StepExecution stepExecution = new StepExecution(itemOrientedStep, jobExecutionContext); + + stepExecution.setExecutionContext(new ExecutionContext(PropertiesConverter.stringToProperties("foo=bar"))); + // step.setLastExecution(stepExecution); + + try { + itemOrientedStep.execute(stepExecution); + fail("Expected RuntimeException"); + } + catch (RuntimeException ex) { + assertEquals(BatchStatus.FAILED, stepExecution.getStatus()); + // The original rollback was caused by this one: + assertEquals("Foo", ex.getMessage()); + } + } + + public void testStatusForResetFailedException() throws Exception { + + ItemReader itemReader = new AbstractItemReader() { + public Object read() throws Exception { + // Trigger a rollback + throw new RuntimeException("Foo"); + } + }; + itemOrientedStep.setItemHandler(new SimpleItemHandler(itemReader, itemWriter)); + itemOrientedStep.setTransactionManager(new ResourcelessTransactionManager() { + protected void doRollback(DefaultTransactionStatus status) throws TransactionException { + // Simulate failure on rollback when stream resets + throw new ResetFailedException("Bar"); + } + }); + + JobExecution jobExecutionContext = new JobExecution(jobInstance); + StepExecution stepExecution = new StepExecution(itemOrientedStep, jobExecutionContext); + + stepExecution.setExecutionContext(new ExecutionContext(PropertiesConverter.stringToProperties("foo=bar"))); + // step.setLastExecution(stepExecution); + + try { + itemOrientedStep.execute(stepExecution); + fail("Expected BatchCriticalException"); + } + catch (InfrastructureException ex) { + assertEquals(BatchStatus.UNKNOWN, stepExecution.getStatus()); + String msg = stepExecution.getExitStatus().getExitDescription(); + assertTrue("Message does not contain ResetFailedException: " + msg, msg.contains("ResetFailedException")); + // The original rollback was caused by this one: + assertEquals("Bar", ex.getCause().getMessage()); + } + } + + public void testStatusForCommitFailedException() throws Exception { + + itemOrientedStep.setTransactionManager(new ResourcelessTransactionManager() { + protected void doCommit(DefaultTransactionStatus status) throws TransactionException { + // Simulate failure on rollback when stream resets + throw new RuntimeException("Bar"); + } + }); + + JobExecution jobExecutionContext = new JobExecution(jobInstance); + StepExecution stepExecution = new StepExecution(itemOrientedStep, jobExecutionContext); + + stepExecution.setExecutionContext(new ExecutionContext(PropertiesConverter.stringToProperties("foo=bar"))); + // step.setLastExecution(stepExecution); + + try { + itemOrientedStep.execute(stepExecution); + fail("Expected BatchCriticalException"); + } + catch (InfrastructureException ex) { + assertEquals(BatchStatus.UNKNOWN, stepExecution.getStatus()); + String msg = stepExecution.getExitStatus().getExitDescription(); + assertEquals("", msg); + msg = ex.getMessage(); + assertTrue("Message does not contain 'saving': " + msg, msg.contains("saving")); + // The original rollback was caused by this one: + assertEquals("Bar", ex.getCause().getMessage()); + } + } + + public void testStatusForFinalUpdateFailedException() throws Exception { + + itemOrientedStep.setJobRepository(new JobRepositorySupport() { + public void saveOrUpdate(StepExecution stepExecution) { + if (stepExecution.getEndTime()!=null) { + throw new RuntimeException("Bar"); + } + super.saveOrUpdate(stepExecution); + } + }); + + JobExecution jobExecutionContext = new JobExecution(jobInstance); + StepExecution stepExecution = new StepExecution(itemOrientedStep, jobExecutionContext); + + try { + itemOrientedStep.execute(stepExecution); + fail("Expected RuntimeException"); + } + catch (RuntimeException ex) { + // The job actually completeed, but teh streams couldn't be closed. + assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); + String msg = stepExecution.getExitStatus().getExitDescription(); + assertEquals("", msg); + msg = ex.getMessage(); + assertTrue("Message does not contain 'final': " + msg, msg.contains("final")); + // The original rollback was caused by this one: + assertEquals("Bar", ex.getCause().getMessage()); + } + } + + public void testStatusForCloseFailedException() throws Exception { + + MockRestartableItemReader itemReader = new MockRestartableItemReader() { + public void close(ExecutionContext executionContext) throws StreamException { + super.close(executionContext); + // Simulate failure on rollback when stream resets + throw new RuntimeException("Bar"); + } + }; + itemOrientedStep.setItemHandler(new SimpleItemHandler(itemReader, itemWriter)); + itemOrientedStep.registerStream(itemReader); + + JobExecution jobExecutionContext = new JobExecution(jobInstance); + StepExecution stepExecution = new StepExecution(itemOrientedStep, jobExecutionContext); + + stepExecution.setExecutionContext(new ExecutionContext(PropertiesConverter.stringToProperties("foo=bar"))); + // step.setLastExecution(stepExecution); + + try { + itemOrientedStep.execute(stepExecution); + fail("Expected InfrastructureException"); + } + catch (InfrastructureException ex) { + // The job actually completeed, but the streams couldn't be closed. + assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); + String msg = stepExecution.getExitStatus().getExitDescription(); + assertEquals("", msg); + msg = ex.getMessage(); + assertTrue("Message does not contain 'close': " + msg, msg.contains("close")); + // The original rollback was caused by this one: + assertEquals("Bar", ex.getCause().getMessage()); + } + } + + private class MockRestartableItemReader extends ItemStreamSupport implements ItemReader, StepListener { + + private boolean getExecutionAttributesCalled = false; + + private boolean restoreFromCalled = false; + + private boolean restoreFromCalledWithSomeContext = false; + + public Object read() throws Exception { + return "item"; + } + + public boolean isRestoreFromCalledWithSomeContext() { + return restoreFromCalledWithSomeContext; + } + + public void update(ExecutionContext executionContext) { + getExecutionAttributesCalled = true; + executionContext.putString("spam", "bucket"); + } + + public boolean isGetExecutionAttributesCalled() { + return getExecutionAttributesCalled; + } + + public boolean isRestoreFromCalled() { + return restoreFromCalled; + } + + public void mark() throws MarkFailedException { + } + + public void reset() throws ResetFailedException { + } + + public ExitStatus afterStep(StepExecution stepExecution) { + return null; + } + + public void beforeStep(StepExecution stepExecution) { + } + + public ExitStatus onErrorInStep(StepExecution stepExecution, Throwable e) { + return null; + } + + } + +} diff --git a/spring-batch-execution/src/test/java/org/springframework/batch/execution/step/StepSupport.java b/spring-batch-execution/src/test/java/org/springframework/batch/execution/step/StepSupport.java index bdccb4df2d..59486ee01e 100644 --- a/spring-batch-execution/src/test/java/org/springframework/batch/execution/step/StepSupport.java +++ b/spring-batch-execution/src/test/java/org/springframework/batch/execution/step/StepSupport.java @@ -1,117 +1,117 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.execution.step; - -import org.springframework.batch.core.domain.JobInterruptedException; -import org.springframework.batch.core.domain.Step; -import org.springframework.batch.core.domain.StepExecution; -import org.springframework.batch.io.exception.InfrastructureException; -import org.springframework.beans.factory.BeanNameAware; - -/** - * Basic no-op support implementation for use as base class for {@link Step}. Implements {@link BeanNameAware} so that - * if no name is provided explicitly it will be inferred from the bean definition in Spring configuration. - * - * @author Dave Syer - * - */ -public class StepSupport implements Step, BeanNameAware { - - private String name; - - private int startLimit = Integer.MAX_VALUE; - - private boolean allowStartIfComplete; - - /** - * Default constructor for {@link StepSupport}. - */ - public StepSupport() { - super(); - } - - /** - * @param string - */ - public StepSupport(String string) { - super(); - this.name = string; - } - - public String getName() { - return this.name; - } - - /** - * Set the name property if it is not already set. Because of the order of the callbacks in a Spring container the - * name property will be set first if it is present. Care is needed with bean definition inheritance - if a parent - * bean has a name, then its children need an explicit name as well, otherwise they will not be unique. - * - * @see org.springframework.beans.factory.BeanNameAware#setBeanName(java.lang.String) - */ - public void setBeanName(String name) { - if (this.name == null) { - this.name = name; - } - } - - /** - * Set the name property. Always overrides the default value if this object is a Spring bean. - * - * @see #setBeanName(java.lang.String) - */ - public void setName(String name) { - this.name = name; - } - - public int getStartLimit() { - return this.startLimit; - } - - /** - * Public setter for the startLimit. - * - * @param startLimit the startLimit to set - */ - public void setStartLimit(int startLimit) { - this.startLimit = startLimit; - } - - public boolean isAllowStartIfComplete() { - return this.allowStartIfComplete; - } - - /** - * Public setter for the shouldAllowStartIfComplete. - * - * @param allowStartIfComplete the shouldAllowStartIfComplete to set - */ - public void setAllowStartIfComplete(boolean allowStartIfComplete) { - this.allowStartIfComplete = allowStartIfComplete; - } - - /** - * Not supported but provided so that tests can easily create a step. - * - * @throws UnsupportedOperationException always - * - * @see org.springframework.batch.core.domain.Step#execute(org.springframework.batch.core.domain.StepExecution) - */ - public void execute(StepExecution stepExecution) throws JobInterruptedException, InfrastructureException { - throw new UnsupportedOperationException( - "Cannot process a StepExecution. Use a smarter subclass of StepSupport."); - } -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.execution.step; + +import org.springframework.batch.core.domain.JobInterruptedException; +import org.springframework.batch.core.domain.Step; +import org.springframework.batch.core.domain.StepExecution; +import org.springframework.batch.io.exception.InfrastructureException; +import org.springframework.beans.factory.BeanNameAware; + +/** + * Basic no-op support implementation for use as base class for {@link Step}. Implements {@link BeanNameAware} so that + * if no name is provided explicitly it will be inferred from the bean definition in Spring configuration. + * + * @author Dave Syer + * + */ +public class StepSupport implements Step, BeanNameAware { + + private String name; + + private int startLimit = Integer.MAX_VALUE; + + private boolean allowStartIfComplete; + + /** + * Default constructor for {@link StepSupport}. + */ + public StepSupport() { + super(); + } + + /** + * @param string + */ + public StepSupport(String string) { + super(); + this.name = string; + } + + public String getName() { + return this.name; + } + + /** + * Set the name property if it is not already set. Because of the order of the callbacks in a Spring container the + * name property will be set first if it is present. Care is needed with bean definition inheritance - if a parent + * bean has a name, then its children need an explicit name as well, otherwise they will not be unique. + * + * @see org.springframework.beans.factory.BeanNameAware#setBeanName(java.lang.String) + */ + public void setBeanName(String name) { + if (this.name == null) { + this.name = name; + } + } + + /** + * Set the name property. Always overrides the default value if this object is a Spring bean. + * + * @see #setBeanName(java.lang.String) + */ + public void setName(String name) { + this.name = name; + } + + public int getStartLimit() { + return this.startLimit; + } + + /** + * Public setter for the startLimit. + * + * @param startLimit the startLimit to set + */ + public void setStartLimit(int startLimit) { + this.startLimit = startLimit; + } + + public boolean isAllowStartIfComplete() { + return this.allowStartIfComplete; + } + + /** + * Public setter for the shouldAllowStartIfComplete. + * + * @param allowStartIfComplete the shouldAllowStartIfComplete to set + */ + public void setAllowStartIfComplete(boolean allowStartIfComplete) { + this.allowStartIfComplete = allowStartIfComplete; + } + + /** + * Not supported but provided so that tests can easily create a step. + * + * @throws UnsupportedOperationException always + * + * @see org.springframework.batch.core.domain.Step#execute(org.springframework.batch.core.domain.StepExecution) + */ + public void execute(StepExecution stepExecution) throws JobInterruptedException, InfrastructureException { + throw new UnsupportedOperationException( + "Cannot process a StepExecution. Use a smarter subclass of StepSupport."); + } +} diff --git a/spring-batch-execution/src/test/java/org/springframework/batch/execution/step/support/DefaultStepFactoryBeanTests.java b/spring-batch-execution/src/test/java/org/springframework/batch/execution/step/support/DefaultStepFactoryBeanTests.java index 6300d777ad..8e43124a1a 100644 --- a/spring-batch-execution/src/test/java/org/springframework/batch/execution/step/support/DefaultStepFactoryBeanTests.java +++ b/spring-batch-execution/src/test/java/org/springframework/batch/execution/step/support/DefaultStepFactoryBeanTests.java @@ -1,189 +1,189 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.batch.execution.step.support; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -import junit.framework.TestCase; - -import org.springframework.batch.core.domain.BatchListener; -import org.springframework.batch.core.domain.BatchStatus; -import org.springframework.batch.core.domain.JobExecution; -import org.springframework.batch.core.domain.JobParameters; -import org.springframework.batch.core.listener.ItemListenerSupport; -import org.springframework.batch.execution.job.SimpleJob; -import org.springframework.batch.execution.repository.SimpleJobRepository; -import org.springframework.batch.execution.repository.dao.MapJobExecutionDao; -import org.springframework.batch.execution.repository.dao.MapJobInstanceDao; -import org.springframework.batch.execution.repository.dao.MapStepExecutionDao; -import org.springframework.batch.execution.step.AbstractStep; -import org.springframework.batch.execution.step.ItemOrientedStep; -import org.springframework.batch.item.ItemReader; -import org.springframework.batch.item.ItemWriter; -import org.springframework.batch.item.reader.ListItemReader; -import org.springframework.batch.item.writer.AbstractItemWriter; -import org.springframework.batch.repeat.RepeatContext; -import org.springframework.batch.repeat.exception.handler.ExceptionHandler; -import org.springframework.batch.repeat.support.RepeatTemplate; -import org.springframework.batch.support.transaction.ResourcelessTransactionManager; -import org.springframework.batch.support.transaction.TransactionAwareProxyFactory; - -public class DefaultStepFactoryBeanTests extends TestCase { - - private List recovered = new ArrayList(); - - private SimpleJobRepository repository = new SimpleJobRepository(new MapJobInstanceDao(), new MapJobExecutionDao(), - new MapStepExecutionDao()); - - private List processed = new ArrayList(); - - private ItemWriter processor = new AbstractItemWriter() { - public void write(Object data) throws Exception { - processed.add((String) data); - } - }; - - private ItemReader provider; - - private SimpleJob job = new SimpleJob();; - - protected void setUp() throws Exception { - super.setUp(); - job.setJobRepository(repository); - MapJobInstanceDao.clear(); - MapJobExecutionDao.clear(); - MapStepExecutionDao.clear(); - } - - private DefaultStepFactoryBean getStep(String arg) throws Exception { - return getStep(new String[] { arg }); - } - - private DefaultStepFactoryBean getStep(String arg0, String arg1) throws Exception { - return getStep(new String[] { arg0, arg1 }); - } - - private DefaultStepFactoryBean getStep(String[] args) throws Exception { - DefaultStepFactoryBean factory = new DefaultStepFactoryBean(); - - List items = TransactionAwareProxyFactory.createTransactionalList(); - items.addAll(Arrays.asList(args)); - provider = new ListItemReader(items); - - factory.setItemReader(provider); - factory.setItemWriter(processor); - factory.setJobRepository(repository); - factory.setTransactionManager(new ResourcelessTransactionManager()); - factory.setBeanName("stepName"); - return factory; - } - - public void testSimpleJob() throws Exception { - - job.setSteps(new ArrayList()); - AbstractStep step = (AbstractStep) getStep("foo", "bar").getObject(); - step.setName("step1"); - job.addStep(step); - step = (AbstractStep) getStep("spam").getObject(); - step.setName("step2"); - job.addStep(step); - - JobExecution jobExecution = repository.createJobExecution(job, new JobParameters()); - - job.execute(jobExecution); - assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus()); - assertEquals(3, processed.size()); - assertTrue(processed.contains("foo")); - } - - public void testSimpleJobWithItemListeners() throws Exception { - - final List throwables = new ArrayList(); - - RepeatTemplate chunkOperations = new RepeatTemplate(); - // Always handle the exception a check it is the right one... - chunkOperations.setExceptionHandler(new ExceptionHandler() { - public void handleException(RepeatContext context, Throwable throwable) throws RuntimeException { - throwables.add(throwable); - assertEquals("Error!", throwable.getMessage()); - } - }); - - /* - * Each message fails once and the chunk (size=1) "rolls back"; then it - * is recovered ("skipped") on the second attempt (see retry policy - * definition above)... - */ - DefaultStepFactoryBean factory = getStep(new String[] { "foo", "bar", "spam" }); - - factory.setItemWriter(new AbstractItemWriter() { - public void write(Object data) throws Exception { - throw new RuntimeException("Error!"); - } - }); - factory.setListeners(new BatchListener[] { new ItemListenerSupport() { - public void onReadError(Exception ex) { - recovered.add(ex); - } - - public void onWriteError(Exception ex, Object item) { - recovered.add(ex); - } - } }); - - ItemOrientedStep step = (ItemOrientedStep) factory.getObject(); - step.setChunkOperations(chunkOperations); - - job.setSteps(Collections.singletonList(step)); - - JobExecution jobExecution = repository.createJobExecution(job, new JobParameters()); - job.execute(jobExecution); - - assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus()); - assertEquals(0, processed.size()); - // provider should be exhausted - assertEquals(null, provider.read()); - assertEquals(3, recovered.size()); - } - - public void testExceptionTerminates() throws Exception { - DefaultStepFactoryBean factory = getStep(new String[] { "foo", "bar", "spam" }); - factory.setBeanName("exceptionStep"); - factory.setItemWriter(new AbstractItemWriter() { - public void write(Object data) throws Exception { - throw new RuntimeException("Foo"); - } - }); - ItemOrientedStep step = (ItemOrientedStep) factory.getObject(); - job.setSteps(Collections.singletonList(step)); - - JobExecution jobExecution = repository.createJobExecution(job, new JobParameters()); - try { - job.execute(jobExecution); - fail("Expected RuntimeException"); - } - catch (RuntimeException e) { - assertEquals("Foo", e.getMessage()); - // expected - } - assertEquals(BatchStatus.FAILED, jobExecution.getStatus()); - } - -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.batch.execution.step.support; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import junit.framework.TestCase; + +import org.springframework.batch.core.domain.BatchListener; +import org.springframework.batch.core.domain.BatchStatus; +import org.springframework.batch.core.domain.JobExecution; +import org.springframework.batch.core.domain.JobParameters; +import org.springframework.batch.core.listener.ItemListenerSupport; +import org.springframework.batch.execution.job.SimpleJob; +import org.springframework.batch.execution.repository.SimpleJobRepository; +import org.springframework.batch.execution.repository.dao.MapJobExecutionDao; +import org.springframework.batch.execution.repository.dao.MapJobInstanceDao; +import org.springframework.batch.execution.repository.dao.MapStepExecutionDao; +import org.springframework.batch.execution.step.AbstractStep; +import org.springframework.batch.execution.step.ItemOrientedStep; +import org.springframework.batch.item.ItemReader; +import org.springframework.batch.item.ItemWriter; +import org.springframework.batch.item.reader.ListItemReader; +import org.springframework.batch.item.writer.AbstractItemWriter; +import org.springframework.batch.repeat.RepeatContext; +import org.springframework.batch.repeat.exception.handler.ExceptionHandler; +import org.springframework.batch.repeat.support.RepeatTemplate; +import org.springframework.batch.support.transaction.ResourcelessTransactionManager; +import org.springframework.batch.support.transaction.TransactionAwareProxyFactory; + +public class DefaultStepFactoryBeanTests extends TestCase { + + private List recovered = new ArrayList(); + + private SimpleJobRepository repository = new SimpleJobRepository(new MapJobInstanceDao(), new MapJobExecutionDao(), + new MapStepExecutionDao()); + + private List processed = new ArrayList(); + + private ItemWriter processor = new AbstractItemWriter() { + public void write(Object data) throws Exception { + processed.add((String) data); + } + }; + + private ItemReader provider; + + private SimpleJob job = new SimpleJob();; + + protected void setUp() throws Exception { + super.setUp(); + job.setJobRepository(repository); + MapJobInstanceDao.clear(); + MapJobExecutionDao.clear(); + MapStepExecutionDao.clear(); + } + + private DefaultStepFactoryBean getStep(String arg) throws Exception { + return getStep(new String[] { arg }); + } + + private DefaultStepFactoryBean getStep(String arg0, String arg1) throws Exception { + return getStep(new String[] { arg0, arg1 }); + } + + private DefaultStepFactoryBean getStep(String[] args) throws Exception { + DefaultStepFactoryBean factory = new DefaultStepFactoryBean(); + + List items = TransactionAwareProxyFactory.createTransactionalList(); + items.addAll(Arrays.asList(args)); + provider = new ListItemReader(items); + + factory.setItemReader(provider); + factory.setItemWriter(processor); + factory.setJobRepository(repository); + factory.setTransactionManager(new ResourcelessTransactionManager()); + factory.setBeanName("stepName"); + return factory; + } + + public void testSimpleJob() throws Exception { + + job.setSteps(new ArrayList()); + AbstractStep step = (AbstractStep) getStep("foo", "bar").getObject(); + step.setName("step1"); + job.addStep(step); + step = (AbstractStep) getStep("spam").getObject(); + step.setName("step2"); + job.addStep(step); + + JobExecution jobExecution = repository.createJobExecution(job, new JobParameters()); + + job.execute(jobExecution); + assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus()); + assertEquals(3, processed.size()); + assertTrue(processed.contains("foo")); + } + + public void testSimpleJobWithItemListeners() throws Exception { + + final List throwables = new ArrayList(); + + RepeatTemplate chunkOperations = new RepeatTemplate(); + // Always handle the exception a check it is the right one... + chunkOperations.setExceptionHandler(new ExceptionHandler() { + public void handleException(RepeatContext context, Throwable throwable) throws RuntimeException { + throwables.add(throwable); + assertEquals("Error!", throwable.getMessage()); + } + }); + + /* + * Each message fails once and the chunk (size=1) "rolls back"; then it + * is recovered ("skipped") on the second attempt (see retry policy + * definition above)... + */ + DefaultStepFactoryBean factory = getStep(new String[] { "foo", "bar", "spam" }); + + factory.setItemWriter(new AbstractItemWriter() { + public void write(Object data) throws Exception { + throw new RuntimeException("Error!"); + } + }); + factory.setListeners(new BatchListener[] { new ItemListenerSupport() { + public void onReadError(Exception ex) { + recovered.add(ex); + } + + public void onWriteError(Exception ex, Object item) { + recovered.add(ex); + } + } }); + + ItemOrientedStep step = (ItemOrientedStep) factory.getObject(); + step.setChunkOperations(chunkOperations); + + job.setSteps(Collections.singletonList(step)); + + JobExecution jobExecution = repository.createJobExecution(job, new JobParameters()); + job.execute(jobExecution); + + assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus()); + assertEquals(0, processed.size()); + // provider should be exhausted + assertEquals(null, provider.read()); + assertEquals(3, recovered.size()); + } + + public void testExceptionTerminates() throws Exception { + DefaultStepFactoryBean factory = getStep(new String[] { "foo", "bar", "spam" }); + factory.setBeanName("exceptionStep"); + factory.setItemWriter(new AbstractItemWriter() { + public void write(Object data) throws Exception { + throw new RuntimeException("Foo"); + } + }); + ItemOrientedStep step = (ItemOrientedStep) factory.getObject(); + job.setSteps(Collections.singletonList(step)); + + JobExecution jobExecution = repository.createJobExecution(job, new JobParameters()); + try { + job.execute(jobExecution); + fail("Expected RuntimeException"); + } + catch (RuntimeException e) { + assertEquals("Foo", e.getMessage()); + // expected + } + assertEquals(BatchStatus.FAILED, jobExecution.getStatus()); + } + +} diff --git a/spring-batch-execution/src/test/java/org/springframework/batch/execution/step/support/JobRepositorySupport.java b/spring-batch-execution/src/test/java/org/springframework/batch/execution/step/support/JobRepositorySupport.java index c456d28eaf..f744ed8fd1 100644 --- a/spring-batch-execution/src/test/java/org/springframework/batch/execution/step/support/JobRepositorySupport.java +++ b/spring-batch-execution/src/test/java/org/springframework/batch/execution/step/support/JobRepositorySupport.java @@ -1,73 +1,73 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.execution.step.support; - -import org.springframework.batch.core.domain.Job; -import org.springframework.batch.core.domain.JobExecution; -import org.springframework.batch.core.domain.JobInstance; -import org.springframework.batch.core.domain.JobParameters; -import org.springframework.batch.core.domain.Step; -import org.springframework.batch.core.domain.StepExecution; -import org.springframework.batch.core.repository.JobRepository; - -/** - * @author Dave Syer - * - */ -public class JobRepositorySupport implements JobRepository { - - /* (non-Javadoc) - * @see org.springframework.batch.container.common.repository.JobRepository#findOrCreateJob(org.springframework.batch.container.common.domain.JobConfiguration) - */ - public JobExecution createJobExecution(Job jobConfiguration, JobParameters jobParameters) { - return null; - } - - /* (non-Javadoc) - * @see org.springframework.batch.container.common.repository.JobRepository#saveOrUpdate(org.springframework.batch.container.common.domain.JobExecution) - */ - public void saveOrUpdate(JobExecution jobExecution) { - } - - /* (non-Javadoc) - * @see org.springframework.batch.container.common.repository.JobRepository#saveOrUpdate(org.springframework.batch.container.common.domain.StepExecution) - */ - public void saveOrUpdate(StepExecution stepExecution) { - } - - /* (non-Javadoc) - * @see org.springframework.batch.core.repository.JobRepository#saveOrUpdateExecutionContext(org.springframework.batch.core.domain.StepExecution) - */ - public void saveOrUpdateExecutionContext(StepExecution stepExecution) { - } - - /* (non-Javadoc) - * @see org.springframework.batch.container.common.repository.JobRepository#update(org.springframework.batch.container.common.domain.Job) - */ - public void update(JobInstance job) { - } - - public StepExecution getLastStepExecution(JobInstance jobInstance, Step step) { - // TODO Auto-generated method stub - return null; - } - - public int getStepExecutionCount(JobInstance jobInstance, Step step) { - // TODO Auto-generated method stub - return 0; - } - -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.execution.step.support; + +import org.springframework.batch.core.domain.Job; +import org.springframework.batch.core.domain.JobExecution; +import org.springframework.batch.core.domain.JobInstance; +import org.springframework.batch.core.domain.JobParameters; +import org.springframework.batch.core.domain.Step; +import org.springframework.batch.core.domain.StepExecution; +import org.springframework.batch.core.repository.JobRepository; + +/** + * @author Dave Syer + * + */ +public class JobRepositorySupport implements JobRepository { + + /* (non-Javadoc) + * @see org.springframework.batch.container.common.repository.JobRepository#findOrCreateJob(org.springframework.batch.container.common.domain.JobConfiguration) + */ + public JobExecution createJobExecution(Job jobConfiguration, JobParameters jobParameters) { + return null; + } + + /* (non-Javadoc) + * @see org.springframework.batch.container.common.repository.JobRepository#saveOrUpdate(org.springframework.batch.container.common.domain.JobExecution) + */ + public void saveOrUpdate(JobExecution jobExecution) { + } + + /* (non-Javadoc) + * @see org.springframework.batch.container.common.repository.JobRepository#saveOrUpdate(org.springframework.batch.container.common.domain.StepExecution) + */ + public void saveOrUpdate(StepExecution stepExecution) { + } + + /* (non-Javadoc) + * @see org.springframework.batch.core.repository.JobRepository#saveOrUpdateExecutionContext(org.springframework.batch.core.domain.StepExecution) + */ + public void saveOrUpdateExecutionContext(StepExecution stepExecution) { + } + + /* (non-Javadoc) + * @see org.springframework.batch.container.common.repository.JobRepository#update(org.springframework.batch.container.common.domain.Job) + */ + public void update(JobInstance job) { + } + + public StepExecution getLastStepExecution(JobInstance jobInstance, Step step) { + // TODO Auto-generated method stub + return null; + } + + public int getStepExecutionCount(JobInstance jobInstance, Step step) { + // TODO Auto-generated method stub + return 0; + } + +} diff --git a/spring-batch-execution/src/test/java/org/springframework/batch/execution/step/support/SimpleExitStatusExceptionClassifierTests.java b/spring-batch-execution/src/test/java/org/springframework/batch/execution/step/support/SimpleExitStatusExceptionClassifierTests.java index b8a4ff5e42..9dee57ba01 100644 --- a/spring-batch-execution/src/test/java/org/springframework/batch/execution/step/support/SimpleExitStatusExceptionClassifierTests.java +++ b/spring-batch-execution/src/test/java/org/springframework/batch/execution/step/support/SimpleExitStatusExceptionClassifierTests.java @@ -1,77 +1,77 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.execution.step.support; - - -import org.springframework.batch.core.domain.JobInterruptedException; -import org.springframework.batch.core.runtime.ExitStatusExceptionClassifier; -import org.springframework.batch.execution.step.support.SimpleExitStatusExceptionClassifier; -import org.springframework.batch.repeat.ExitStatus; - -import junit.framework.TestCase; - -/** - * @author Lucas Ward - * - */ -public class SimpleExitStatusExceptionClassifierTests extends TestCase { - - NullPointerException exception; - - SimpleExitStatusExceptionClassifier classifier = new SimpleExitStatusExceptionClassifier(); - - protected void setUp() throws Exception { - super.setUp(); - exception = new NullPointerException(); - } - - public void testClassifyForExitCode() { - ExitStatus exitStatus = classifier.classifyForExitCode(exception); - assertEquals(exitStatus.getExitCode(), "FATAL_EXCEPTION"); - String description = exitStatus.getExitDescription(); - assertTrue("Description does not contain NullPointerException: "+description, description.indexOf("java.lang.NullPointerException")>=0); - } - - public void testClassify() { - ExitStatus exitStatus = (ExitStatus)classifier.classify(exception); - assertEquals(exitStatus.getExitCode(), "FATAL_EXCEPTION"); - String description = exitStatus.getExitDescription(); - assertTrue("Description does not contain NullPointerException: "+description, description.indexOf("java.lang.NullPointerException")>=0); - } - - public void testGetDefault() { - ExitStatus exitStatus = (ExitStatus)classifier.getDefault(); - assertEquals(exitStatus.getExitCode(), "FATAL_EXCEPTION"); - assertEquals(exitStatus.getExitDescription(), ""); - } - - /* - * Attempting to classify a null throwable should lead to a blank description, not a - * null pointer exception. - */ - public void testClassifyNullThrowable(){ - ExitStatus exitStatus = (ExitStatus)classifier.classify(null); - assertEquals(exitStatus.getExitCode(), "FATAL_EXCEPTION"); - assertEquals(exitStatus.getExitDescription(), ""); - } - - public void testClassifyInterruptedException(){ - ExitStatus exitStatus = (ExitStatus)classifier.classifyForExitCode(new JobInterruptedException("")); - assertEquals(exitStatus.getExitCode(), ExitStatusExceptionClassifier.JOB_INTERRUPTED); - assertEquals(exitStatus.getExitDescription(), - JobInterruptedException.class.getName()); - } -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.execution.step.support; + + +import org.springframework.batch.core.domain.JobInterruptedException; +import org.springframework.batch.core.runtime.ExitStatusExceptionClassifier; +import org.springframework.batch.execution.step.support.SimpleExitStatusExceptionClassifier; +import org.springframework.batch.repeat.ExitStatus; + +import junit.framework.TestCase; + +/** + * @author Lucas Ward + * + */ +public class SimpleExitStatusExceptionClassifierTests extends TestCase { + + NullPointerException exception; + + SimpleExitStatusExceptionClassifier classifier = new SimpleExitStatusExceptionClassifier(); + + protected void setUp() throws Exception { + super.setUp(); + exception = new NullPointerException(); + } + + public void testClassifyForExitCode() { + ExitStatus exitStatus = classifier.classifyForExitCode(exception); + assertEquals(exitStatus.getExitCode(), "FATAL_EXCEPTION"); + String description = exitStatus.getExitDescription(); + assertTrue("Description does not contain NullPointerException: "+description, description.indexOf("java.lang.NullPointerException")>=0); + } + + public void testClassify() { + ExitStatus exitStatus = (ExitStatus)classifier.classify(exception); + assertEquals(exitStatus.getExitCode(), "FATAL_EXCEPTION"); + String description = exitStatus.getExitDescription(); + assertTrue("Description does not contain NullPointerException: "+description, description.indexOf("java.lang.NullPointerException")>=0); + } + + public void testGetDefault() { + ExitStatus exitStatus = (ExitStatus)classifier.getDefault(); + assertEquals(exitStatus.getExitCode(), "FATAL_EXCEPTION"); + assertEquals(exitStatus.getExitDescription(), ""); + } + + /* + * Attempting to classify a null throwable should lead to a blank description, not a + * null pointer exception. + */ + public void testClassifyNullThrowable(){ + ExitStatus exitStatus = (ExitStatus)classifier.classify(null); + assertEquals(exitStatus.getExitCode(), "FATAL_EXCEPTION"); + assertEquals(exitStatus.getExitDescription(), ""); + } + + public void testClassifyInterruptedException(){ + ExitStatus exitStatus = (ExitStatus)classifier.classifyForExitCode(new JobInterruptedException("")); + assertEquals(exitStatus.getExitCode(), ExitStatusExceptionClassifier.JOB_INTERRUPTED); + assertEquals(exitStatus.getExitDescription(), + JobInterruptedException.class.getName()); + } +} diff --git a/spring-batch-execution/src/test/java/org/springframework/batch/execution/step/support/ThreadStepInterruptionPolicyTests.java b/spring-batch-execution/src/test/java/org/springframework/batch/execution/step/support/ThreadStepInterruptionPolicyTests.java index f73d4ae27d..a66e3a19ad 100644 --- a/spring-batch-execution/src/test/java/org/springframework/batch/execution/step/support/ThreadStepInterruptionPolicyTests.java +++ b/spring-batch-execution/src/test/java/org/springframework/batch/execution/step/support/ThreadStepInterruptionPolicyTests.java @@ -1,58 +1,58 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.execution.step.support; - -import junit.framework.TestCase; - -import org.springframework.batch.core.domain.JobInterruptedException; -import org.springframework.batch.execution.step.support.ThreadStepInterruptionPolicy; -import org.springframework.batch.repeat.RepeatContext; -import org.springframework.batch.repeat.context.RepeatContextSupport; - -/** - * @author Dave Syer - * - */ -public class ThreadStepInterruptionPolicyTests extends TestCase { - - ThreadStepInterruptionPolicy policy = new ThreadStepInterruptionPolicy(); - private RepeatContext context = new RepeatContextSupport(null);; - - /** - * Test method for {@link org.springframework.batch.core.executor.interrupt.ThreadStepInterruptionPolicy#checkInterrupted(org.springframework.batch.repeat.RepeatContext)}. - * @throws Exception - */ - public void testCheckInterruptedNotComplete() throws Exception { - policy.checkInterrupted(context); - // no exception - } - - /** - * Test method for {@link org.springframework.batch.core.executor.interrupt.ThreadStepInterruptionPolicy#checkInterrupted(org.springframework.batch.repeat.RepeatContext)}. - * @throws Exception - */ - public void testCheckInterruptedComplete() throws Exception { - context.setTerminateOnly(); - try { - policy.checkInterrupted(context); - fail("Expected StepInterruptedException"); - } catch (JobInterruptedException e) { - // expected - assertTrue(e.getMessage().indexOf("interrupt")>=0); - } - } - -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.execution.step.support; + +import junit.framework.TestCase; + +import org.springframework.batch.core.domain.JobInterruptedException; +import org.springframework.batch.execution.step.support.ThreadStepInterruptionPolicy; +import org.springframework.batch.repeat.RepeatContext; +import org.springframework.batch.repeat.context.RepeatContextSupport; + +/** + * @author Dave Syer + * + */ +public class ThreadStepInterruptionPolicyTests extends TestCase { + + ThreadStepInterruptionPolicy policy = new ThreadStepInterruptionPolicy(); + private RepeatContext context = new RepeatContextSupport(null);; + + /** + * Test method for {@link org.springframework.batch.core.executor.interrupt.ThreadStepInterruptionPolicy#checkInterrupted(org.springframework.batch.repeat.RepeatContext)}. + * @throws Exception + */ + public void testCheckInterruptedNotComplete() throws Exception { + policy.checkInterrupted(context); + // no exception + } + + /** + * Test method for {@link org.springframework.batch.core.executor.interrupt.ThreadStepInterruptionPolicy#checkInterrupted(org.springframework.batch.repeat.RepeatContext)}. + * @throws Exception + */ + public void testCheckInterruptedComplete() throws Exception { + context.setTerminateOnly(); + try { + policy.checkInterrupted(context); + fail("Expected StepInterruptedException"); + } catch (JobInterruptedException e) { + // expected + assertTrue(e.getMessage().indexOf("interrupt")>=0); + } + } + +} diff --git a/spring-batch-infrastructure/.project b/spring-batch-infrastructure/.project index 35219658b2..6f2559a0ca 100644 --- a/spring-batch-infrastructure/.project +++ b/spring-batch-infrastructure/.project @@ -1,29 +1,29 @@ - - - spring-batch-infrastructure - The Spring Batch Infrastructure is a set of low-level components, interfaces and tools for batch processing applications and optimisations. - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.springframework.ide.eclipse.core.springbuilder - - - - - org.devzuz.q.maven.jdt.core.mavenIncrementalBuilder - - - - - - org.springframework.ide.eclipse.core.springnature - org.eclipse.jdt.core.javanature - org.devzuz.q.maven.jdt.core.mavenNature - - + + + spring-batch-infrastructure + The Spring Batch Infrastructure is a set of low-level components, interfaces and tools for batch processing applications and optimisations. + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.springframework.ide.eclipse.core.springbuilder + + + + + org.devzuz.q.maven.jdt.core.mavenIncrementalBuilder + + + + + + org.springframework.ide.eclipse.core.springnature + org.eclipse.jdt.core.javanature + org.devzuz.q.maven.jdt.core.mavenNature + + diff --git a/spring-batch-infrastructure/.settings/org.eclipse.jdt.core.prefs b/spring-batch-infrastructure/.settings/org.eclipse.jdt.core.prefs index b97ef7d410..d3a8350953 100644 --- a/spring-batch-infrastructure/.settings/org.eclipse.jdt.core.prefs +++ b/spring-batch-infrastructure/.settings/org.eclipse.jdt.core.prefs @@ -1,8 +1,8 @@ -#Thu Mar 06 17:21:58 GMT 2008 -eclipse.preferences.version=1 -instance/org.eclipse.core.net/org.eclipse.core.net.hasMigrated=true -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.4 -org.eclipse.jdt.core.compiler.compliance=1.4 -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.enumIdentifier=warning -org.eclipse.jdt.core.compiler.source=1.4 +#Thu Mar 06 17:21:58 GMT 2008 +eclipse.preferences.version=1 +instance/org.eclipse.core.net/org.eclipse.core.net.hasMigrated=true +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.4 +org.eclipse.jdt.core.compiler.compliance=1.4 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=warning +org.eclipse.jdt.core.compiler.source=1.4 diff --git a/spring-batch-infrastructure/.settings/org.eclipse.mylyn.tasks.ui.prefs b/spring-batch-infrastructure/.settings/org.eclipse.mylyn.tasks.ui.prefs index c017c7c132..01dd83051c 100644 --- a/spring-batch-infrastructure/.settings/org.eclipse.mylyn.tasks.ui.prefs +++ b/spring-batch-infrastructure/.settings/org.eclipse.mylyn.tasks.ui.prefs @@ -1,4 +1,4 @@ -#Thu Aug 23 07:01:38 BST 2007 -eclipse.preferences.version=1 -project.repository.kind=jira -project.repository.url=http\://opensource.atlassian.com/projects/spring +#Thu Aug 23 07:01:38 BST 2007 +eclipse.preferences.version=1 +project.repository.kind=jira +project.repository.url=http\://opensource.atlassian.com/projects/spring diff --git a/spring-batch-infrastructure/.settings/org.springframework.ide.eclipse.core.prefs b/spring-batch-infrastructure/.settings/org.springframework.ide.eclipse.core.prefs index a76011c636..0e7af83f21 100644 --- a/spring-batch-infrastructure/.settings/org.springframework.ide.eclipse.core.prefs +++ b/spring-batch-infrastructure/.settings/org.springframework.ide.eclipse.core.prefs @@ -1,33 +1,33 @@ -#Wed Oct 10 18:12:57 BST 2007 -eclipse.preferences.version=1 -org.springframework.ide.eclipse.core.builders.enable.aopreferencemodelbuilder=true -org.springframework.ide.eclipse.core.validator.enable.org.springframework.ide.eclipse.beans.core.beansvalidator=true -org.springframework.ide.eclipse.core.validator.enable.org.springframework.ide.eclipse.webflow.core.validator=true -org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.beanAlias-org.springframework.ide.eclipse.beans.core.beansvalidator=true -org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.beanClass-org.springframework.ide.eclipse.beans.core.beansvalidator=true -org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.beanConstructorArgument-org.springframework.ide.eclipse.beans.core.beansvalidator=true -org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.beanDefinition-org.springframework.ide.eclipse.beans.core.beansvalidator=true -org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.beanDefinitionHolder-org.springframework.ide.eclipse.beans.core.beansvalidator=true -org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.beanFactory-org.springframework.ide.eclipse.beans.core.beansvalidator=true -org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.beanInitDestroyMethod-org.springframework.ide.eclipse.beans.core.beansvalidator=true -org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.beanProperty-org.springframework.ide.eclipse.beans.core.beansvalidator=true -org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.beanReference-org.springframework.ide.eclipse.beans.core.beansvalidator=true -org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.requiredProperty-org.springframework.ide.eclipse.beans.core.beansvalidator=false -org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.action-org.springframework.ide.eclipse.webflow.core.validator=true -org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.actionstate-org.springframework.ide.eclipse.webflow.core.validator=true -org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.attribute-org.springframework.ide.eclipse.webflow.core.validator=true -org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.attributemapper-org.springframework.ide.eclipse.webflow.core.validator=true -org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.beanaction-org.springframework.ide.eclipse.webflow.core.validator=true -org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.evaluationaction-org.springframework.ide.eclipse.webflow.core.validator=true -org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.evaluationresult-org.springframework.ide.eclipse.webflow.core.validator=true -org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.exceptionhandler-org.springframework.ide.eclipse.webflow.core.validator=true -org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.import-org.springframework.ide.eclipse.webflow.core.validator=true -org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.inputattribute-org.springframework.ide.eclipse.webflow.core.validator=true -org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.mapping-org.springframework.ide.eclipse.webflow.core.validator=true -org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.outputattribute-org.springframework.ide.eclipse.webflow.core.validator=true -org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.set-org.springframework.ide.eclipse.webflow.core.validator=true -org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.state-org.springframework.ide.eclipse.webflow.core.validator=true -org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.subflowstate-org.springframework.ide.eclipse.webflow.core.validator=true -org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.transition-org.springframework.ide.eclipse.webflow.core.validator=true -org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.variable-org.springframework.ide.eclipse.webflow.core.validator=true -org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.webflowstate-org.springframework.ide.eclipse.webflow.core.validator=true +#Wed Oct 10 18:12:57 BST 2007 +eclipse.preferences.version=1 +org.springframework.ide.eclipse.core.builders.enable.aopreferencemodelbuilder=true +org.springframework.ide.eclipse.core.validator.enable.org.springframework.ide.eclipse.beans.core.beansvalidator=true +org.springframework.ide.eclipse.core.validator.enable.org.springframework.ide.eclipse.webflow.core.validator=true +org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.beanAlias-org.springframework.ide.eclipse.beans.core.beansvalidator=true +org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.beanClass-org.springframework.ide.eclipse.beans.core.beansvalidator=true +org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.beanConstructorArgument-org.springframework.ide.eclipse.beans.core.beansvalidator=true +org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.beanDefinition-org.springframework.ide.eclipse.beans.core.beansvalidator=true +org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.beanDefinitionHolder-org.springframework.ide.eclipse.beans.core.beansvalidator=true +org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.beanFactory-org.springframework.ide.eclipse.beans.core.beansvalidator=true +org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.beanInitDestroyMethod-org.springframework.ide.eclipse.beans.core.beansvalidator=true +org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.beanProperty-org.springframework.ide.eclipse.beans.core.beansvalidator=true +org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.beanReference-org.springframework.ide.eclipse.beans.core.beansvalidator=true +org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.requiredProperty-org.springframework.ide.eclipse.beans.core.beansvalidator=false +org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.action-org.springframework.ide.eclipse.webflow.core.validator=true +org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.actionstate-org.springframework.ide.eclipse.webflow.core.validator=true +org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.attribute-org.springframework.ide.eclipse.webflow.core.validator=true +org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.attributemapper-org.springframework.ide.eclipse.webflow.core.validator=true +org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.beanaction-org.springframework.ide.eclipse.webflow.core.validator=true +org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.evaluationaction-org.springframework.ide.eclipse.webflow.core.validator=true +org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.evaluationresult-org.springframework.ide.eclipse.webflow.core.validator=true +org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.exceptionhandler-org.springframework.ide.eclipse.webflow.core.validator=true +org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.import-org.springframework.ide.eclipse.webflow.core.validator=true +org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.inputattribute-org.springframework.ide.eclipse.webflow.core.validator=true +org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.mapping-org.springframework.ide.eclipse.webflow.core.validator=true +org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.outputattribute-org.springframework.ide.eclipse.webflow.core.validator=true +org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.set-org.springframework.ide.eclipse.webflow.core.validator=true +org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.state-org.springframework.ide.eclipse.webflow.core.validator=true +org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.subflowstate-org.springframework.ide.eclipse.webflow.core.validator=true +org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.transition-org.springframework.ide.eclipse.webflow.core.validator=true +org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.variable-org.springframework.ide.eclipse.webflow.core.validator=true +org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.webflowstate-org.springframework.ide.eclipse.webflow.core.validator=true diff --git a/spring-batch-infrastructure/.springBeans b/spring-batch-infrastructure/.springBeans index 5c11fe605e..826912ba02 100644 --- a/spring-batch-infrastructure/.springBeans +++ b/spring-batch-infrastructure/.springBeans @@ -1,15 +1,15 @@ - - - 1 - - - - - - - src/test/resources/org/springframework/batch/io/sql/data-source-context.xml - src/test/resources/org/springframework/batch/retry/aop/retry-transaction-test.xml - - - - + + + 1 + + + + + + + src/test/resources/org/springframework/batch/io/sql/data-source-context.xml + src/test/resources/org/springframework/batch/retry/aop/retry-transaction-test.xml + + + + diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/common/BinaryExceptionClassifier.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/common/BinaryExceptionClassifier.java index 2e4f9abffa..628f1a7183 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/common/BinaryExceptionClassifier.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/common/BinaryExceptionClassifier.java @@ -1,77 +1,77 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.common; - -import java.util.HashMap; -import java.util.Map; - -/** - * A {@link ExceptionClassifier} that has only two classes of exception. - * Provides convenient methods for setting up and querying the classification - * with boolean return type. - * - * @author Dave Syer - * - */ -public class BinaryExceptionClassifier extends ExceptionClassifierSupport { - - /** - * The classifier result for a non-default exception. - */ - public static final String NON_DEFAULT = "NON_DEFAULT"; - - private SubclassExceptionClassifier delegate = new SubclassExceptionClassifier(); - - /** - * Set the special exceptions. Any exception on the list, or subclasses - * thereof, will be classified as non-default. - * - * @param exceptionClasses defaults to {@link Exception}. - */ - public final void setExceptionClasses(Class[] exceptionClasses) { - Map temp = new HashMap(); - for (int i = 0; i < exceptionClasses.length; i++) { - temp.put(exceptionClasses[i], NON_DEFAULT); - } - this.delegate.setTypeMap(temp); - } - - /** - * Convenience method to return boolean if the throwable is classified as - * default. - * - * @param throwable the Throwable to classify - * @return true if it is default classified (i.e. not on the list provided - * in {@link #setExceptionClasses(Class[])}. - */ - public boolean isDefault(Throwable throwable) { - return classify(throwable).equals(DEFAULT); - } - - /** - * Returns either {@link ExceptionClassifierSupport#DEFAULT} or - * {@link #NON_DEFAULT} depending on the type of the throwable. If the type - * of the throwable or one of its ancestors is on the exception class list - * the classification is as {@link #NON_DEFAULT}. - * - * @see #setExceptionClasses(Class[]) - * @see ExceptionClassifierSupport#classify(Throwable) - */ - public Object classify(Throwable throwable) { - return delegate.classify(throwable); - } - -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.common; + +import java.util.HashMap; +import java.util.Map; + +/** + * A {@link ExceptionClassifier} that has only two classes of exception. + * Provides convenient methods for setting up and querying the classification + * with boolean return type. + * + * @author Dave Syer + * + */ +public class BinaryExceptionClassifier extends ExceptionClassifierSupport { + + /** + * The classifier result for a non-default exception. + */ + public static final String NON_DEFAULT = "NON_DEFAULT"; + + private SubclassExceptionClassifier delegate = new SubclassExceptionClassifier(); + + /** + * Set the special exceptions. Any exception on the list, or subclasses + * thereof, will be classified as non-default. + * + * @param exceptionClasses defaults to {@link Exception}. + */ + public final void setExceptionClasses(Class[] exceptionClasses) { + Map temp = new HashMap(); + for (int i = 0; i < exceptionClasses.length; i++) { + temp.put(exceptionClasses[i], NON_DEFAULT); + } + this.delegate.setTypeMap(temp); + } + + /** + * Convenience method to return boolean if the throwable is classified as + * default. + * + * @param throwable the Throwable to classify + * @return true if it is default classified (i.e. not on the list provided + * in {@link #setExceptionClasses(Class[])}. + */ + public boolean isDefault(Throwable throwable) { + return classify(throwable).equals(DEFAULT); + } + + /** + * Returns either {@link ExceptionClassifierSupport#DEFAULT} or + * {@link #NON_DEFAULT} depending on the type of the throwable. If the type + * of the throwable or one of its ancestors is on the exception class list + * the classification is as {@link #NON_DEFAULT}. + * + * @see #setExceptionClasses(Class[]) + * @see ExceptionClassifierSupport#classify(Throwable) + */ + public Object classify(Throwable throwable) { + return delegate.classify(throwable); + } + +} diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/common/SubclassExceptionClassifier.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/common/SubclassExceptionClassifier.java index b68ca341ac..f2776a4102 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/common/SubclassExceptionClassifier.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/common/SubclassExceptionClassifier.java @@ -1,113 +1,113 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.common; - -import java.util.Comparator; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; -import java.util.Set; -import java.util.TreeSet; - -import org.springframework.util.Assert; - -/** - * - * @author Dave Syer - * - */ -public class SubclassExceptionClassifier extends ExceptionClassifierSupport { - - private Map classified = new HashMap(); - - /** - * Map of Throwable class types to keys for the classifier. Any subclass of - * the type provided will be classified as of the type given by the - * correspinding map entry value. - * - * @param typeMap the typeMap to set - */ - public final void setTypeMap(Map typeMap) { - Map map = new HashMap(); - for (Iterator iter = typeMap.entrySet().iterator(); iter.hasNext();) { - Map.Entry entry = (Map.Entry) iter.next(); - addRetryableExceptionClass(entry.getKey(), entry.getValue(), map); - } - this.classified = map; - } - - /** - * Return the value from the type map whose key is the class of the given - * Throwable, or its nearest ancestor if a subclass. - * - * @see org.springframework.batch.common.ExceptionClassifierSupport#classify(java.lang.Throwable) - */ - public Object classify(Throwable throwable) { - - if (throwable == null) { - return super.classify(throwable); - } - - Class exceptionClass = throwable.getClass(); - if (classified.containsKey(exceptionClass)) { - return classified.get(exceptionClass); - } - - // check for subclasses - Set classes = new TreeSet(new ClassComparator()); - classes.addAll(classified.keySet()); - for (Iterator iterator = classes.iterator(); iterator.hasNext();) { - Class cls = (Class) iterator.next(); - if (cls.isAssignableFrom(exceptionClass)) { - Object value = classified.get(cls); - addRetryableExceptionClass(exceptionClass, value, this.classified); - return value; - } - } - - return super.classify(throwable); - } - - private void addRetryableExceptionClass(Object candidateClass, Object classifiedAs, Map map) { - Assert.isAssignable(Class.class, candidateClass.getClass()); - Class exceptionClass = (Class) candidateClass; - Assert.isAssignable(Throwable.class, exceptionClass); - map.put(exceptionClass, classifiedAs); - } - - /** - * Comparator for classes to order by inheritance. - * - * @author Dave Syer - * - */ - private class ClassComparator implements Comparator { - /** - * @return 1 if arg0 is assignable from arg1 - * @return -1 otherwise - * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object) - */ - public int compare(Object arg0, Object arg1) { - Class cls0 = (Class) arg0; - Class cls1 = (Class) arg1; - if (cls0.isAssignableFrom(cls1)) { - return 1; - } - return -1; - } - } - -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.common; + +import java.util.Comparator; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; +import java.util.TreeSet; + +import org.springframework.util.Assert; + +/** + * + * @author Dave Syer + * + */ +public class SubclassExceptionClassifier extends ExceptionClassifierSupport { + + private Map classified = new HashMap(); + + /** + * Map of Throwable class types to keys for the classifier. Any subclass of + * the type provided will be classified as of the type given by the + * correspinding map entry value. + * + * @param typeMap the typeMap to set + */ + public final void setTypeMap(Map typeMap) { + Map map = new HashMap(); + for (Iterator iter = typeMap.entrySet().iterator(); iter.hasNext();) { + Map.Entry entry = (Map.Entry) iter.next(); + addRetryableExceptionClass(entry.getKey(), entry.getValue(), map); + } + this.classified = map; + } + + /** + * Return the value from the type map whose key is the class of the given + * Throwable, or its nearest ancestor if a subclass. + * + * @see org.springframework.batch.common.ExceptionClassifierSupport#classify(java.lang.Throwable) + */ + public Object classify(Throwable throwable) { + + if (throwable == null) { + return super.classify(throwable); + } + + Class exceptionClass = throwable.getClass(); + if (classified.containsKey(exceptionClass)) { + return classified.get(exceptionClass); + } + + // check for subclasses + Set classes = new TreeSet(new ClassComparator()); + classes.addAll(classified.keySet()); + for (Iterator iterator = classes.iterator(); iterator.hasNext();) { + Class cls = (Class) iterator.next(); + if (cls.isAssignableFrom(exceptionClass)) { + Object value = classified.get(cls); + addRetryableExceptionClass(exceptionClass, value, this.classified); + return value; + } + } + + return super.classify(throwable); + } + + private void addRetryableExceptionClass(Object candidateClass, Object classifiedAs, Map map) { + Assert.isAssignable(Class.class, candidateClass.getClass()); + Class exceptionClass = (Class) candidateClass; + Assert.isAssignable(Throwable.class, exceptionClass); + map.put(exceptionClass, classifiedAs); + } + + /** + * Comparator for classes to order by inheritance. + * + * @author Dave Syer + * + */ + private class ClassComparator implements Comparator { + /** + * @return 1 if arg0 is assignable from arg1 + * @return -1 otherwise + * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object) + */ + public int compare(Object arg0, Object arg1) { + Class cls0 = (Class) arg0; + Class cls1 = (Class) arg1; + if (cls0.isAssignableFrom(cls1)) { + return 1; + } + return -1; + } + } + +} diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/cursor/HibernateCursorItemReader.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/cursor/HibernateCursorItemReader.java index 893dea5748..c95a69e3b1 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/cursor/HibernateCursorItemReader.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/cursor/HibernateCursorItemReader.java @@ -1,242 +1,242 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.io.cursor; - -import java.util.ArrayList; -import java.util.List; - -import org.hibernate.ScrollableResults; -import org.hibernate.Session; -import org.hibernate.SessionFactory; -import org.hibernate.StatelessSession; -import org.springframework.batch.io.Skippable; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.item.ExecutionContextUserSupport; -import org.springframework.batch.item.ItemReader; -import org.springframework.batch.item.ItemStream; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.util.Assert; -import org.springframework.util.StringUtils; - -/** - * {@link ItemReader} for reading database records built on top of Hibernate. - * - * It executes the HQL {@link #queryString} when initialized and iterates over - * the result set as {@link #read()} method is called, returning an object - * corresponding to current row. - * - * Input source can be configured to use either {@link StatelessSession} - * sufficient for simple mappings without the need to cascade to associated - * objects or standard hibernate {@link Session} for more advanced mappings or - * when caching is desired. - * - * When stateful session is used it will be cleared after successful commit - * without being flushed (no inserts or updates are expected). - * - * @author Robert Kasanicky - * @author Dave Syer - */ -public class HibernateCursorItemReader extends ExecutionContextUserSupport implements ItemReader, ItemStream, Skippable, InitializingBean { - - private static final String RESTART_DATA_ROW_NUMBER_KEY = "row.number"; - - private static final String SKIPPED_ROWS = "skipped.rows"; - - private SessionFactory sessionFactory; - - private StatelessSession statelessSession; - - private Session statefulSession; - - private ScrollableResults cursor; - - private String queryString; - - private boolean useStatelessSession = true; - - private int lastCommitRowNumber = 0; - - private final List skippedRows = new ArrayList(); - - private int skipCount = 0; - - /* Current count of processed records. */ - private int currentProcessedRow = 0; - - private boolean initialized = false; - - private boolean saveState = false; - - - public HibernateCursorItemReader() { - setName(HibernateCursorItemReader.class.getSimpleName()); - } - - public Object read() { - if (!initialized) { - open(new ExecutionContext()); - } - if (cursor.next()) { - currentProcessedRow++; - if (!skippedRows.isEmpty()) { - // while is necessary to handle successive skips. - while (skippedRows.contains(new Integer(currentProcessedRow))) { - if (!cursor.next()) { - return null; - } - currentProcessedRow++; - } - } - Object data = cursor.get(0); - return data; - } - return null; - } - - /** - * Closes the result set cursor and hibernate session. - */ - public void close(ExecutionContext executionContext) { - initialized = false; - cursor.close(); - currentProcessedRow = 0; - skippedRows.clear(); - skipCount = 0; - if (useStatelessSession) { - statelessSession.close(); - } - else { - statefulSession.close(); - } - } - - /** - * Creates cursor for the query. - */ - public void open(ExecutionContext executionContext) { - Assert.state(!initialized, "Cannot open an already opened ItemReader, call close first"); - - if (useStatelessSession) { - statelessSession = sessionFactory.openStatelessSession(); - cursor = statelessSession.createQuery(queryString).scroll(); - } - else { - statefulSession = sessionFactory.openSession(); - cursor = statefulSession.createQuery(queryString).scroll(); - } - initialized = true; - - if (executionContext.containsKey(getKey(RESTART_DATA_ROW_NUMBER_KEY))) { - currentProcessedRow = Integer.parseInt(executionContext.getString(getKey(RESTART_DATA_ROW_NUMBER_KEY))); - cursor.setRowNumber(currentProcessedRow - 1); - } - - if (executionContext.containsKey(getKey(SKIPPED_ROWS))) { - String[] skipped = StringUtils.commaDelimitedListToStringArray(executionContext.getString(getKey(SKIPPED_ROWS))); - for (int i = 0; i < skipped.length; i++) { - this.skippedRows.add(new Integer(skipped[i])); - } - } - } - - /** - * @param sessionFactory hibernate session factory - */ - public void setSessionFactory(SessionFactory sessionFactory) { - this.sessionFactory = sessionFactory; - } - - public void afterPropertiesSet() throws Exception { - Assert.notNull(sessionFactory); - Assert.hasLength(queryString); - } - - /** - * @param queryString HQL query string - */ - public void setQueryString(String queryString) { - this.queryString = queryString; - } - - /** - * Can be set only in uninitialized state. - * - * @param useStatelessSession true to use - * {@link StatelessSession} false to use standard hibernate - * {@link Session} - */ - public void setUseStatelessSession(boolean useStatelessSession) { - Assert.state(!initialized); - this.useStatelessSession = useStatelessSession; - } - - /** - */ - public void update(ExecutionContext executionContext) { - if(saveState){ - Assert.notNull(executionContext, "ExecutionContext must not be null"); - executionContext.putString(getKey(RESTART_DATA_ROW_NUMBER_KEY), "" + currentProcessedRow); - String skipped = skippedRows.toString(); - executionContext.putString(getKey(SKIPPED_ROWS), skipped.substring(1, skipped.length() - 1)); - } - } - - /** - * Skip the current row. If the transaction is rolled back, this row will - * not be represented when read() is called. For example, if you read in row - * 2, find the data to be bad, and call skip(), then continue processing and - * find - */ - public void skip() { - skippedRows.add(new Integer(currentProcessedRow)); - skipCount++; - } - - /** - * Mark is supported as long as this {@link ItemStream} is used in a - * single-threaded environment. The state backing the mark is a single - * counter, keeping track of the current position, so multiple threads - * cannot be accommodated. - * - * @see org.springframework.batch.item.ItemReader#mark() - */ - public void mark() { - lastCommitRowNumber = currentProcessedRow; - if (!useStatelessSession) { - statefulSession.clear(); - } - } - - /* - * (non-Javadoc) - * @see org.springframework.batch.item.stream.ItemStreamAdapter#reset(org.springframework.batch.item.ExecutionContext) - */ - public void reset() { - currentProcessedRow = lastCommitRowNumber; - if (lastCommitRowNumber == 0) { - cursor.beforeFirst(); - } - else { - // Set the cursor so that next time it is advanced it will - // come back to the committed row. - cursor.setRowNumber(lastCommitRowNumber - 1); - } - } - - public void setSaveState(boolean saveState) { - this.saveState = saveState; - } -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.io.cursor; + +import java.util.ArrayList; +import java.util.List; + +import org.hibernate.ScrollableResults; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.hibernate.StatelessSession; +import org.springframework.batch.io.Skippable; +import org.springframework.batch.item.ExecutionContext; +import org.springframework.batch.item.ExecutionContextUserSupport; +import org.springframework.batch.item.ItemReader; +import org.springframework.batch.item.ItemStream; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.util.Assert; +import org.springframework.util.StringUtils; + +/** + * {@link ItemReader} for reading database records built on top of Hibernate. + * + * It executes the HQL {@link #queryString} when initialized and iterates over + * the result set as {@link #read()} method is called, returning an object + * corresponding to current row. + * + * Input source can be configured to use either {@link StatelessSession} + * sufficient for simple mappings without the need to cascade to associated + * objects or standard hibernate {@link Session} for more advanced mappings or + * when caching is desired. + * + * When stateful session is used it will be cleared after successful commit + * without being flushed (no inserts or updates are expected). + * + * @author Robert Kasanicky + * @author Dave Syer + */ +public class HibernateCursorItemReader extends ExecutionContextUserSupport implements ItemReader, ItemStream, Skippable, InitializingBean { + + private static final String RESTART_DATA_ROW_NUMBER_KEY = "row.number"; + + private static final String SKIPPED_ROWS = "skipped.rows"; + + private SessionFactory sessionFactory; + + private StatelessSession statelessSession; + + private Session statefulSession; + + private ScrollableResults cursor; + + private String queryString; + + private boolean useStatelessSession = true; + + private int lastCommitRowNumber = 0; + + private final List skippedRows = new ArrayList(); + + private int skipCount = 0; + + /* Current count of processed records. */ + private int currentProcessedRow = 0; + + private boolean initialized = false; + + private boolean saveState = false; + + + public HibernateCursorItemReader() { + setName(HibernateCursorItemReader.class.getSimpleName()); + } + + public Object read() { + if (!initialized) { + open(new ExecutionContext()); + } + if (cursor.next()) { + currentProcessedRow++; + if (!skippedRows.isEmpty()) { + // while is necessary to handle successive skips. + while (skippedRows.contains(new Integer(currentProcessedRow))) { + if (!cursor.next()) { + return null; + } + currentProcessedRow++; + } + } + Object data = cursor.get(0); + return data; + } + return null; + } + + /** + * Closes the result set cursor and hibernate session. + */ + public void close(ExecutionContext executionContext) { + initialized = false; + cursor.close(); + currentProcessedRow = 0; + skippedRows.clear(); + skipCount = 0; + if (useStatelessSession) { + statelessSession.close(); + } + else { + statefulSession.close(); + } + } + + /** + * Creates cursor for the query. + */ + public void open(ExecutionContext executionContext) { + Assert.state(!initialized, "Cannot open an already opened ItemReader, call close first"); + + if (useStatelessSession) { + statelessSession = sessionFactory.openStatelessSession(); + cursor = statelessSession.createQuery(queryString).scroll(); + } + else { + statefulSession = sessionFactory.openSession(); + cursor = statefulSession.createQuery(queryString).scroll(); + } + initialized = true; + + if (executionContext.containsKey(getKey(RESTART_DATA_ROW_NUMBER_KEY))) { + currentProcessedRow = Integer.parseInt(executionContext.getString(getKey(RESTART_DATA_ROW_NUMBER_KEY))); + cursor.setRowNumber(currentProcessedRow - 1); + } + + if (executionContext.containsKey(getKey(SKIPPED_ROWS))) { + String[] skipped = StringUtils.commaDelimitedListToStringArray(executionContext.getString(getKey(SKIPPED_ROWS))); + for (int i = 0; i < skipped.length; i++) { + this.skippedRows.add(new Integer(skipped[i])); + } + } + } + + /** + * @param sessionFactory hibernate session factory + */ + public void setSessionFactory(SessionFactory sessionFactory) { + this.sessionFactory = sessionFactory; + } + + public void afterPropertiesSet() throws Exception { + Assert.notNull(sessionFactory); + Assert.hasLength(queryString); + } + + /** + * @param queryString HQL query string + */ + public void setQueryString(String queryString) { + this.queryString = queryString; + } + + /** + * Can be set only in uninitialized state. + * + * @param useStatelessSession true to use + * {@link StatelessSession} false to use standard hibernate + * {@link Session} + */ + public void setUseStatelessSession(boolean useStatelessSession) { + Assert.state(!initialized); + this.useStatelessSession = useStatelessSession; + } + + /** + */ + public void update(ExecutionContext executionContext) { + if(saveState){ + Assert.notNull(executionContext, "ExecutionContext must not be null"); + executionContext.putString(getKey(RESTART_DATA_ROW_NUMBER_KEY), "" + currentProcessedRow); + String skipped = skippedRows.toString(); + executionContext.putString(getKey(SKIPPED_ROWS), skipped.substring(1, skipped.length() - 1)); + } + } + + /** + * Skip the current row. If the transaction is rolled back, this row will + * not be represented when read() is called. For example, if you read in row + * 2, find the data to be bad, and call skip(), then continue processing and + * find + */ + public void skip() { + skippedRows.add(new Integer(currentProcessedRow)); + skipCount++; + } + + /** + * Mark is supported as long as this {@link ItemStream} is used in a + * single-threaded environment. The state backing the mark is a single + * counter, keeping track of the current position, so multiple threads + * cannot be accommodated. + * + * @see org.springframework.batch.item.ItemReader#mark() + */ + public void mark() { + lastCommitRowNumber = currentProcessedRow; + if (!useStatelessSession) { + statefulSession.clear(); + } + } + + /* + * (non-Javadoc) + * @see org.springframework.batch.item.stream.ItemStreamAdapter#reset(org.springframework.batch.item.ExecutionContext) + */ + public void reset() { + currentProcessedRow = lastCommitRowNumber; + if (lastCommitRowNumber == 0) { + cursor.beforeFirst(); + } + else { + // Set the cursor so that next time it is advanced it will + // come back to the committed row. + cursor.setRowNumber(lastCommitRowNumber - 1); + } + } + + public void setSaveState(boolean saveState) { + this.saveState = saveState; + } +} diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/cursor/JdbcCursorItemReader.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/cursor/JdbcCursorItemReader.java index 644e3b5eec..74ee6806e9 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/cursor/JdbcCursorItemReader.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/cursor/JdbcCursorItemReader.java @@ -1,519 +1,519 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.batch.io.cursor; - -import java.sql.Connection; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.SQLWarning; -import java.sql.Statement; -import java.util.ArrayList; -import java.util.List; - -import javax.sql.DataSource; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.springframework.batch.io.Skippable; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.item.ExecutionContextUserSupport; -import org.springframework.batch.item.ItemReader; -import org.springframework.batch.item.ItemStream; -import org.springframework.batch.item.exception.ResetFailedException; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.dao.DataAccessException; -import org.springframework.dao.InvalidDataAccessResourceUsageException; -import org.springframework.jdbc.SQLWarningException; -import org.springframework.jdbc.core.RowMapper; -import org.springframework.jdbc.support.JdbcUtils; -import org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator; -import org.springframework.jdbc.support.SQLExceptionTranslator; -import org.springframework.jdbc.support.SQLStateSQLExceptionTranslator; -import org.springframework.util.Assert; -import org.springframework.util.StringUtils; - -/** - *

- * Simple input source that opens a JDBC cursor and continually retrieves the - * next row in the ResultSet. It is extremely important to note that the - * JdbcDriver used must be version 3.0 or higher. This is because earlier - * versions do not support holding a ResultSet open over commits. - *

- * - *

- * Each call to {@link #read()} will call the provided RowMapper, passing in the - * ResultSet. There is currently no wrapping of the ResultSet to suppress calls - * to next(). However, if the RowMapper (mistakenly) increments the current row, - * the next call to read will verify that the current row is at the expected - * position and throw a DataAccessException if it is not. This means that, in - * theory, a RowMapper could read ahead, as long as it returns the row back to - * the correct position before returning. The reason for such strictness on the - * ResultSet is due to the need to maintain control for transactions, - * restartability and skippability. This ensures that each call to - * {@link #read()} returns the ResultSet at the correct line, regardless of - * rollbacks, restarts, or skips. - *

- * - *

- * {@link ExecutionContext}: The current row is returned as restart data, and - * when restored from that same data, the cursor is opened and the current row - * set to the value within the restart data. Two values are stored: the current - * line being processed and the number of lines that have been skipped. - *

- * - *

- * Transactions: The same ResultSet is held open regardless of commits or roll - * backs in a surrounding transaction. This means that when such a transaction - * is committed, the input source is notified through the {@link #mark()} and - * {@link #reset()} so that it can save it's current row number. Later, if the - * transaction is rolled back, the current row can be moved back to the same row - * number as it was on when commit was called. - *

- * - *

- * Calling skip will indicate that a record is bad and should not be - * re-presented to the user if the transaction is rolled back. For example, if - * row 2 is read in, and found to be bad, calling skip will inform the - * {@link ItemReader}. If reading is then continued, and a rollback is - * necessary because of an error on output, the input source will be returned to - * row 1. Calling read while on row 1 will move the current row to 3, not 2, - * because 2 has been marked as skipped. - *

- * - *

- * Calling close on this {@link ItemStream} will cause all resources it is - * currently using to be freed. (Connection, ResultSet, etc). It is then illegal - * to call {@link #read()} again until it has been opened. - *

- * - * @author Lucas Ward - * @author Peter Zozom - */ -public class JdbcCursorItemReader extends ExecutionContextUserSupport implements ItemReader, InitializingBean, ItemStream, Skippable { - - private static Log log = LogFactory.getLog(JdbcCursorItemReader.class); - - public static final int VALUE_NOT_SET = -1; - - private static final String CURRENT_PROCESSED_ROW = "last.processed.row.number"; - - private static final String SKIPPED_ROWS = "skipped.rows"; - - private static final String SKIP_COUNT = "skipped.record.count"; - - private Connection con; - - private Statement stmt; - - protected ResultSet rs; - - private DataSource dataSource; - - private String sql; - - private final List skippedRows = new ArrayList(); - - private int skipCount = 0; - - private int fetchSize = VALUE_NOT_SET; - - private int maxRows = VALUE_NOT_SET; - - private int queryTimeout = VALUE_NOT_SET; - - private boolean ignoreWarnings = true; - - private boolean verifyCursorPosition = true; - - private SQLExceptionTranslator exceptionTranslator; - - /* Current count of processed records. */ - private long currentProcessedRow = 0; - - private long lastCommittedRow = 0; - - private RowMapper mapper; - - private boolean initialized = false; - - private boolean saveState = false; - - public JdbcCursorItemReader() { - setName(JdbcCursorItemReader.class.getSimpleName()); - } - - /** - * Assert that mandatory properties are set. - * - * @throws IllegalArgumentException if either data source or sql properties - * not set. - */ - public void afterPropertiesSet() throws Exception { - Assert.notNull(dataSource, "DataSOurce must be provided"); - Assert.notNull(sql, "The SQL query must be provided"); - } - - /** - * Public setter for the data source for injection purposes. - * - * @param dataSource - */ - public void setDataSource(DataSource dataSource) { - this.dataSource = dataSource; - } - - /** - * Increment the cursor to the next row, validating the cursor position and - * passing the resultset to the RowMapper. If read has not been called on - * this instance before, the cursor will be opened. If there are skipped - * records for this commit scope, an internal list of skipped records will - * be checked to ensure that only a valid row is given to the mapper. - * - * @returns Object returned by RowMapper - * @throws DataAccessException - * @throws IllegalStateExceptino if mapper is null. - */ - public Object read() { - - if (!initialized) { - open(new ExecutionContext()); - } - - Assert.state(mapper != null, "Mapper must not be null."); - - try { - if (!rs.next()) { - return null; - } - else { - currentProcessedRow++; - if (!skippedRows.isEmpty()) { - // while is necessary to handle successive skips. - while (skippedRows.contains(new Long(currentProcessedRow))) { - if (!rs.next()) { - return null; - } - currentProcessedRow++; - } - } - - Object mappedResult = mapper.mapRow(rs, (int) currentProcessedRow); - - verifyCursorPosition(currentProcessedRow); - - return mappedResult; - } - } - catch (SQLException se) { - throw getExceptionTranslator().translate("Trying to process next row", sql, se); - } - - } - - public long getCurrentProcessedRow() { - return currentProcessedRow; - } - - /** - * Mark the current row. Calling reset will cause the result set to be set - * to the current row when mark was called. - */ - public void mark() { - lastCommittedRow = currentProcessedRow; - skippedRows.clear(); - } - - /** - * Set the ResultSet's current row to the last marked position. - * - * @throws DataAccessException - */ - public void reset() throws ResetFailedException { - try { - currentProcessedRow = lastCommittedRow; - if (currentProcessedRow > 0) { - rs.absolute((int) currentProcessedRow); - } - else { - rs.beforeFirst(); - } - - } - catch (SQLException se) { - throw new ResetFailedException(getExceptionTranslator().translate( - "Attempted to move ResultSet to last committed row", sql, se)); - } - } - - /** - * Close this input source. The ResultSet, Statement and Connection created - * will be closed. This must be called or the connection and cursor will be - * held open indefinitely! - * - * @see org.springframework.batch.item.ResourceLifecycle#close(ExecutionContext) - */ - public void close(ExecutionContext executionContext) { - initialized = false; - JdbcUtils.closeResultSet(this.rs); - JdbcUtils.closeStatement(this.stmt); - JdbcUtils.closeConnection(this.con); - this.currentProcessedRow = 0; - skippedRows.clear(); - skipCount = 0; - } - - // Check the result set is in synch with the currentRow attribute. This is - // important - // to ensure that the user hasn't modified the current row. - private void verifyCursorPosition(long expectedCurrentRow) throws SQLException { - if (verifyCursorPosition) { - if (expectedCurrentRow != this.rs.getRow()) { - throw new InvalidDataAccessResourceUsageException("Unexpected cursor position change."); - } - } - } - - /* - * Executes the provided SQL query. The statement is created with - * 'READ_ONLY' and 'HOLD_CUSORS_OVER_COMMIT' set to true. This is extremely - * important, since a non read-only cursor may lock tables that shouldn't be - * locked, and not holding the cursor open over a commit would require it to - * be reopened after each commit, which would destroy performance. - */ - private void executeQuery() { - - Assert.state(dataSource != null, "DataSource must not be null."); - - try { - this.con = dataSource.getConnection(); - this.stmt = this.con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY, - ResultSet.HOLD_CURSORS_OVER_COMMIT); - applyStatementSettings(this.stmt); - this.rs = this.stmt.executeQuery(sql); - handleWarnings(this.stmt.getWarnings()); - } - catch (SQLException se) { - close(null); - throw getExceptionTranslator().translate("Executing query", sql, se); - } - - } - - /* - * Prepare the given JDBC Statement (or PreparedStatement or - * CallableStatement), applying statement settings such as fetch size, max - * rows, and query timeout. @param stmt the JDBC Statement to prepare - * @throws SQLException - * - * @see #setFetchSize - * @see #setMaxRows - * @see #setQueryTimeout - */ - private void applyStatementSettings(Statement stmt) throws SQLException { - if (fetchSize != VALUE_NOT_SET) { - stmt.setFetchSize(fetchSize); - stmt.setFetchDirection(ResultSet.FETCH_FORWARD); - } - if (maxRows != VALUE_NOT_SET) { - stmt.setMaxRows(maxRows); - } - if (queryTimeout != VALUE_NOT_SET) { - stmt.setQueryTimeout(queryTimeout); - } - } - - /* - * Return the exception translator for this instance.

Creates a default - * SQLErrorCodeSQLExceptionTranslator for the specified DataSource if none - * is set. - */ - protected SQLExceptionTranslator getExceptionTranslator() { - if (exceptionTranslator == null) { - if (dataSource != null) { - exceptionTranslator = new SQLErrorCodeSQLExceptionTranslator(dataSource); - } - else { - exceptionTranslator = new SQLStateSQLExceptionTranslator(); - } - } - return exceptionTranslator; - } - - /* - * Throw a SQLWarningException if we're not ignoring warnings, else log the - * warnings (at debug level). - * - * @param warning the warnings object from the current statement. May be - * null, in which case this method does nothing. - * - * @see org.springframework.jdbc.SQLWarningException - */ - private void handleWarnings(SQLWarning warnings) throws SQLWarningException { - if (ignoreWarnings) { - SQLWarning warningToLog = warnings; - while (warningToLog != null) { - log.debug("SQLWarning ignored: SQL state '" + warningToLog.getSQLState() + "', error code '" - + warningToLog.getErrorCode() + "', message [" + warningToLog.getMessage() + "]"); - warningToLog = warningToLog.getNextWarning(); - } - } - else if (warnings != null) { - throw new SQLWarningException("Warning not ignored", warnings); - } - } - - /* - * (non-Javadoc) - * @see org.springframework.batch.item.stream.ItemStreamAdapter#getExecutionContext() - */ - public void update(ExecutionContext executionContext) { - if (saveState) { - Assert.notNull(executionContext, "ExecutionContext must not be null"); - String skipped = skippedRows.toString(); - executionContext.putString(getKey(SKIPPED_ROWS), skipped.substring(1, skipped.length() - 1)); - executionContext.putLong(getKey(CURRENT_PROCESSED_ROW), currentProcessedRow); - executionContext.putLong(getKey(SKIP_COUNT), skipCount); - } - } - - /* - * (non-Javadoc) - * @see org.springframework.batch.item.stream.ItemStreamAdapter#restoreFrom(org.springframework.batch.item.ExecutionContext) - */ - public void open(ExecutionContext context) { - Assert.state(!initialized, "Stream is already initialized. Close before re-opening."); - Assert.isNull(rs); - Assert.notNull(context, "ExecutionContext must not be null"); - executeQuery(); - initialized = true; - - // Properties restartProperties = data.getProperties(); - if (!context.containsKey(getKey(CURRENT_PROCESSED_ROW))) { - return; - } - - try { - this.currentProcessedRow = context.getLong(getKey(CURRENT_PROCESSED_ROW)); - rs.absolute((int) currentProcessedRow); - } - catch (SQLException se) { - throw getExceptionTranslator().translate("Attempted to move ResultSet to last committed row", sql, se); - } - - if (!context.containsKey(getKey(SKIPPED_ROWS))) { - return; - } - - String[] skipped = StringUtils.commaDelimitedListToStringArray(context.getString(getKey(SKIPPED_ROWS))); - for (int i = 0; i < skipped.length; i++) { - this.skippedRows.add(new Long(skipped[i])); - } - } - - /** - * Skip the current row. If the transaction is rolled back, this row will - * not be represented to the RowMapper when read() is called. For example, - * if you read in row 2, find the data to be bad, and call skip(), then - * continue processing and find - */ - public void skip() { - skippedRows.add(new Long(currentProcessedRow)); - skipCount++; - } - - /** - * Gives the JDBC driver a hint as to the number of rows that should be - * fetched from the database when more rows are needed for this - * ResultSet object. If the fetch size specified is zero, the - * JDBC driver ignores the value. - * - * @param fetchSize the number of rows to fetch - * @see ResultSet#setFetchSize(int) - */ - public void setFetchSize(int fetchSize) { - this.fetchSize = fetchSize; - } - - /** - * Sets the limit for the maximum number of rows that any - * ResultSet object can contain to the given number. - * - * @param maxRows the new max rows limit; zero means there is no limit - * @see Statement#setMaxRows(int) - */ - public void setMaxRows(int maxRows) { - this.maxRows = maxRows; - } - - /** - * Sets the number of seconds the driver will wait for a - * Statement object to execute to the given number of - * seconds. If the limit is exceeded, an SQLException is - * thrown. - * - * @param queryTimeout seconds the new query timeout limit in seconds; zero - * means there is no limit - * @see Statement#setQueryTimeout(int) - */ - public void setQueryTimeout(int queryTimeout) { - this.queryTimeout = queryTimeout; - } - - /** - * Set whether SQLWarnings should be ignored (only logged) or exception - * should be thrown. - * - * @param ignoreWarnings if TRUE, warnings are ignored - */ - public void setIgnoreWarnings(boolean ignoreWarnings) { - this.ignoreWarnings = ignoreWarnings; - } - - /** - * Allow verification of cursor position after current row is processed by - * RowMapper or RowCallbackHandler. Default value is TRUE. - * - * @param verifyCursorPosition if true, cursor position is verified - */ - public void setVerifyCursorPosition(boolean verifyCursorPosition) { - this.verifyCursorPosition = verifyCursorPosition; - } - - /** - * Set the RowMapper to be used for all calls to read(). - * - * @param mapper - */ - public void setMapper(RowMapper mapper) { - this.mapper = mapper; - } - - /** - * Set the sql statement to be used when creating the cursor. This statement - * should be a complete and valid Sql statement, as it will be run directly - * without any modification. - * - * @param sql - */ - public void setSql(String sql) { - this.sql = sql; - } - - public void setSaveState(boolean saveState) { - this.saveState = saveState; - } -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.batch.io.cursor; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.SQLWarning; +import java.sql.Statement; +import java.util.ArrayList; +import java.util.List; + +import javax.sql.DataSource; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.batch.io.Skippable; +import org.springframework.batch.item.ExecutionContext; +import org.springframework.batch.item.ExecutionContextUserSupport; +import org.springframework.batch.item.ItemReader; +import org.springframework.batch.item.ItemStream; +import org.springframework.batch.item.exception.ResetFailedException; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.dao.DataAccessException; +import org.springframework.dao.InvalidDataAccessResourceUsageException; +import org.springframework.jdbc.SQLWarningException; +import org.springframework.jdbc.core.RowMapper; +import org.springframework.jdbc.support.JdbcUtils; +import org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator; +import org.springframework.jdbc.support.SQLExceptionTranslator; +import org.springframework.jdbc.support.SQLStateSQLExceptionTranslator; +import org.springframework.util.Assert; +import org.springframework.util.StringUtils; + +/** + *

+ * Simple input source that opens a JDBC cursor and continually retrieves the + * next row in the ResultSet. It is extremely important to note that the + * JdbcDriver used must be version 3.0 or higher. This is because earlier + * versions do not support holding a ResultSet open over commits. + *

+ * + *

+ * Each call to {@link #read()} will call the provided RowMapper, passing in the + * ResultSet. There is currently no wrapping of the ResultSet to suppress calls + * to next(). However, if the RowMapper (mistakenly) increments the current row, + * the next call to read will verify that the current row is at the expected + * position and throw a DataAccessException if it is not. This means that, in + * theory, a RowMapper could read ahead, as long as it returns the row back to + * the correct position before returning. The reason for such strictness on the + * ResultSet is due to the need to maintain control for transactions, + * restartability and skippability. This ensures that each call to + * {@link #read()} returns the ResultSet at the correct line, regardless of + * rollbacks, restarts, or skips. + *

+ * + *

+ * {@link ExecutionContext}: The current row is returned as restart data, and + * when restored from that same data, the cursor is opened and the current row + * set to the value within the restart data. Two values are stored: the current + * line being processed and the number of lines that have been skipped. + *

+ * + *

+ * Transactions: The same ResultSet is held open regardless of commits or roll + * backs in a surrounding transaction. This means that when such a transaction + * is committed, the input source is notified through the {@link #mark()} and + * {@link #reset()} so that it can save it's current row number. Later, if the + * transaction is rolled back, the current row can be moved back to the same row + * number as it was on when commit was called. + *

+ * + *

+ * Calling skip will indicate that a record is bad and should not be + * re-presented to the user if the transaction is rolled back. For example, if + * row 2 is read in, and found to be bad, calling skip will inform the + * {@link ItemReader}. If reading is then continued, and a rollback is + * necessary because of an error on output, the input source will be returned to + * row 1. Calling read while on row 1 will move the current row to 3, not 2, + * because 2 has been marked as skipped. + *

+ * + *

+ * Calling close on this {@link ItemStream} will cause all resources it is + * currently using to be freed. (Connection, ResultSet, etc). It is then illegal + * to call {@link #read()} again until it has been opened. + *

+ * + * @author Lucas Ward + * @author Peter Zozom + */ +public class JdbcCursorItemReader extends ExecutionContextUserSupport implements ItemReader, InitializingBean, ItemStream, Skippable { + + private static Log log = LogFactory.getLog(JdbcCursorItemReader.class); + + public static final int VALUE_NOT_SET = -1; + + private static final String CURRENT_PROCESSED_ROW = "last.processed.row.number"; + + private static final String SKIPPED_ROWS = "skipped.rows"; + + private static final String SKIP_COUNT = "skipped.record.count"; + + private Connection con; + + private Statement stmt; + + protected ResultSet rs; + + private DataSource dataSource; + + private String sql; + + private final List skippedRows = new ArrayList(); + + private int skipCount = 0; + + private int fetchSize = VALUE_NOT_SET; + + private int maxRows = VALUE_NOT_SET; + + private int queryTimeout = VALUE_NOT_SET; + + private boolean ignoreWarnings = true; + + private boolean verifyCursorPosition = true; + + private SQLExceptionTranslator exceptionTranslator; + + /* Current count of processed records. */ + private long currentProcessedRow = 0; + + private long lastCommittedRow = 0; + + private RowMapper mapper; + + private boolean initialized = false; + + private boolean saveState = false; + + public JdbcCursorItemReader() { + setName(JdbcCursorItemReader.class.getSimpleName()); + } + + /** + * Assert that mandatory properties are set. + * + * @throws IllegalArgumentException if either data source or sql properties + * not set. + */ + public void afterPropertiesSet() throws Exception { + Assert.notNull(dataSource, "DataSOurce must be provided"); + Assert.notNull(sql, "The SQL query must be provided"); + } + + /** + * Public setter for the data source for injection purposes. + * + * @param dataSource + */ + public void setDataSource(DataSource dataSource) { + this.dataSource = dataSource; + } + + /** + * Increment the cursor to the next row, validating the cursor position and + * passing the resultset to the RowMapper. If read has not been called on + * this instance before, the cursor will be opened. If there are skipped + * records for this commit scope, an internal list of skipped records will + * be checked to ensure that only a valid row is given to the mapper. + * + * @returns Object returned by RowMapper + * @throws DataAccessException + * @throws IllegalStateExceptino if mapper is null. + */ + public Object read() { + + if (!initialized) { + open(new ExecutionContext()); + } + + Assert.state(mapper != null, "Mapper must not be null."); + + try { + if (!rs.next()) { + return null; + } + else { + currentProcessedRow++; + if (!skippedRows.isEmpty()) { + // while is necessary to handle successive skips. + while (skippedRows.contains(new Long(currentProcessedRow))) { + if (!rs.next()) { + return null; + } + currentProcessedRow++; + } + } + + Object mappedResult = mapper.mapRow(rs, (int) currentProcessedRow); + + verifyCursorPosition(currentProcessedRow); + + return mappedResult; + } + } + catch (SQLException se) { + throw getExceptionTranslator().translate("Trying to process next row", sql, se); + } + + } + + public long getCurrentProcessedRow() { + return currentProcessedRow; + } + + /** + * Mark the current row. Calling reset will cause the result set to be set + * to the current row when mark was called. + */ + public void mark() { + lastCommittedRow = currentProcessedRow; + skippedRows.clear(); + } + + /** + * Set the ResultSet's current row to the last marked position. + * + * @throws DataAccessException + */ + public void reset() throws ResetFailedException { + try { + currentProcessedRow = lastCommittedRow; + if (currentProcessedRow > 0) { + rs.absolute((int) currentProcessedRow); + } + else { + rs.beforeFirst(); + } + + } + catch (SQLException se) { + throw new ResetFailedException(getExceptionTranslator().translate( + "Attempted to move ResultSet to last committed row", sql, se)); + } + } + + /** + * Close this input source. The ResultSet, Statement and Connection created + * will be closed. This must be called or the connection and cursor will be + * held open indefinitely! + * + * @see org.springframework.batch.item.ResourceLifecycle#close(ExecutionContext) + */ + public void close(ExecutionContext executionContext) { + initialized = false; + JdbcUtils.closeResultSet(this.rs); + JdbcUtils.closeStatement(this.stmt); + JdbcUtils.closeConnection(this.con); + this.currentProcessedRow = 0; + skippedRows.clear(); + skipCount = 0; + } + + // Check the result set is in synch with the currentRow attribute. This is + // important + // to ensure that the user hasn't modified the current row. + private void verifyCursorPosition(long expectedCurrentRow) throws SQLException { + if (verifyCursorPosition) { + if (expectedCurrentRow != this.rs.getRow()) { + throw new InvalidDataAccessResourceUsageException("Unexpected cursor position change."); + } + } + } + + /* + * Executes the provided SQL query. The statement is created with + * 'READ_ONLY' and 'HOLD_CUSORS_OVER_COMMIT' set to true. This is extremely + * important, since a non read-only cursor may lock tables that shouldn't be + * locked, and not holding the cursor open over a commit would require it to + * be reopened after each commit, which would destroy performance. + */ + private void executeQuery() { + + Assert.state(dataSource != null, "DataSource must not be null."); + + try { + this.con = dataSource.getConnection(); + this.stmt = this.con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY, + ResultSet.HOLD_CURSORS_OVER_COMMIT); + applyStatementSettings(this.stmt); + this.rs = this.stmt.executeQuery(sql); + handleWarnings(this.stmt.getWarnings()); + } + catch (SQLException se) { + close(null); + throw getExceptionTranslator().translate("Executing query", sql, se); + } + + } + + /* + * Prepare the given JDBC Statement (or PreparedStatement or + * CallableStatement), applying statement settings such as fetch size, max + * rows, and query timeout. @param stmt the JDBC Statement to prepare + * @throws SQLException + * + * @see #setFetchSize + * @see #setMaxRows + * @see #setQueryTimeout + */ + private void applyStatementSettings(Statement stmt) throws SQLException { + if (fetchSize != VALUE_NOT_SET) { + stmt.setFetchSize(fetchSize); + stmt.setFetchDirection(ResultSet.FETCH_FORWARD); + } + if (maxRows != VALUE_NOT_SET) { + stmt.setMaxRows(maxRows); + } + if (queryTimeout != VALUE_NOT_SET) { + stmt.setQueryTimeout(queryTimeout); + } + } + + /* + * Return the exception translator for this instance.

Creates a default + * SQLErrorCodeSQLExceptionTranslator for the specified DataSource if none + * is set. + */ + protected SQLExceptionTranslator getExceptionTranslator() { + if (exceptionTranslator == null) { + if (dataSource != null) { + exceptionTranslator = new SQLErrorCodeSQLExceptionTranslator(dataSource); + } + else { + exceptionTranslator = new SQLStateSQLExceptionTranslator(); + } + } + return exceptionTranslator; + } + + /* + * Throw a SQLWarningException if we're not ignoring warnings, else log the + * warnings (at debug level). + * + * @param warning the warnings object from the current statement. May be + * null, in which case this method does nothing. + * + * @see org.springframework.jdbc.SQLWarningException + */ + private void handleWarnings(SQLWarning warnings) throws SQLWarningException { + if (ignoreWarnings) { + SQLWarning warningToLog = warnings; + while (warningToLog != null) { + log.debug("SQLWarning ignored: SQL state '" + warningToLog.getSQLState() + "', error code '" + + warningToLog.getErrorCode() + "', message [" + warningToLog.getMessage() + "]"); + warningToLog = warningToLog.getNextWarning(); + } + } + else if (warnings != null) { + throw new SQLWarningException("Warning not ignored", warnings); + } + } + + /* + * (non-Javadoc) + * @see org.springframework.batch.item.stream.ItemStreamAdapter#getExecutionContext() + */ + public void update(ExecutionContext executionContext) { + if (saveState) { + Assert.notNull(executionContext, "ExecutionContext must not be null"); + String skipped = skippedRows.toString(); + executionContext.putString(getKey(SKIPPED_ROWS), skipped.substring(1, skipped.length() - 1)); + executionContext.putLong(getKey(CURRENT_PROCESSED_ROW), currentProcessedRow); + executionContext.putLong(getKey(SKIP_COUNT), skipCount); + } + } + + /* + * (non-Javadoc) + * @see org.springframework.batch.item.stream.ItemStreamAdapter#restoreFrom(org.springframework.batch.item.ExecutionContext) + */ + public void open(ExecutionContext context) { + Assert.state(!initialized, "Stream is already initialized. Close before re-opening."); + Assert.isNull(rs); + Assert.notNull(context, "ExecutionContext must not be null"); + executeQuery(); + initialized = true; + + // Properties restartProperties = data.getProperties(); + if (!context.containsKey(getKey(CURRENT_PROCESSED_ROW))) { + return; + } + + try { + this.currentProcessedRow = context.getLong(getKey(CURRENT_PROCESSED_ROW)); + rs.absolute((int) currentProcessedRow); + } + catch (SQLException se) { + throw getExceptionTranslator().translate("Attempted to move ResultSet to last committed row", sql, se); + } + + if (!context.containsKey(getKey(SKIPPED_ROWS))) { + return; + } + + String[] skipped = StringUtils.commaDelimitedListToStringArray(context.getString(getKey(SKIPPED_ROWS))); + for (int i = 0; i < skipped.length; i++) { + this.skippedRows.add(new Long(skipped[i])); + } + } + + /** + * Skip the current row. If the transaction is rolled back, this row will + * not be represented to the RowMapper when read() is called. For example, + * if you read in row 2, find the data to be bad, and call skip(), then + * continue processing and find + */ + public void skip() { + skippedRows.add(new Long(currentProcessedRow)); + skipCount++; + } + + /** + * Gives the JDBC driver a hint as to the number of rows that should be + * fetched from the database when more rows are needed for this + * ResultSet object. If the fetch size specified is zero, the + * JDBC driver ignores the value. + * + * @param fetchSize the number of rows to fetch + * @see ResultSet#setFetchSize(int) + */ + public void setFetchSize(int fetchSize) { + this.fetchSize = fetchSize; + } + + /** + * Sets the limit for the maximum number of rows that any + * ResultSet object can contain to the given number. + * + * @param maxRows the new max rows limit; zero means there is no limit + * @see Statement#setMaxRows(int) + */ + public void setMaxRows(int maxRows) { + this.maxRows = maxRows; + } + + /** + * Sets the number of seconds the driver will wait for a + * Statement object to execute to the given number of + * seconds. If the limit is exceeded, an SQLException is + * thrown. + * + * @param queryTimeout seconds the new query timeout limit in seconds; zero + * means there is no limit + * @see Statement#setQueryTimeout(int) + */ + public void setQueryTimeout(int queryTimeout) { + this.queryTimeout = queryTimeout; + } + + /** + * Set whether SQLWarnings should be ignored (only logged) or exception + * should be thrown. + * + * @param ignoreWarnings if TRUE, warnings are ignored + */ + public void setIgnoreWarnings(boolean ignoreWarnings) { + this.ignoreWarnings = ignoreWarnings; + } + + /** + * Allow verification of cursor position after current row is processed by + * RowMapper or RowCallbackHandler. Default value is TRUE. + * + * @param verifyCursorPosition if true, cursor position is verified + */ + public void setVerifyCursorPosition(boolean verifyCursorPosition) { + this.verifyCursorPosition = verifyCursorPosition; + } + + /** + * Set the RowMapper to be used for all calls to read(). + * + * @param mapper + */ + public void setMapper(RowMapper mapper) { + this.mapper = mapper; + } + + /** + * Set the sql statement to be used when creating the cursor. This statement + * should be a complete and valid Sql statement, as it will be run directly + * without any modification. + * + * @param sql + */ + public void setSql(String sql) { + this.sql = sql; + } + + public void setSaveState(boolean saveState) { + this.saveState = saveState; + } +} diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/driving/DrivingQueryItemReader.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/driving/DrivingQueryItemReader.java index 76b0d7e907..30fe7caa5f 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/driving/DrivingQueryItemReader.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/driving/DrivingQueryItemReader.java @@ -1,204 +1,204 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.io.driving; - -import java.util.Iterator; -import java.util.List; - -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.item.ItemReader; -import org.springframework.batch.item.ItemStream; -import org.springframework.batch.item.exception.NoWorkFoundException; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.util.Assert; - -/** - *

- * Convenience class for driving query input sources. Input Sources of this type - * use a 'driving query' to return back a list of keys. Upon each call to read, - * a new key is returned. To use the input source, inject a key generation - * strategy. - *

- * - *

- * Mutability: Because this base class cannot guarantee that the keys returned - * by subclasses are immutable, care should be taken to not modify a key value. - * Doing so would cause issues if a rollback occurs. For example, if a call to - * read() is made, and the returned key is modified, a rollback will cause the - * next call to read() to return the same object that was originally returned, - * since there is no way to create a defensive copy, and re-querying the - * database for all the keys would be too resource intensive. - *

- * - * - * @author Lucas Ward - * @since 1.0 - */ -public class DrivingQueryItemReader implements ItemReader, InitializingBean, - ItemStream { - - private boolean initialized = false; - - private List keys; - - private Iterator keysIterator; - - private int currentIndex = 0; - - private int lastCommitIndex = 0; - - private KeyGenerator keyGenerator; - - private boolean saveState = false; - - public DrivingQueryItemReader() { - - } - - /** - * Initialize the input source with the provided keys list. - * - * @param keys - */ - public DrivingQueryItemReader(List keys) { - this.keys = keys; - this.keysIterator = keys.iterator(); - } - - /** - * Return the next key in the List. If the ItemReader has not been - * initialized yet, then {@link AbstractDrivingQueryItemReader.open()} will - * be called. - * - * @return next key in the list if not index is not at the last element, - * null otherwise. - */ - public Object read() { - if (!initialized) { - open(new ExecutionContext()); - } - - if (keysIterator.hasNext()) { - currentIndex++; - return keysIterator.next(); - } - - return null; - } - - /** - * Get the current key. This method will return the same object returned by - * the last read() method. If the ItemReader hasn't been initialized yet, - * then null will be returned. - * - * @return the current key. - */ - protected Object getCurrentKey() { - if (initialized) { - return keys.get(currentIndex - 1); - } - - return null; - } - - /** - * Close the resource by setting the list of keys to null, allowing them to - * be garbage collected. - */ - public void close(ExecutionContext executionContext) { - initialized = false; - currentIndex = 0; - lastCommitIndex = 0; - keys = null; - keysIterator = null; - } - - /** - * Initialize the input source by delegating to the subclass in order to - * retrieve the keys. The input source will also be registered with the - * {@link BatchTransactionSynchronizationManager} in order to ensure it is - * notified about commits and rollbacks. - * - * @throws IllegalStateException if the keys list is null or initialized is - * true. - */ - public void open(ExecutionContext executionContext) { - - Assert.state(keys == null && !initialized, "Cannot open an already opened input source" - + ", call close() first."); - keys = keyGenerator.retrieveKeys(executionContext); - if(keys == null || keys.size() == 0){ - throw new NoWorkFoundException("KeyGenerator must return at least 1 key"); - } - keysIterator = keys.listIterator(); - initialized = true; - } - - public void update(ExecutionContext executionContext) { - if(saveState){ - Assert.notNull(executionContext, "ExecutionContext must not be null"); - if(getCurrentKey() != null){ - keyGenerator.saveState(getCurrentKey(), executionContext); - } - } - } - - public void afterPropertiesSet() throws Exception { - Assert.notNull(keyGenerator, "The KeyGenerator must not be null."); - } - - /** - * Set the key generation strategy to use for this input source. - * - * @param keyGenerator - */ - public void setKeyGenerator(KeyGenerator keyGenerator) { - this.keyGenerator = keyGenerator; - } - - protected void transactionCommitted() { - mark(); - } - - protected void transactionRolledBack() { - reset(); - } - - /** - * Mark is supported as long as this {@link ItemStream} is used in a - * single-threaded environment. The state backing the mark is a single - * counter, keeping track of the current position, so multiple threads - * cannot be accommodated. - * - * @see org.springframework.batch.item.ItemReader#mark() - */ - public void mark() { - lastCommitIndex = currentIndex; - } - - /* - * (non-Javadoc) - * - * @see org.springframework.batch.io.support.AbstractTransactionalIoSource#reset(org.springframework.batch.item.ExecutionContext) - */ - public void reset() { - keysIterator = keys.listIterator(lastCommitIndex); - } - - public void setSaveState(boolean saveState) { - this.saveState = saveState; - } -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.io.driving; + +import java.util.Iterator; +import java.util.List; + +import org.springframework.batch.item.ExecutionContext; +import org.springframework.batch.item.ItemReader; +import org.springframework.batch.item.ItemStream; +import org.springframework.batch.item.exception.NoWorkFoundException; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.util.Assert; + +/** + *

+ * Convenience class for driving query input sources. Input Sources of this type + * use a 'driving query' to return back a list of keys. Upon each call to read, + * a new key is returned. To use the input source, inject a key generation + * strategy. + *

+ * + *

+ * Mutability: Because this base class cannot guarantee that the keys returned + * by subclasses are immutable, care should be taken to not modify a key value. + * Doing so would cause issues if a rollback occurs. For example, if a call to + * read() is made, and the returned key is modified, a rollback will cause the + * next call to read() to return the same object that was originally returned, + * since there is no way to create a defensive copy, and re-querying the + * database for all the keys would be too resource intensive. + *

+ * + * + * @author Lucas Ward + * @since 1.0 + */ +public class DrivingQueryItemReader implements ItemReader, InitializingBean, + ItemStream { + + private boolean initialized = false; + + private List keys; + + private Iterator keysIterator; + + private int currentIndex = 0; + + private int lastCommitIndex = 0; + + private KeyGenerator keyGenerator; + + private boolean saveState = false; + + public DrivingQueryItemReader() { + + } + + /** + * Initialize the input source with the provided keys list. + * + * @param keys + */ + public DrivingQueryItemReader(List keys) { + this.keys = keys; + this.keysIterator = keys.iterator(); + } + + /** + * Return the next key in the List. If the ItemReader has not been + * initialized yet, then {@link AbstractDrivingQueryItemReader.open()} will + * be called. + * + * @return next key in the list if not index is not at the last element, + * null otherwise. + */ + public Object read() { + if (!initialized) { + open(new ExecutionContext()); + } + + if (keysIterator.hasNext()) { + currentIndex++; + return keysIterator.next(); + } + + return null; + } + + /** + * Get the current key. This method will return the same object returned by + * the last read() method. If the ItemReader hasn't been initialized yet, + * then null will be returned. + * + * @return the current key. + */ + protected Object getCurrentKey() { + if (initialized) { + return keys.get(currentIndex - 1); + } + + return null; + } + + /** + * Close the resource by setting the list of keys to null, allowing them to + * be garbage collected. + */ + public void close(ExecutionContext executionContext) { + initialized = false; + currentIndex = 0; + lastCommitIndex = 0; + keys = null; + keysIterator = null; + } + + /** + * Initialize the input source by delegating to the subclass in order to + * retrieve the keys. The input source will also be registered with the + * {@link BatchTransactionSynchronizationManager} in order to ensure it is + * notified about commits and rollbacks. + * + * @throws IllegalStateException if the keys list is null or initialized is + * true. + */ + public void open(ExecutionContext executionContext) { + + Assert.state(keys == null && !initialized, "Cannot open an already opened input source" + + ", call close() first."); + keys = keyGenerator.retrieveKeys(executionContext); + if(keys == null || keys.size() == 0){ + throw new NoWorkFoundException("KeyGenerator must return at least 1 key"); + } + keysIterator = keys.listIterator(); + initialized = true; + } + + public void update(ExecutionContext executionContext) { + if(saveState){ + Assert.notNull(executionContext, "ExecutionContext must not be null"); + if(getCurrentKey() != null){ + keyGenerator.saveState(getCurrentKey(), executionContext); + } + } + } + + public void afterPropertiesSet() throws Exception { + Assert.notNull(keyGenerator, "The KeyGenerator must not be null."); + } + + /** + * Set the key generation strategy to use for this input source. + * + * @param keyGenerator + */ + public void setKeyGenerator(KeyGenerator keyGenerator) { + this.keyGenerator = keyGenerator; + } + + protected void transactionCommitted() { + mark(); + } + + protected void transactionRolledBack() { + reset(); + } + + /** + * Mark is supported as long as this {@link ItemStream} is used in a + * single-threaded environment. The state backing the mark is a single + * counter, keeping track of the current position, so multiple threads + * cannot be accommodated. + * + * @see org.springframework.batch.item.ItemReader#mark() + */ + public void mark() { + lastCommitIndex = currentIndex; + } + + /* + * (non-Javadoc) + * + * @see org.springframework.batch.io.support.AbstractTransactionalIoSource#reset(org.springframework.batch.item.ExecutionContext) + */ + public void reset() { + keysIterator = keys.listIterator(lastCommitIndex); + } + + public void setSaveState(boolean saveState) { + this.saveState = saveState; + } +} diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/driving/IbatisDrivingQueryItemReader.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/driving/IbatisDrivingQueryItemReader.java index b33117e288..7e761caed0 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/driving/IbatisDrivingQueryItemReader.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/driving/IbatisDrivingQueryItemReader.java @@ -1,67 +1,67 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.io.driving; - -import org.springframework.batch.io.driving.support.IbatisKeyGenerator; -import org.springframework.orm.ibatis.SqlMapClientTemplate; - -import com.ibatis.sqlmap.client.SqlMapClient; - -/** - * Extension of {@link DrivingQueryItemReader} that maps keys to - * objects. An iBatis query id must be set to map and return each 'detail record'. - * - * @author Lucas Ward - * @see IbatisKeyGenerator - */ -public class IbatisDrivingQueryItemReader extends DrivingQueryItemReader { - - private String detailsQueryId; - - private SqlMapClientTemplate sqlMapClientTemplate; - - /** - * Overridden read() that uses the returned key as arguments to the details query. - * - * @see org.springframework.batch.io.driving.DrivingQueryItemReader#read() - */ - public Object read() { - Object key = super.read(); - if (key==null) { - return null; - } - return sqlMapClientTemplate.queryForObject(detailsQueryId, key); - } - - /** - * @param detailsQueryId id of the iBATIS select statement that will used - * to retrieve an object for a single primary key from the list - * returned by driving query - */ - public void setDetailsQueryId(String detailsQueryId) { - this.detailsQueryId = detailsQueryId; - } - - /** - * Set the {@link SqlMapClientTemplate} to use for this input source. - * - * @param sqlMapClientTemplate - */ - public void setSqlMapClient( - SqlMapClient sqlMapClient) { - this.sqlMapClientTemplate = new SqlMapClientTemplate(sqlMapClient); - } -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.io.driving; + +import org.springframework.batch.io.driving.support.IbatisKeyGenerator; +import org.springframework.orm.ibatis.SqlMapClientTemplate; + +import com.ibatis.sqlmap.client.SqlMapClient; + +/** + * Extension of {@link DrivingQueryItemReader} that maps keys to + * objects. An iBatis query id must be set to map and return each 'detail record'. + * + * @author Lucas Ward + * @see IbatisKeyGenerator + */ +public class IbatisDrivingQueryItemReader extends DrivingQueryItemReader { + + private String detailsQueryId; + + private SqlMapClientTemplate sqlMapClientTemplate; + + /** + * Overridden read() that uses the returned key as arguments to the details query. + * + * @see org.springframework.batch.io.driving.DrivingQueryItemReader#read() + */ + public Object read() { + Object key = super.read(); + if (key==null) { + return null; + } + return sqlMapClientTemplate.queryForObject(detailsQueryId, key); + } + + /** + * @param detailsQueryId id of the iBATIS select statement that will used + * to retrieve an object for a single primary key from the list + * returned by driving query + */ + public void setDetailsQueryId(String detailsQueryId) { + this.detailsQueryId = detailsQueryId; + } + + /** + * Set the {@link SqlMapClientTemplate} to use for this input source. + * + * @param sqlMapClientTemplate + */ + public void setSqlMapClient( + SqlMapClient sqlMapClient) { + this.sqlMapClientTemplate = new SqlMapClientTemplate(sqlMapClient); + } +} diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/driving/support/ExecutionContextRowMapper.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/driving/support/ExecutionContextRowMapper.java index 991c39e34b..d03efa9590 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/driving/support/ExecutionContextRowMapper.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/driving/support/ExecutionContextRowMapper.java @@ -1,53 +1,53 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.io.driving.support; - -import org.springframework.batch.item.ExecutionContext; -import org.springframework.jdbc.core.PreparedStatementSetter; -import org.springframework.jdbc.core.RowMapper; - -/** - * {@link ExecutionContextRowMapper} extends the standard {@link RowMapper} interface to provide for - * converting an object returned from a RowMapper to {@link ExecutionContext} and back again. One - * of the most common use cases for this type of functionality is the DrivingQuery approach - * to sql processing. Using a {@link ExecutionContextRowMapper}, developers can create each unique key - * to suite their specific needs, and also describe how such a key would be converted to - * {@link ExecutionContext}, so that it can be serialized and stored. - * - * @author Lucas Ward - * @see RowMapper - * @since 1.0 - */ -public interface ExecutionContextRowMapper extends RowMapper { - - /** - * Given the provided composite key, return a {@link ExecutionContext} representation. - * - * @param key - * @return ExecutionContext representing the composite key. - * @throws IllegalArgumentException if key is null or of an unsupported type. - */ - public void mapKeys(Object key, ExecutionContext executionContext); - - /** - * Given the provided restart data, return a PreparedStatementSeter that can - * be used as parameters to a JdbcTemplate. - * - * @param executionContext - * @return an array of objects that can be used as arguments to a JdbcTemplate. - */ - public PreparedStatementSetter createSetter(ExecutionContext executionContext); -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.io.driving.support; + +import org.springframework.batch.item.ExecutionContext; +import org.springframework.jdbc.core.PreparedStatementSetter; +import org.springframework.jdbc.core.RowMapper; + +/** + * {@link ExecutionContextRowMapper} extends the standard {@link RowMapper} interface to provide for + * converting an object returned from a RowMapper to {@link ExecutionContext} and back again. One + * of the most common use cases for this type of functionality is the DrivingQuery approach + * to sql processing. Using a {@link ExecutionContextRowMapper}, developers can create each unique key + * to suite their specific needs, and also describe how such a key would be converted to + * {@link ExecutionContext}, so that it can be serialized and stored. + * + * @author Lucas Ward + * @see RowMapper + * @since 1.0 + */ +public interface ExecutionContextRowMapper extends RowMapper { + + /** + * Given the provided composite key, return a {@link ExecutionContext} representation. + * + * @param key + * @return ExecutionContext representing the composite key. + * @throws IllegalArgumentException if key is null or of an unsupported type. + */ + public void mapKeys(Object key, ExecutionContext executionContext); + + /** + * Given the provided restart data, return a PreparedStatementSeter that can + * be used as parameters to a JdbcTemplate. + * + * @param executionContext + * @return an array of objects that can be used as arguments to a JdbcTemplate. + */ + public PreparedStatementSetter createSetter(ExecutionContext executionContext); +} diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/driving/support/IbatisKeyGenerator.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/driving/support/IbatisKeyGenerator.java index ac975fd17d..7bb48de116 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/driving/support/IbatisKeyGenerator.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/driving/support/IbatisKeyGenerator.java @@ -1,101 +1,101 @@ -package org.springframework.batch.io.driving.support; - -import java.util.List; - -import org.springframework.batch.io.driving.DrivingQueryItemReader; -import org.springframework.batch.io.driving.KeyGenerator; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.item.ExecutionContextUserSupport; -import org.springframework.orm.ibatis.SqlMapClientTemplate; -import org.springframework.util.Assert; - -import com.ibatis.sqlmap.client.SqlMapClient; - -/** - * {@link KeyGenerator} based on iBATIS ORM framework. It is functionally - * similar to {@link SingleColumnJdbcKeyGenerator} but does not make assumptions - * about the primary key structure. - * - * @author Robert Kasanicky - * @author Lucas Ward - * @see DrivingQueryItemReader - */ -public class IbatisKeyGenerator extends ExecutionContextUserSupport implements KeyGenerator { - - private static final String RESTART_KEY = "key.index"; - - private SqlMapClientTemplate sqlMapClientTemplate; - - private String drivingQuery; - - private String restartQueryId; - - public IbatisKeyGenerator() { - setName(IbatisKeyGenerator.class.getSimpleName()); - } - - /* - * Retrieve the keys using the provided driving query id. - * - * @see org.springframework.batch.io.support.AbstractDrivingQueryItemReader#retrieveKeys() - */ - public List retrieveKeys(ExecutionContext executionContext) { - if (executionContext.containsKey(getKey(RESTART_KEY))) { - Object key = executionContext.getString(getKey(RESTART_KEY)); - return sqlMapClientTemplate.queryForList(restartQueryId, key); - } - else { - return sqlMapClientTemplate.queryForList(drivingQuery); - } - } - - /* - * (non-Javadoc) - * @see org.springframework.batch.io.driving.KeyGenerator#getKeyAsExecutionContext(java.lang.Object) - */ - public void saveState(Object key, ExecutionContext executionContext) { - Assert.notNull(key, "Key must not be null"); - Assert.notNull(executionContext, "ExecutionContext must be null"); - executionContext.putString(getKey(RESTART_KEY), key.toString()); - } - - /* - * (non-Javadoc) - * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet() - */ - public void afterPropertiesSet() throws Exception { - Assert.notNull(sqlMapClientTemplate, "SqlMaperClientTemplate must not be null."); - Assert.hasText(drivingQuery, "The DrivingQuery must not be null or empty."); - } - - /** - * @param sqlMapClient configured iBATIS client - */ - public void setSqlMapClient(SqlMapClient sqlMapClient) { - this.sqlMapClientTemplate = new SqlMapClientTemplate(); - this.sqlMapClientTemplate.setSqlMapClient(sqlMapClient); - } - - /** - * @param drivingQueryId id of the iBATIS select statement that will be used - * to retrieve the list of primary keys - */ - public void setDrivingQueryId(String drivingQueryId) { - this.drivingQuery = drivingQueryId; - } - - /** - * Set the id of the restart query. - * - * @param restartQueryId id of the iBatis select statement that will be used - * to retrieve the list of primary keys after a restart. - */ - public void setRestartQueryId(String restartQueryId) { - this.restartQueryId = restartQueryId; - } - - public final SqlMapClientTemplate getSqlMapClientTemplate() { - return sqlMapClientTemplate; - } - -} +package org.springframework.batch.io.driving.support; + +import java.util.List; + +import org.springframework.batch.io.driving.DrivingQueryItemReader; +import org.springframework.batch.io.driving.KeyGenerator; +import org.springframework.batch.item.ExecutionContext; +import org.springframework.batch.item.ExecutionContextUserSupport; +import org.springframework.orm.ibatis.SqlMapClientTemplate; +import org.springframework.util.Assert; + +import com.ibatis.sqlmap.client.SqlMapClient; + +/** + * {@link KeyGenerator} based on iBATIS ORM framework. It is functionally + * similar to {@link SingleColumnJdbcKeyGenerator} but does not make assumptions + * about the primary key structure. + * + * @author Robert Kasanicky + * @author Lucas Ward + * @see DrivingQueryItemReader + */ +public class IbatisKeyGenerator extends ExecutionContextUserSupport implements KeyGenerator { + + private static final String RESTART_KEY = "key.index"; + + private SqlMapClientTemplate sqlMapClientTemplate; + + private String drivingQuery; + + private String restartQueryId; + + public IbatisKeyGenerator() { + setName(IbatisKeyGenerator.class.getSimpleName()); + } + + /* + * Retrieve the keys using the provided driving query id. + * + * @see org.springframework.batch.io.support.AbstractDrivingQueryItemReader#retrieveKeys() + */ + public List retrieveKeys(ExecutionContext executionContext) { + if (executionContext.containsKey(getKey(RESTART_KEY))) { + Object key = executionContext.getString(getKey(RESTART_KEY)); + return sqlMapClientTemplate.queryForList(restartQueryId, key); + } + else { + return sqlMapClientTemplate.queryForList(drivingQuery); + } + } + + /* + * (non-Javadoc) + * @see org.springframework.batch.io.driving.KeyGenerator#getKeyAsExecutionContext(java.lang.Object) + */ + public void saveState(Object key, ExecutionContext executionContext) { + Assert.notNull(key, "Key must not be null"); + Assert.notNull(executionContext, "ExecutionContext must be null"); + executionContext.putString(getKey(RESTART_KEY), key.toString()); + } + + /* + * (non-Javadoc) + * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet() + */ + public void afterPropertiesSet() throws Exception { + Assert.notNull(sqlMapClientTemplate, "SqlMaperClientTemplate must not be null."); + Assert.hasText(drivingQuery, "The DrivingQuery must not be null or empty."); + } + + /** + * @param sqlMapClient configured iBATIS client + */ + public void setSqlMapClient(SqlMapClient sqlMapClient) { + this.sqlMapClientTemplate = new SqlMapClientTemplate(); + this.sqlMapClientTemplate.setSqlMapClient(sqlMapClient); + } + + /** + * @param drivingQueryId id of the iBATIS select statement that will be used + * to retrieve the list of primary keys + */ + public void setDrivingQueryId(String drivingQueryId) { + this.drivingQuery = drivingQueryId; + } + + /** + * Set the id of the restart query. + * + * @param restartQueryId id of the iBatis select statement that will be used + * to retrieve the list of primary keys after a restart. + */ + public void setRestartQueryId(String restartQueryId) { + this.restartQueryId = restartQueryId; + } + + public final SqlMapClientTemplate getSqlMapClientTemplate() { + return sqlMapClientTemplate; + } + +} diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/driving/support/MultipleColumnJdbcKeyGenerator.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/driving/support/MultipleColumnJdbcKeyGenerator.java index 6ee179627d..adfc38c57c 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/driving/support/MultipleColumnJdbcKeyGenerator.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/driving/support/MultipleColumnJdbcKeyGenerator.java @@ -1,138 +1,138 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.io.driving.support; - -import java.util.List; - -import org.springframework.batch.io.driving.DrivingQueryItemReader; -import org.springframework.batch.io.driving.KeyGenerator; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.util.Assert; -import org.springframework.util.StringUtils; - -/** - *

- * Jdbc implementation of the {@link KeyGenerator} interface that works for - * composite keys. (i.e. keys represented by multiple columns) A sql query to be - * used to return the keys and a {@link ExecutionContextRowMapper} to map each - * row in the resultset to an Object must be set in order to work correctly. - *

- * - * @author Lucas Ward - * @see DrivingQueryItemReader - * @since 1.0 - */ -public class MultipleColumnJdbcKeyGenerator implements KeyGenerator { - - private JdbcTemplate jdbcTemplate; - - private ExecutionContextRowMapper keyMapper = new ColumnMapExecutionContextRowMapper(); - - private String sql; - - private String restartSql; - - public MultipleColumnJdbcKeyGenerator() { - } - - /** - * Construct a new ItemReader. - * - * @param jdbcTemplate - * @param sql - Sql statement that returns all keys to process. - * @param keyMapper - RowMapper that maps each row of the ResultSet to an - * object. - */ - public MultipleColumnJdbcKeyGenerator(JdbcTemplate jdbcTemplate, String sql) { - this(); - Assert.notNull(jdbcTemplate, "The JdbcTemplate must not be null."); - Assert.hasText(sql, "The DrivingQuery must not be null or empty."); - Assert.notNull(keyMapper, "The key RowMapper must not be null."); - this.jdbcTemplate = jdbcTemplate; - this.sql = sql; - } - - /* - * (non-Javadoc) - * @see org.springframework.batch.io.sql.scratch.AbstractDrivingQueryItemReader#retrieveKeys() - */ - public List retrieveKeys(ExecutionContext executionContext) { - - Assert.state(keyMapper != null, "KeyMapper must not be null."); - Assert.state(StringUtils.hasText(restartSql), "The RestartQuery must not be null or empty" - + " in order to restart."); - - if (executionContext.size() > 0) { - return jdbcTemplate.query(restartSql, keyMapper.createSetter(executionContext), keyMapper); - } - else { - return jdbcTemplate.query(sql, keyMapper); - } - } - - /* - * (non-Javadoc) - * @see org.springframework.batch.io.driving.KeyGenerator#getKeyAsExecutionContext(java.lang.Object) - */ - public void saveState(Object key, ExecutionContext executionContext) { - Assert.state(keyMapper != null, "Key mapper must not be null."); - keyMapper.mapKeys(key, executionContext); - } - - /** - * Set the query to use to retrieve keys in order to restore the previous - * state for restart. - * - * @param restartQuery - */ - public void setRestartSql(String restartQuery) { - this.restartSql = restartQuery; - } - - /* - * (non-Javadoc) - * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet() - */ - public void afterPropertiesSet() throws Exception { - Assert.notNull(jdbcTemplate, "The JdbcTemplate must not be null."); - Assert.hasText(sql, "The DrivingQuery must not be null or empty."); - Assert.notNull(keyMapper, "The key RowMapper must not be null."); - } - - /** - * Set the {@link ExecutionContextRowMapper} to be used to map a resultset - * to keys. - * - * @param keyMapper - */ - public void setKeyMapper(ExecutionContextRowMapper keyMapper) { - this.keyMapper = keyMapper; - } - - /** - * Set the sql statement used to generate the keys list. - * - * @param sql - */ - public void setSql(String sql) { - this.sql = sql; - } - - public void setJdbcTemplate(JdbcTemplate jdbcTemplate) { - this.jdbcTemplate = jdbcTemplate; - } -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.io.driving.support; + +import java.util.List; + +import org.springframework.batch.io.driving.DrivingQueryItemReader; +import org.springframework.batch.io.driving.KeyGenerator; +import org.springframework.batch.item.ExecutionContext; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.util.Assert; +import org.springframework.util.StringUtils; + +/** + *

+ * Jdbc implementation of the {@link KeyGenerator} interface that works for + * composite keys. (i.e. keys represented by multiple columns) A sql query to be + * used to return the keys and a {@link ExecutionContextRowMapper} to map each + * row in the resultset to an Object must be set in order to work correctly. + *

+ * + * @author Lucas Ward + * @see DrivingQueryItemReader + * @since 1.0 + */ +public class MultipleColumnJdbcKeyGenerator implements KeyGenerator { + + private JdbcTemplate jdbcTemplate; + + private ExecutionContextRowMapper keyMapper = new ColumnMapExecutionContextRowMapper(); + + private String sql; + + private String restartSql; + + public MultipleColumnJdbcKeyGenerator() { + } + + /** + * Construct a new ItemReader. + * + * @param jdbcTemplate + * @param sql - Sql statement that returns all keys to process. + * @param keyMapper - RowMapper that maps each row of the ResultSet to an + * object. + */ + public MultipleColumnJdbcKeyGenerator(JdbcTemplate jdbcTemplate, String sql) { + this(); + Assert.notNull(jdbcTemplate, "The JdbcTemplate must not be null."); + Assert.hasText(sql, "The DrivingQuery must not be null or empty."); + Assert.notNull(keyMapper, "The key RowMapper must not be null."); + this.jdbcTemplate = jdbcTemplate; + this.sql = sql; + } + + /* + * (non-Javadoc) + * @see org.springframework.batch.io.sql.scratch.AbstractDrivingQueryItemReader#retrieveKeys() + */ + public List retrieveKeys(ExecutionContext executionContext) { + + Assert.state(keyMapper != null, "KeyMapper must not be null."); + Assert.state(StringUtils.hasText(restartSql), "The RestartQuery must not be null or empty" + + " in order to restart."); + + if (executionContext.size() > 0) { + return jdbcTemplate.query(restartSql, keyMapper.createSetter(executionContext), keyMapper); + } + else { + return jdbcTemplate.query(sql, keyMapper); + } + } + + /* + * (non-Javadoc) + * @see org.springframework.batch.io.driving.KeyGenerator#getKeyAsExecutionContext(java.lang.Object) + */ + public void saveState(Object key, ExecutionContext executionContext) { + Assert.state(keyMapper != null, "Key mapper must not be null."); + keyMapper.mapKeys(key, executionContext); + } + + /** + * Set the query to use to retrieve keys in order to restore the previous + * state for restart. + * + * @param restartQuery + */ + public void setRestartSql(String restartQuery) { + this.restartSql = restartQuery; + } + + /* + * (non-Javadoc) + * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet() + */ + public void afterPropertiesSet() throws Exception { + Assert.notNull(jdbcTemplate, "The JdbcTemplate must not be null."); + Assert.hasText(sql, "The DrivingQuery must not be null or empty."); + Assert.notNull(keyMapper, "The key RowMapper must not be null."); + } + + /** + * Set the {@link ExecutionContextRowMapper} to be used to map a resultset + * to keys. + * + * @param keyMapper + */ + public void setKeyMapper(ExecutionContextRowMapper keyMapper) { + this.keyMapper = keyMapper; + } + + /** + * Set the sql statement used to generate the keys list. + * + * @param sql + */ + public void setSql(String sql) { + this.sql = sql; + } + + public void setJdbcTemplate(JdbcTemplate jdbcTemplate) { + this.jdbcTemplate = jdbcTemplate; + } +} diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/driving/support/SingleColumnJdbcKeyGenerator.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/driving/support/SingleColumnJdbcKeyGenerator.java index 40dbef2913..2b7f0bb563 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/driving/support/SingleColumnJdbcKeyGenerator.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/driving/support/SingleColumnJdbcKeyGenerator.java @@ -1,152 +1,152 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.io.driving.support; - -import java.util.List; - -import org.springframework.batch.io.driving.KeyGenerator; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.item.ExecutionContextUserSupport; -import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.jdbc.core.RowMapper; -import org.springframework.jdbc.core.SingleColumnRowMapper; -import org.springframework.util.Assert; -import org.springframework.util.StringUtils; - -/** - *

- * Jdbc {@link KeyGenerator} implementation that only works for a single column - * key. A sql query must be passed in which will be used to return a list of - * keys. Each key will be mapped by a {@link RowMapper} that returns a mapped - * key. By default, the {@link SingleColumnRowMapper} is used, and will convert - * keys into well known types at runtime. It is extremely important to note that - * only one column should be mapped to an object and returned as a key. If - * multiple columns are returned as a key in this strategy, then restart will - * not function properly. Instead a strategy that supports keys comprised of - * multiple columns should be used. - * - *

- * Restartability: Because the key is only one column, restart is made much more - * simple. Before each commit, the last processed key is returned to be stored - * as restart data. Upon restart, that same key is given back to restore from, - * using a separate 'RestartQuery'. This means that only the keys remaining to - * be processed are returned, rather than returning the original list of keys - * and iterating forward to that last committed point. - *

- * - * @author Lucas Ward - * @since 1.0 - */ -public class SingleColumnJdbcKeyGenerator extends ExecutionContextUserSupport implements KeyGenerator { - - private static final String RESTART_KEY = "key"; - - private JdbcTemplate jdbcTemplate; - - private String sql; - - private String restartSql; - - private RowMapper keyMapper = new SingleColumnRowMapper(); - - public SingleColumnJdbcKeyGenerator() { - setName(SingleColumnJdbcKeyGenerator.class.getSimpleName()); - } - - /** - * Constructs a new instance using the provided jdbcTemplate and string - * representing the sql statement that should be used to retrieve keys. - * - * @param jdbcTemplate - * @param sql - * @throws IllegalArgumentException if jdbcTemplate is null. - * @throws IllegalArgumentException if sql string is empty or null. - */ - public SingleColumnJdbcKeyGenerator(JdbcTemplate jdbcTemplate, String sql) { - this(); - Assert.notNull(jdbcTemplate, "JdbcTemplate must not be null."); - Assert.hasText(sql, "The sql statement must not be null or empty."); - this.jdbcTemplate = jdbcTemplate; - this.sql = sql; - } - - /* - * (non-Javadoc) - * @see org.springframework.batch.io.driving.KeyGenerationStrategy#retrieveKeys() - */ - public List retrieveKeys(ExecutionContext executionContext) { - - Assert.notNull(executionContext, "The restart data must not be null."); - - if (executionContext.containsKey(RESTART_KEY)) { - Assert.state(StringUtils.hasText(restartSql), "The RestartQuery must not be null or empty" - + " in order to restart."); - return jdbcTemplate.query(restartSql, new Object[] { executionContext.getString(RESTART_KEY) }, keyMapper); - } - else{ - return jdbcTemplate.query(sql, keyMapper); - } - } - - /** - * Get the restart data representing the last processed key. - * - * @see KeyGenerator#saveState(Object) - * @throws IllegalArgumentException if key is null. - */ - public void saveState(Object key, ExecutionContext executionContext) { - Assert.notNull(key, "The key must not be null."); - executionContext.putString(RESTART_KEY, key.toString()); - } - - /* - * (non-Javadoc) - * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet() - */ - public void afterPropertiesSet() throws Exception { - Assert.notNull(jdbcTemplate, "JdbcTemplate must not be null."); - Assert.hasText(sql, "The DrivingQuery must not be null or empty."); - } - - /** - * Set the {@link RowMapper} to be used to map each key to an object. - * - * @param keyMapper - */ - public void setKeyMapper(RowMapper keyMapper) { - this.keyMapper = keyMapper; - } - - /** - * Set the SQL query to be used to return the remaining keys to be - * processed. - * - * @param restartSql - */ - public void setRestartSql(String restartSql) { - this.restartSql = restartSql; - } - - /** - * Set the SQL statement to be used to return the keys to be processed. - * - * @param sql - */ - public void setSql(String sql) { - this.sql = sql; - } - -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.io.driving.support; + +import java.util.List; + +import org.springframework.batch.io.driving.KeyGenerator; +import org.springframework.batch.item.ExecutionContext; +import org.springframework.batch.item.ExecutionContextUserSupport; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.RowMapper; +import org.springframework.jdbc.core.SingleColumnRowMapper; +import org.springframework.util.Assert; +import org.springframework.util.StringUtils; + +/** + *

+ * Jdbc {@link KeyGenerator} implementation that only works for a single column + * key. A sql query must be passed in which will be used to return a list of + * keys. Each key will be mapped by a {@link RowMapper} that returns a mapped + * key. By default, the {@link SingleColumnRowMapper} is used, and will convert + * keys into well known types at runtime. It is extremely important to note that + * only one column should be mapped to an object and returned as a key. If + * multiple columns are returned as a key in this strategy, then restart will + * not function properly. Instead a strategy that supports keys comprised of + * multiple columns should be used. + * + *

+ * Restartability: Because the key is only one column, restart is made much more + * simple. Before each commit, the last processed key is returned to be stored + * as restart data. Upon restart, that same key is given back to restore from, + * using a separate 'RestartQuery'. This means that only the keys remaining to + * be processed are returned, rather than returning the original list of keys + * and iterating forward to that last committed point. + *

+ * + * @author Lucas Ward + * @since 1.0 + */ +public class SingleColumnJdbcKeyGenerator extends ExecutionContextUserSupport implements KeyGenerator { + + private static final String RESTART_KEY = "key"; + + private JdbcTemplate jdbcTemplate; + + private String sql; + + private String restartSql; + + private RowMapper keyMapper = new SingleColumnRowMapper(); + + public SingleColumnJdbcKeyGenerator() { + setName(SingleColumnJdbcKeyGenerator.class.getSimpleName()); + } + + /** + * Constructs a new instance using the provided jdbcTemplate and string + * representing the sql statement that should be used to retrieve keys. + * + * @param jdbcTemplate + * @param sql + * @throws IllegalArgumentException if jdbcTemplate is null. + * @throws IllegalArgumentException if sql string is empty or null. + */ + public SingleColumnJdbcKeyGenerator(JdbcTemplate jdbcTemplate, String sql) { + this(); + Assert.notNull(jdbcTemplate, "JdbcTemplate must not be null."); + Assert.hasText(sql, "The sql statement must not be null or empty."); + this.jdbcTemplate = jdbcTemplate; + this.sql = sql; + } + + /* + * (non-Javadoc) + * @see org.springframework.batch.io.driving.KeyGenerationStrategy#retrieveKeys() + */ + public List retrieveKeys(ExecutionContext executionContext) { + + Assert.notNull(executionContext, "The restart data must not be null."); + + if (executionContext.containsKey(RESTART_KEY)) { + Assert.state(StringUtils.hasText(restartSql), "The RestartQuery must not be null or empty" + + " in order to restart."); + return jdbcTemplate.query(restartSql, new Object[] { executionContext.getString(RESTART_KEY) }, keyMapper); + } + else{ + return jdbcTemplate.query(sql, keyMapper); + } + } + + /** + * Get the restart data representing the last processed key. + * + * @see KeyGenerator#saveState(Object) + * @throws IllegalArgumentException if key is null. + */ + public void saveState(Object key, ExecutionContext executionContext) { + Assert.notNull(key, "The key must not be null."); + executionContext.putString(RESTART_KEY, key.toString()); + } + + /* + * (non-Javadoc) + * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet() + */ + public void afterPropertiesSet() throws Exception { + Assert.notNull(jdbcTemplate, "JdbcTemplate must not be null."); + Assert.hasText(sql, "The DrivingQuery must not be null or empty."); + } + + /** + * Set the {@link RowMapper} to be used to map each key to an object. + * + * @param keyMapper + */ + public void setKeyMapper(RowMapper keyMapper) { + this.keyMapper = keyMapper; + } + + /** + * Set the SQL query to be used to return the remaining keys to be + * processed. + * + * @param restartSql + */ + public void setRestartSql(String restartSql) { + this.restartSql = restartSql; + } + + /** + * Set the SQL statement to be used to return the keys to be processed. + * + * @param sql + */ + public void setSql(String sql) { + this.sql = sql; + } + +} diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/exception/DynamicMethodInvocationException.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/exception/DynamicMethodInvocationException.java index 495995b297..f47b9a7e60 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/exception/DynamicMethodInvocationException.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/exception/DynamicMethodInvocationException.java @@ -1,23 +1,23 @@ -package org.springframework.batch.io.exception; - -import org.springframework.util.MethodInvoker; - -/** - * Indicates an error has been encountered - * while trying to dynamically call a method e.g. using {@link MethodInvoker}. - * - * @author Robert Kasanicky - */ -public class DynamicMethodInvocationException extends RuntimeException { - - //generated value - private static final long serialVersionUID = -6056786139731564040L; - - public DynamicMethodInvocationException(Throwable cause){ - super(cause); - } - - public DynamicMethodInvocationException(String message, Throwable cause) { - super(message, cause); - } -} +package org.springframework.batch.io.exception; + +import org.springframework.util.MethodInvoker; + +/** + * Indicates an error has been encountered + * while trying to dynamically call a method e.g. using {@link MethodInvoker}. + * + * @author Robert Kasanicky + */ +public class DynamicMethodInvocationException extends RuntimeException { + + //generated value + private static final long serialVersionUID = -6056786139731564040L; + + public DynamicMethodInvocationException(Throwable cause){ + super(cause); + } + + public DynamicMethodInvocationException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/exception/FlatFileParsingException.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/exception/FlatFileParsingException.java index 449e8cedaf..7a3965ff2e 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/exception/FlatFileParsingException.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/exception/FlatFileParsingException.java @@ -1,64 +1,64 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.io.exception; - -/** - * Exception thrown when errors are encountered - * parsing flat files. The original input, typically - * a line, can be passed in, so that latter catches - * can write out the original input to a log, or - * an error table. - * - * @author Lucas Ward - * - */ -public class FlatFileParsingException extends ParsingException { - - private static final long serialVersionUID = 2529197834044942724L; - - private String input; - private int lineNumber; - - public FlatFileParsingException(String message, String input) { - super(message); - this.input = input; - } - - public FlatFileParsingException(String message, String input, int lineNumber) { - super(message); - this.input = input; - this.lineNumber = lineNumber; - } - - public FlatFileParsingException(String message, Throwable cause, String input, int lineNumber) { - super(message, cause); - this.input = input; - this.lineNumber = lineNumber; - } - - public FlatFileParsingException(Throwable cause, String input) { - super(cause); - this.input = input; - } - - public String getInput() { - return input; - } - - public int getLineNumber() { - return lineNumber; - } -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.io.exception; + +/** + * Exception thrown when errors are encountered + * parsing flat files. The original input, typically + * a line, can be passed in, so that latter catches + * can write out the original input to a log, or + * an error table. + * + * @author Lucas Ward + * + */ +public class FlatFileParsingException extends ParsingException { + + private static final long serialVersionUID = 2529197834044942724L; + + private String input; + private int lineNumber; + + public FlatFileParsingException(String message, String input) { + super(message); + this.input = input; + } + + public FlatFileParsingException(String message, String input, int lineNumber) { + super(message); + this.input = input; + this.lineNumber = lineNumber; + } + + public FlatFileParsingException(String message, Throwable cause, String input, int lineNumber) { + super(message, cause); + this.input = input; + this.lineNumber = lineNumber; + } + + public FlatFileParsingException(Throwable cause, String input) { + super(cause); + this.input = input; + } + + public String getInput() { + return input; + } + + public int getLineNumber() { + return lineNumber; + } +} diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/exception/ParsingException.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/exception/ParsingException.java index cdaf1659cf..85e9f5d8d0 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/exception/ParsingException.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/exception/ParsingException.java @@ -1,40 +1,40 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.io.exception; - -/** - * Exception indicating that an error has been encountered - * parsing io, typically from a file. - * - * @author Lucas Ward - * - */ -public class ParsingException extends RuntimeException { - - private static final long serialVersionUID = 2953386084409312312L; - - public ParsingException(String message) { - super(message); - } - - public ParsingException(String message, Throwable cause) { - super(message, cause); - } - - public ParsingException(Throwable cause) { - super(cause); - } -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.io.exception; + +/** + * Exception indicating that an error has been encountered + * parsing io, typically from a file. + * + * @author Lucas Ward + * + */ +public class ParsingException extends RuntimeException { + + private static final long serialVersionUID = 2953386084409312312L; + + public ParsingException(String message) { + super(message); + } + + public ParsingException(String message, Throwable cause) { + super(message, cause); + } + + public ParsingException(Throwable cause) { + super(cause); + } +} diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/file/FlatFileItemWriter.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/file/FlatFileItemWriter.java index e6faebf09a..7e9f741873 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/file/FlatFileItemWriter.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/file/FlatFileItemWriter.java @@ -1,489 +1,489 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.batch.io.file; - -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.nio.channels.Channels; -import java.nio.channels.FileChannel; -import java.nio.charset.UnsupportedCharsetException; - -import org.springframework.batch.io.exception.ConfigurationException; -import org.springframework.batch.io.exception.InfrastructureException; -import org.springframework.batch.io.file.mapping.FieldSet; -import org.springframework.batch.io.file.mapping.FieldSetCreator; -import org.springframework.batch.io.file.transform.DelimitedLineAggregator; -import org.springframework.batch.io.file.transform.LineAggregator; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.item.ExecutionContextUserSupport; -import org.springframework.batch.item.ItemStream; -import org.springframework.batch.item.ItemWriter; -import org.springframework.batch.item.exception.ClearFailedException; -import org.springframework.batch.item.exception.FlushFailedException; -import org.springframework.batch.item.exception.ResetFailedException; -import org.springframework.batch.item.exception.StreamException; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.core.io.Resource; -import org.springframework.dao.DataAccessResourceFailureException; -import org.springframework.util.Assert; - -/** - * This class is an output target that writes data to a file or stream. The - * writer also provides restart, statistics and transaction features by - * implementing corresponding interfaces where possible (with a file). The - * location of the file is defined by a {@link Resource} and must represent a - * writable file.
- * - * Uses buffered writer to improve performance.
- * - * Use {@link #write(String)} method to output a line to an item writer. - * - *

- * This class will be updated in the future to use a buffering approach to - * handling transactions, rather than outputting directly to the file and - * truncating on rollback - *

- * - * @author Waseem Malik - * @author Tomas Slanina - * @author Robert Kasanicky - * @author Dave Syer - */ -public class FlatFileItemWriter extends ExecutionContextUserSupport implements ItemWriter, ItemStream, - InitializingBean { - - private static final String LINE_SEPARATOR = System.getProperty("line.separator"); - - private static final String WRITTEN_STATISTICS_NAME = "written"; - - private static final String RESTART_COUNT_STATISTICS_NAME = "restart.count"; - - private static final String RESTART_DATA_NAME = "current.count"; - - private Resource resource; - - private OutputState state = null; - - private LineAggregator lineAggregator = new DelimitedLineAggregator(); - - private FieldSetCreator fieldSetCreator; - - public FlatFileItemWriter() { - setName(FlatFileItemWriter.class.getSimpleName()); - } - - /** - * Assert that mandatory properties (resource) are set. - * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet() - */ - public void afterPropertiesSet() throws Exception { - Assert.notNull(resource, "The resource must be set"); - Assert.notNull(fieldSetCreator, "A FieldSetUnmapper must be provided."); - File file = resource.getFile(); - Assert.state(!file.exists() || file.canWrite(), "Resource is not writable: [" + resource + "]"); - } - - /** - * Public setter for the {@link LineAggregator}. This will be used to - * translate a {@link FieldSet} into a line for output. - * - * @param lineAggregator the {@link LineAggregator} to set - */ - public void setLineAggregator(LineAggregator lineAggregator) { - this.lineAggregator = lineAggregator; - } - - /** - * Public setter for the {@link FieldSetCreator}. This will be used to - * transform the item into a {@link FieldSet} before it is aggregated by the - * {@link LineAggregator}. - * - * @param fieldSetCreator the {@link FieldSetCreator} to set - */ - public void setFieldSetUnmapper(FieldSetCreator fieldSetCreator) { - this.fieldSetCreator = fieldSetCreator; - } - - /** - * Setter for resource. Represents a file that can be written. - * - * @param resource - */ - public void setResource(Resource resource) { - this.resource = resource; - } - - /** - * Writes out a string followed by a "new line", where the format of the new - * line separator is determined by the underlying operating system. If the - * input is not a String and a converter is available the converter will be - * applied and then this method recursively called with the result. If the - * input is an array or collection each value will be written to a separate - * line (recursively calling this method for each value). If no converter is - * supplied the input object's toString method will be used.
- * - * @param data Object (a String or Object that can be converted) to be - * written to output stream - * @throws Exception if the transformer or file output fail - */ - public void write(Object data) throws Exception { - FieldSet fieldSet = fieldSetCreator.mapItem(data); - getOutputState().write(lineAggregator.aggregate(fieldSet) + LINE_SEPARATOR); - } - - /** - * @see ResourceLifecycle#close(ExecutionContext) - */ - public void close(ExecutionContext executionContext) { - if (state != null) { - getOutputState().close(); - state = null; - } - } - - /** - * Sets encoding for output template. - */ - public void setEncoding(String newEncoding) { - getOutputState().setEncoding(newEncoding); - } - - /** - * Sets buffer size for output template - */ - public void setBufferSize(int newSize) { - getOutputState().setBufferSize(newSize); - } - - /** - * @param shouldDeleteIfExists the shouldDeleteIfExists to set - */ - public void setShouldDeleteIfExists(boolean shouldDeleteIfExists) { - getOutputState().setShouldDeleteIfExists(shouldDeleteIfExists); - } - - /** - * Initialize the Output Template. - * @see ResourceLifecycle#open() - */ - public void open(ExecutionContext executionContext) { - OutputState outputState = getOutputState(); - if(executionContext.containsKey(getKey(RESTART_DATA_NAME))){ - outputState.restoreFrom(executionContext); - } - } - - /** - * @see ItemStream#update(ExecutionContext) - */ - public void update(ExecutionContext executionContext) { - if (state == null) { - throw new StreamException("ItemStream not open or already closed."); - } - Assert.notNull(executionContext, "ExecutionContext must not be null"); - executionContext.putLong(getKey(RESTART_DATA_NAME), state.position()); - executionContext.putLong(getKey(WRITTEN_STATISTICS_NAME), state.linesWritten); - executionContext.putLong(getKey(RESTART_COUNT_STATISTICS_NAME), state.restartCount); - } - - // Returns object representing state. - private OutputState getOutputState() { - if (state == null) { - state = new OutputState(); - } - return (OutputState) state; - } - - /** - * Encapsulates the runtime state of the writer. All state changing - * operations on the writer go through this class. - */ - private class OutputState { - // default encoding for writing to output files - set to UTF-8. - private static final String DEFAULT_CHARSET = "UTF-8"; - - private static final int DEFAULT_BUFFER_SIZE = 2048; - - // The bufferedWriter over the file channel that is actually written - BufferedWriter outputBufferedWriter; - - FileChannel fileChannel; - - // this represents the charset encoding (if any is needed) for the - // output file - String encoding = DEFAULT_CHARSET; - - // Optional write buffer size - int bufferSize = DEFAULT_BUFFER_SIZE; - - boolean restarted = false; - - boolean initialized = false; - - long lastMarkedByteOffsetPosition = 0; - - long linesWritten = 0; - - long restartCount = 0; - - boolean shouldDeleteIfExists = true; - - /** - * Return the byte offset position of the cursor in the output file as a - * long integer. - */ - public long position() { - long pos = 0; - - if (fileChannel == null) { - return 0; - } - - try { - outputBufferedWriter.flush(); - pos = fileChannel.position(); - } - catch (IOException e) { - throw new InfrastructureException("An Error occured while trying to get filechannel position", e); - } - - return pos; - - } - - /** - * @param properties - */ - public void restoreFrom(ExecutionContext executionContext) { - lastMarkedByteOffsetPosition = executionContext.getLong(getKey(RESTART_DATA_NAME)); - restarted = true; - } - - /** - * @param shouldDeleteIfExists2 - */ - public void setShouldDeleteIfExists(boolean shouldDeleteIfExists) { - this.shouldDeleteIfExists = shouldDeleteIfExists; - } - - /** - * @param newSize - */ - public void setBufferSize(int newSize) { - bufferSize = newSize; - } - - /** - * @param newEncoding - */ - public void setEncoding(String newEncoding) { - encoding = newEncoding; - } - - /** - * Close the open resource and reset counters. - */ - public void close() { - initialized = false; - restarted = false; - try { - if (outputBufferedWriter == null) { - return; - } - outputBufferedWriter.close(); - fileChannel.close(); - } - catch (IOException ioe) { - throw new StreamException("Unable to close the the ItemWriter", ioe); - } - } - - /** - * @param data - * @param offset - * @param length - */ - public void write(String line) { - if (!initialized) { - initializeBufferedWriter(); - } - - try { - outputBufferedWriter.write(line); - outputBufferedWriter.flush(); - linesWritten++; - } - catch (IOException e) { - throw new InfrastructureException("An Error occured while trying to write to FlatFileItemWriter", e); - } - } - - /** - * Truncate the output at the last known good point. - */ - public void truncate() { - try { - fileChannel.truncate(lastMarkedByteOffsetPosition); - fileChannel.position(lastMarkedByteOffsetPosition); - } - catch (IOException e) { - throw new InfrastructureException("An Error occured while truncating output file", e); - } - } - - /** - * Mark the current position. - */ - public void mark() { - lastMarkedByteOffsetPosition = this.position(); - } - - /** - * Creates the buffered writer for the output file channel based on - * configuration information. - */ - private void initializeBufferedWriter() { - File file; - - try { - file = resource.getFile(); - - // If the output source was restarted, keep existing file. - // If the output source was not restarted, check following: - // - if the file should be deleted, delete it if it was exiting - // and create blank file, - // - if the file should not be deleted, if it already exists, - // throw an exception, - // - if the file was not existing, create new. - if (!restarted) { - if (file.exists()) { - if (shouldDeleteIfExists) { - file.delete(); - } - else { - throw new StreamException("Resource already exists: " + resource); - } - } - String parent = file.getParent(); - if (parent != null) { - new File(parent).mkdirs(); - } - file.createNewFile(); - } - - } - catch (IOException ioe) { - throw new DataAccessResourceFailureException("Unable to write to file resource: [" + resource + "]", - ioe); - } - - try { - fileChannel = (new FileOutputStream(file.getAbsolutePath(), true)).getChannel(); - } - catch (FileNotFoundException fnfe) { - throw new ConfigurationException("Bad filename property parameter " + file, fnfe); - } - - outputBufferedWriter = getBufferedWriter(fileChannel, encoding, bufferSize); - - // in case of restarting reset position to last commited point - if (restarted) { - this.reset(); - } - - initialized = true; - linesWritten = 0; - } - - /** - * Returns the buffered writer opened to the beginning of the file - * specified by the absolute path name contained in absoluteFileName. - */ - private BufferedWriter getBufferedWriter(FileChannel fileChannel, String encoding, int bufferSize) { - try { - - BufferedWriter outputBufferedWriter = null; - - // If a buffer was requested, allocate. - if (bufferSize > 0) { - outputBufferedWriter = new BufferedWriter(Channels.newWriter(fileChannel, encoding), bufferSize); - } - else { - outputBufferedWriter = new BufferedWriter(Channels.newWriter(fileChannel, encoding)); - } - - return outputBufferedWriter; - } - catch (UnsupportedCharsetException ucse) { - throw new StreamException("Bad encoding configuration for output file " + fileChannel, ucse); - } - } - - /** - * Resets the file writer's current position to the point stored in the - * last marked byte offset position variable. It first checks to make - * sure the current size of the file is not less than the byte position - * to be moved to (if it is, throws an environment exception), then it - * truncates the file to that reset position, and set the cursor to - * start writing at that point. - */ - public void reset() throws InfrastructureException { - checkFileSize(); - getOutputState().truncate(); - } - - /** - * Checks (on setState) to make sure that the current output file's size - * is not smaller than the last saved commit point. If it is, then the - * file has been damaged in some way and whole task must be started over - * again from the beginning. - */ - private void checkFileSize() { - long size = -1; - - try { - outputBufferedWriter.flush(); - size = fileChannel.size(); - } - catch (IOException e) { - throw new InfrastructureException("An Error occured while checking file size", e); - } - - if (size < lastMarkedByteOffsetPosition) { - throw new InfrastructureException("Current file size is smaller than size at last commit"); - } - } - - } - - public void clear() throws ClearFailedException { - try { - getOutputState().reset(); - } - catch (InfrastructureException e) { - throw new ResetFailedException(e); - } - } - - public void flush() throws FlushFailedException { - getOutputState().mark(); - } - -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.batch.io.file; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.nio.channels.Channels; +import java.nio.channels.FileChannel; +import java.nio.charset.UnsupportedCharsetException; + +import org.springframework.batch.io.exception.ConfigurationException; +import org.springframework.batch.io.exception.InfrastructureException; +import org.springframework.batch.io.file.mapping.FieldSet; +import org.springframework.batch.io.file.mapping.FieldSetCreator; +import org.springframework.batch.io.file.transform.DelimitedLineAggregator; +import org.springframework.batch.io.file.transform.LineAggregator; +import org.springframework.batch.item.ExecutionContext; +import org.springframework.batch.item.ExecutionContextUserSupport; +import org.springframework.batch.item.ItemStream; +import org.springframework.batch.item.ItemWriter; +import org.springframework.batch.item.exception.ClearFailedException; +import org.springframework.batch.item.exception.FlushFailedException; +import org.springframework.batch.item.exception.ResetFailedException; +import org.springframework.batch.item.exception.StreamException; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.core.io.Resource; +import org.springframework.dao.DataAccessResourceFailureException; +import org.springframework.util.Assert; + +/** + * This class is an output target that writes data to a file or stream. The + * writer also provides restart, statistics and transaction features by + * implementing corresponding interfaces where possible (with a file). The + * location of the file is defined by a {@link Resource} and must represent a + * writable file.
+ * + * Uses buffered writer to improve performance.
+ * + * Use {@link #write(String)} method to output a line to an item writer. + * + *

+ * This class will be updated in the future to use a buffering approach to + * handling transactions, rather than outputting directly to the file and + * truncating on rollback + *

+ * + * @author Waseem Malik + * @author Tomas Slanina + * @author Robert Kasanicky + * @author Dave Syer + */ +public class FlatFileItemWriter extends ExecutionContextUserSupport implements ItemWriter, ItemStream, + InitializingBean { + + private static final String LINE_SEPARATOR = System.getProperty("line.separator"); + + private static final String WRITTEN_STATISTICS_NAME = "written"; + + private static final String RESTART_COUNT_STATISTICS_NAME = "restart.count"; + + private static final String RESTART_DATA_NAME = "current.count"; + + private Resource resource; + + private OutputState state = null; + + private LineAggregator lineAggregator = new DelimitedLineAggregator(); + + private FieldSetCreator fieldSetCreator; + + public FlatFileItemWriter() { + setName(FlatFileItemWriter.class.getSimpleName()); + } + + /** + * Assert that mandatory properties (resource) are set. + * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet() + */ + public void afterPropertiesSet() throws Exception { + Assert.notNull(resource, "The resource must be set"); + Assert.notNull(fieldSetCreator, "A FieldSetUnmapper must be provided."); + File file = resource.getFile(); + Assert.state(!file.exists() || file.canWrite(), "Resource is not writable: [" + resource + "]"); + } + + /** + * Public setter for the {@link LineAggregator}. This will be used to + * translate a {@link FieldSet} into a line for output. + * + * @param lineAggregator the {@link LineAggregator} to set + */ + public void setLineAggregator(LineAggregator lineAggregator) { + this.lineAggregator = lineAggregator; + } + + /** + * Public setter for the {@link FieldSetCreator}. This will be used to + * transform the item into a {@link FieldSet} before it is aggregated by the + * {@link LineAggregator}. + * + * @param fieldSetCreator the {@link FieldSetCreator} to set + */ + public void setFieldSetUnmapper(FieldSetCreator fieldSetCreator) { + this.fieldSetCreator = fieldSetCreator; + } + + /** + * Setter for resource. Represents a file that can be written. + * + * @param resource + */ + public void setResource(Resource resource) { + this.resource = resource; + } + + /** + * Writes out a string followed by a "new line", where the format of the new + * line separator is determined by the underlying operating system. If the + * input is not a String and a converter is available the converter will be + * applied and then this method recursively called with the result. If the + * input is an array or collection each value will be written to a separate + * line (recursively calling this method for each value). If no converter is + * supplied the input object's toString method will be used.
+ * + * @param data Object (a String or Object that can be converted) to be + * written to output stream + * @throws Exception if the transformer or file output fail + */ + public void write(Object data) throws Exception { + FieldSet fieldSet = fieldSetCreator.mapItem(data); + getOutputState().write(lineAggregator.aggregate(fieldSet) + LINE_SEPARATOR); + } + + /** + * @see ResourceLifecycle#close(ExecutionContext) + */ + public void close(ExecutionContext executionContext) { + if (state != null) { + getOutputState().close(); + state = null; + } + } + + /** + * Sets encoding for output template. + */ + public void setEncoding(String newEncoding) { + getOutputState().setEncoding(newEncoding); + } + + /** + * Sets buffer size for output template + */ + public void setBufferSize(int newSize) { + getOutputState().setBufferSize(newSize); + } + + /** + * @param shouldDeleteIfExists the shouldDeleteIfExists to set + */ + public void setShouldDeleteIfExists(boolean shouldDeleteIfExists) { + getOutputState().setShouldDeleteIfExists(shouldDeleteIfExists); + } + + /** + * Initialize the Output Template. + * @see ResourceLifecycle#open() + */ + public void open(ExecutionContext executionContext) { + OutputState outputState = getOutputState(); + if(executionContext.containsKey(getKey(RESTART_DATA_NAME))){ + outputState.restoreFrom(executionContext); + } + } + + /** + * @see ItemStream#update(ExecutionContext) + */ + public void update(ExecutionContext executionContext) { + if (state == null) { + throw new StreamException("ItemStream not open or already closed."); + } + Assert.notNull(executionContext, "ExecutionContext must not be null"); + executionContext.putLong(getKey(RESTART_DATA_NAME), state.position()); + executionContext.putLong(getKey(WRITTEN_STATISTICS_NAME), state.linesWritten); + executionContext.putLong(getKey(RESTART_COUNT_STATISTICS_NAME), state.restartCount); + } + + // Returns object representing state. + private OutputState getOutputState() { + if (state == null) { + state = new OutputState(); + } + return (OutputState) state; + } + + /** + * Encapsulates the runtime state of the writer. All state changing + * operations on the writer go through this class. + */ + private class OutputState { + // default encoding for writing to output files - set to UTF-8. + private static final String DEFAULT_CHARSET = "UTF-8"; + + private static final int DEFAULT_BUFFER_SIZE = 2048; + + // The bufferedWriter over the file channel that is actually written + BufferedWriter outputBufferedWriter; + + FileChannel fileChannel; + + // this represents the charset encoding (if any is needed) for the + // output file + String encoding = DEFAULT_CHARSET; + + // Optional write buffer size + int bufferSize = DEFAULT_BUFFER_SIZE; + + boolean restarted = false; + + boolean initialized = false; + + long lastMarkedByteOffsetPosition = 0; + + long linesWritten = 0; + + long restartCount = 0; + + boolean shouldDeleteIfExists = true; + + /** + * Return the byte offset position of the cursor in the output file as a + * long integer. + */ + public long position() { + long pos = 0; + + if (fileChannel == null) { + return 0; + } + + try { + outputBufferedWriter.flush(); + pos = fileChannel.position(); + } + catch (IOException e) { + throw new InfrastructureException("An Error occured while trying to get filechannel position", e); + } + + return pos; + + } + + /** + * @param properties + */ + public void restoreFrom(ExecutionContext executionContext) { + lastMarkedByteOffsetPosition = executionContext.getLong(getKey(RESTART_DATA_NAME)); + restarted = true; + } + + /** + * @param shouldDeleteIfExists2 + */ + public void setShouldDeleteIfExists(boolean shouldDeleteIfExists) { + this.shouldDeleteIfExists = shouldDeleteIfExists; + } + + /** + * @param newSize + */ + public void setBufferSize(int newSize) { + bufferSize = newSize; + } + + /** + * @param newEncoding + */ + public void setEncoding(String newEncoding) { + encoding = newEncoding; + } + + /** + * Close the open resource and reset counters. + */ + public void close() { + initialized = false; + restarted = false; + try { + if (outputBufferedWriter == null) { + return; + } + outputBufferedWriter.close(); + fileChannel.close(); + } + catch (IOException ioe) { + throw new StreamException("Unable to close the the ItemWriter", ioe); + } + } + + /** + * @param data + * @param offset + * @param length + */ + public void write(String line) { + if (!initialized) { + initializeBufferedWriter(); + } + + try { + outputBufferedWriter.write(line); + outputBufferedWriter.flush(); + linesWritten++; + } + catch (IOException e) { + throw new InfrastructureException("An Error occured while trying to write to FlatFileItemWriter", e); + } + } + + /** + * Truncate the output at the last known good point. + */ + public void truncate() { + try { + fileChannel.truncate(lastMarkedByteOffsetPosition); + fileChannel.position(lastMarkedByteOffsetPosition); + } + catch (IOException e) { + throw new InfrastructureException("An Error occured while truncating output file", e); + } + } + + /** + * Mark the current position. + */ + public void mark() { + lastMarkedByteOffsetPosition = this.position(); + } + + /** + * Creates the buffered writer for the output file channel based on + * configuration information. + */ + private void initializeBufferedWriter() { + File file; + + try { + file = resource.getFile(); + + // If the output source was restarted, keep existing file. + // If the output source was not restarted, check following: + // - if the file should be deleted, delete it if it was exiting + // and create blank file, + // - if the file should not be deleted, if it already exists, + // throw an exception, + // - if the file was not existing, create new. + if (!restarted) { + if (file.exists()) { + if (shouldDeleteIfExists) { + file.delete(); + } + else { + throw new StreamException("Resource already exists: " + resource); + } + } + String parent = file.getParent(); + if (parent != null) { + new File(parent).mkdirs(); + } + file.createNewFile(); + } + + } + catch (IOException ioe) { + throw new DataAccessResourceFailureException("Unable to write to file resource: [" + resource + "]", + ioe); + } + + try { + fileChannel = (new FileOutputStream(file.getAbsolutePath(), true)).getChannel(); + } + catch (FileNotFoundException fnfe) { + throw new ConfigurationException("Bad filename property parameter " + file, fnfe); + } + + outputBufferedWriter = getBufferedWriter(fileChannel, encoding, bufferSize); + + // in case of restarting reset position to last commited point + if (restarted) { + this.reset(); + } + + initialized = true; + linesWritten = 0; + } + + /** + * Returns the buffered writer opened to the beginning of the file + * specified by the absolute path name contained in absoluteFileName. + */ + private BufferedWriter getBufferedWriter(FileChannel fileChannel, String encoding, int bufferSize) { + try { + + BufferedWriter outputBufferedWriter = null; + + // If a buffer was requested, allocate. + if (bufferSize > 0) { + outputBufferedWriter = new BufferedWriter(Channels.newWriter(fileChannel, encoding), bufferSize); + } + else { + outputBufferedWriter = new BufferedWriter(Channels.newWriter(fileChannel, encoding)); + } + + return outputBufferedWriter; + } + catch (UnsupportedCharsetException ucse) { + throw new StreamException("Bad encoding configuration for output file " + fileChannel, ucse); + } + } + + /** + * Resets the file writer's current position to the point stored in the + * last marked byte offset position variable. It first checks to make + * sure the current size of the file is not less than the byte position + * to be moved to (if it is, throws an environment exception), then it + * truncates the file to that reset position, and set the cursor to + * start writing at that point. + */ + public void reset() throws InfrastructureException { + checkFileSize(); + getOutputState().truncate(); + } + + /** + * Checks (on setState) to make sure that the current output file's size + * is not smaller than the last saved commit point. If it is, then the + * file has been damaged in some way and whole task must be started over + * again from the beginning. + */ + private void checkFileSize() { + long size = -1; + + try { + outputBufferedWriter.flush(); + size = fileChannel.size(); + } + catch (IOException e) { + throw new InfrastructureException("An Error occured while checking file size", e); + } + + if (size < lastMarkedByteOffsetPosition) { + throw new InfrastructureException("Current file size is smaller than size at last commit"); + } + } + + } + + public void clear() throws ClearFailedException { + try { + getOutputState().reset(); + } + catch (InfrastructureException e) { + throw new ResetFailedException(e); + } + } + + public void flush() throws FlushFailedException { + getOutputState().mark(); + } + +} diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/file/mapping/DefaultFieldSet.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/file/mapping/DefaultFieldSet.java index 958255e57e..bbca4a3a85 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/file/mapping/DefaultFieldSet.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/file/mapping/DefaultFieldSet.java @@ -1,503 +1,503 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.batch.io.file.mapping; - -import java.math.BigDecimal; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Arrays; -import java.util.Date; -import java.util.List; -import java.util.Properties; - -import org.springframework.util.Assert; -import org.springframework.util.StringUtils; - -/** - * Default implementation of {@link FieldSet} using Java using Java primitive - * and standard types and utilities. Strings are trimmed before parsing by - * default, and so are plain String values. - * - * @author Rob Harrop - * @author Dave Syer - */ -public class DefaultFieldSet implements FieldSet { - - private final static String DEFAULT_DATE_PATTERN = "yyyy-MM-dd"; - - /** - * The fields wrapped by this 'FieldSet' instance. - */ - private String[] tokens; - - private List names; - - public DefaultFieldSet(String[] tokens) { - this.tokens = tokens == null ? null : (String[]) tokens.clone(); - } - - public DefaultFieldSet(String[] tokens, String[] names) { - Assert.notNull(tokens); - Assert.notNull(names); - if (tokens.length != names.length) { - throw new IllegalArgumentException("Field names must be same length as values: names=" - + Arrays.asList(names) + ", values=" + Arrays.asList(tokens)); - } - this.tokens = (String[]) tokens.clone(); - this.names = Arrays.asList(names); - } - - /* - * (non-Javadoc) - * @see org.springframework.batch.io.file.mapping.IFieldSet#getNames() - */ - public String[] getNames() { - if (names == null) { - throw new IllegalStateException("Field names are not known"); - } - return (String[]) names.toArray(); - } - - /* - * (non-Javadoc) - * @see org.springframework.batch.io.file.mapping.IFieldSet#getValues() - */ - public String[] getValues() { - return tokens; - } - - /* - * (non-Javadoc) - * @see org.springframework.batch.io.file.mapping.IFieldSet#readString(int) - */ - public String readString(int index) { - return readAndTrim(index); - } - - /* - * (non-Javadoc) - * @see org.springframework.batch.io.file.mapping.IFieldSet#readString(java.lang.String) - */ - public String readString(String name) { - return readString(indexOf(name)); - } - - /* - * (non-Javadoc) - * @see org.springframework.batch.io.file.mapping.IFieldSet#readRawString(int) - */ - public String readRawString(int index) { - return tokens[index]; - } - - /* - * (non-Javadoc) - * @see org.springframework.batch.io.file.mapping.IFieldSet#readRawString(java.lang.String) - */ - public String readRawString(String name) { - return readRawString(indexOf(name)); - } - - /* - * (non-Javadoc) - * @see org.springframework.batch.io.file.mapping.IFieldSet#readBoolean(int) - */ - public boolean readBoolean(int index) { - return readBoolean(index, "true"); - } - - /* - * (non-Javadoc) - * @see org.springframework.batch.io.file.mapping.IFieldSet#readBoolean(java.lang.String) - */ - public boolean readBoolean(String name) { - return readBoolean(indexOf(name)); - } - - /* - * (non-Javadoc) - * @see org.springframework.batch.io.file.mapping.IFieldSet#readBoolean(int, - * java.lang.String) - */ - public boolean readBoolean(int index, String trueValue) { - Assert.notNull(trueValue, "'trueValue' cannot be null."); - - String value = readAndTrim(index); - - return trueValue.equals(value) ? true : false; - } - - /* - * (non-Javadoc) - * @see org.springframework.batch.io.file.mapping.IFieldSet#readBoolean(java.lang.String, - * java.lang.String) - */ - public boolean readBoolean(String name, String trueValue) { - return readBoolean(indexOf(name), trueValue); - } - - /* - * (non-Javadoc) - * @see org.springframework.batch.io.file.mapping.IFieldSet#readChar(int) - */ - public char readChar(int index) { - String value = readAndTrim(index); - - Assert.isTrue(value.length() == 1, "Cannot convert field value '" + value + "' to char."); - - return value.charAt(0); - } - - /* - * (non-Javadoc) - * @see org.springframework.batch.io.file.mapping.IFieldSet#readChar(java.lang.String) - */ - public char readChar(String name) { - return readChar(indexOf(name)); - } - - /* - * (non-Javadoc) - * @see org.springframework.batch.io.file.mapping.IFieldSet#readByte(int) - */ - public byte readByte(int index) { - return Byte.parseByte(readAndTrim(index)); - } - - /* - * (non-Javadoc) - * @see org.springframework.batch.io.file.mapping.IFieldSet#readByte(java.lang.String) - */ - public byte readByte(String name) { - return readByte(indexOf(name)); - } - - /* - * (non-Javadoc) - * @see org.springframework.batch.io.file.mapping.IFieldSet#readShort(int) - */ - public short readShort(int index) { - return Short.parseShort(readAndTrim(index)); - } - - /* - * (non-Javadoc) - * @see org.springframework.batch.io.file.mapping.IFieldSet#readShort(java.lang.String) - */ - public short readShort(String name) { - return readShort(indexOf(name)); - } - - /* - * (non-Javadoc) - * @see org.springframework.batch.io.file.mapping.IFieldSet#readInt(int) - */ - public int readInt(int index) { - return Integer.parseInt(readAndTrim(index)); - } - - /* - * (non-Javadoc) - * @see org.springframework.batch.io.file.mapping.IFieldSet#readInt(java.lang.String) - */ - public int readInt(String name) { - return readInt(indexOf(name)); - } - - /* - * (non-Javadoc) - * @see org.springframework.batch.io.file.mapping.IFieldSet#readInt(int, - * int) - */ - public int readInt(int index, int defaultValue) { - String value = readAndTrim(index); - - return StringUtils.hasLength(value) ? Integer.parseInt(value) : defaultValue; - } - - /* - * (non-Javadoc) - * @see org.springframework.batch.io.file.mapping.IFieldSet#readInt(java.lang.String, - * int) - */ - public int readInt(String name, int defaultValue) { - return readInt(indexOf(name), defaultValue); - } - - /* - * (non-Javadoc) - * @see org.springframework.batch.io.file.mapping.IFieldSet#readLong(int) - */ - public long readLong(int index) { - return Long.parseLong(readAndTrim(index)); - } - - /* - * (non-Javadoc) - * @see org.springframework.batch.io.file.mapping.IFieldSet#readLong(java.lang.String) - */ - public long readLong(String name) { - return readLong(indexOf(name)); - } - - /* - * (non-Javadoc) - * @see org.springframework.batch.io.file.mapping.IFieldSet#readLong(int, - * long) - */ - public long readLong(int index, long defaultValue) { - String value = readAndTrim(index); - - return StringUtils.hasLength(value) ? Long.parseLong(value) : defaultValue; - } - - /* - * (non-Javadoc) - * @see org.springframework.batch.io.file.mapping.IFieldSet#readLong(java.lang.String, - * long) - */ - public long readLong(String name, long defaultValue) { - return readLong(indexOf(name), defaultValue); - } - - /* - * (non-Javadoc) - * @see org.springframework.batch.io.file.mapping.IFieldSet#readFloat(int) - */ - public float readFloat(int index) { - return Float.parseFloat(readAndTrim(index)); - } - - /* - * (non-Javadoc) - * @see org.springframework.batch.io.file.mapping.IFieldSet#readFloat(java.lang.String) - */ - public float readFloat(String name) { - return readFloat(indexOf(name)); - } - - /* - * (non-Javadoc) - * @see org.springframework.batch.io.file.mapping.IFieldSet#readDouble(int) - */ - public double readDouble(int index) { - return Double.parseDouble(readAndTrim(index)); - } - - /* - * (non-Javadoc) - * @see org.springframework.batch.io.file.mapping.IFieldSet#readDouble(java.lang.String) - */ - public double readDouble(String name) { - return readDouble(indexOf(name)); - } - - /* - * (non-Javadoc) - * @see org.springframework.batch.io.file.mapping.IFieldSet#readBigDecimal(int) - */ - public BigDecimal readBigDecimal(int index) { - return readBigDecimal(index, null); - } - - /* - * (non-Javadoc) - * @see org.springframework.batch.io.file.mapping.IFieldSet#readBigDecimal(java.lang.String) - */ - public BigDecimal readBigDecimal(String name) { - return readBigDecimal(name, null); - } - - /* - * (non-Javadoc) - * @see org.springframework.batch.io.file.mapping.IFieldSet#readBigDecimal(int, - * java.math.BigDecimal) - */ - public BigDecimal readBigDecimal(int index, BigDecimal defaultValue) { - String candidate = readAndTrim(index); - - try { - return (StringUtils.hasText(candidate)) ? new BigDecimal(candidate) : defaultValue; - } - catch (NumberFormatException e) { - throw new IllegalArgumentException("Unparseable number: " + candidate); - } - } - - /* - * (non-Javadoc) - * @see org.springframework.batch.io.file.mapping.IFieldSet#readBigDecimal(java.lang.String, - * java.math.BigDecimal) - */ - public BigDecimal readBigDecimal(String name, BigDecimal defaultValue) { - try { - return readBigDecimal(indexOf(name), defaultValue); - } - catch (IllegalArgumentException e) { - throw new IllegalArgumentException(e.getMessage() + ", name: [" + name + "]"); - } - } - - /* - * (non-Javadoc) - * @see org.springframework.batch.io.file.mapping.IFieldSet#readDate(int) - */ - public Date readDate(int index) { - return readDate(index, DEFAULT_DATE_PATTERN); - } - - /* - * (non-Javadoc) - * @see org.springframework.batch.io.file.mapping.IFieldSet#readDate(java.lang.String) - */ - public Date readDate(String name) { - return readDate(name, DEFAULT_DATE_PATTERN); - } - - /* - * (non-Javadoc) - * @see org.springframework.batch.io.file.mapping.IFieldSet#readDate(int, - * java.lang.String) - */ - public Date readDate(int index, String pattern) { - SimpleDateFormat sdf = new SimpleDateFormat(pattern); - Date date; - String value = readAndTrim(index); - try { - date = sdf.parse(value); - } - catch (ParseException e) { - throw new IllegalArgumentException(e.getMessage() + ", pattern: [" + pattern + "]"); - } - return date; - } - - /* - * (non-Javadoc) - * @see org.springframework.batch.io.file.mapping.IFieldSet#readDate(java.lang.String, - * java.lang.String) - */ - public Date readDate(String name, String pattern) { - try { - return readDate(indexOf(name), pattern); - } - catch (IllegalArgumentException e) { - throw new IllegalArgumentException(e.getMessage() + ", name: [" + name + "]"); - } - } - - /* - * (non-Javadoc) - * @see org.springframework.batch.io.file.mapping.IFieldSet#getFieldCount() - */ - public int getFieldCount() { - return tokens.length; - } - - /** - * Read and trim the {@link String} value at 'index'. - * - * @throws NullPointerException if the field value is null. - */ - protected String readAndTrim(int index) { - String value = tokens[index]; - - if (value != null) { - return value.trim(); - } - else { - return null; - } - } - - /** - * Read and trim the {@link String} value from column with given 'name. - * - * @throws IllegalArgumentException if a column with given name is not - * defined. - */ - protected int indexOf(String name) { - if (names == null) { - throw new IllegalArgumentException("Cannot access columns by name without meta data"); - } - int index = names.indexOf(name); - if (index >= 0) { - return index; - } - throw new IllegalArgumentException("Cannot access column [" + name + "] from " + names); - } - - public String toString() { - if (names != null) { - return getProperties().toString(); - } - - return tokens == null ? "" : Arrays.asList(tokens).toString(); - } - - /** - * @see java.lang.Object#equals(java.lang.Object) - */ - public boolean equals(Object object) { - if (object instanceof DefaultFieldSet) { - DefaultFieldSet fs = (DefaultFieldSet) object; - - if (this.tokens == null) { - return fs.tokens == null; - } - else { - return Arrays.equals(this.tokens, fs.tokens); - } - } - - return false; - } - - public int hashCode() { - // this algorithm was taken from java 1.5 jdk Arrays.hashCode(Object[]) - if (tokens == null) { - return 0; - } - - int result = 1; - - for (int i = 0; i < tokens.length; i++) { - result = 31 * result + (tokens[i] == null ? 0 : tokens[i].hashCode()); - } - - return result; - } - - /* - * (non-Javadoc) - * @see org.springframework.batch.io.file.mapping.IFieldSet#getProperties() - */ - public Properties getProperties() { - if (names == null) { - throw new IllegalStateException("Cannot create properties without meta data"); - } - Properties props = new Properties(); - for (int i = 0; i < tokens.length; i++) { - String value = readAndTrim(i); - if (value != null) { - props.setProperty((String) names.get(i), value); - } - } - return props; - } - -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.batch.io.file.mapping; + +import java.math.BigDecimal; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Arrays; +import java.util.Date; +import java.util.List; +import java.util.Properties; + +import org.springframework.util.Assert; +import org.springframework.util.StringUtils; + +/** + * Default implementation of {@link FieldSet} using Java using Java primitive + * and standard types and utilities. Strings are trimmed before parsing by + * default, and so are plain String values. + * + * @author Rob Harrop + * @author Dave Syer + */ +public class DefaultFieldSet implements FieldSet { + + private final static String DEFAULT_DATE_PATTERN = "yyyy-MM-dd"; + + /** + * The fields wrapped by this 'FieldSet' instance. + */ + private String[] tokens; + + private List names; + + public DefaultFieldSet(String[] tokens) { + this.tokens = tokens == null ? null : (String[]) tokens.clone(); + } + + public DefaultFieldSet(String[] tokens, String[] names) { + Assert.notNull(tokens); + Assert.notNull(names); + if (tokens.length != names.length) { + throw new IllegalArgumentException("Field names must be same length as values: names=" + + Arrays.asList(names) + ", values=" + Arrays.asList(tokens)); + } + this.tokens = (String[]) tokens.clone(); + this.names = Arrays.asList(names); + } + + /* + * (non-Javadoc) + * @see org.springframework.batch.io.file.mapping.IFieldSet#getNames() + */ + public String[] getNames() { + if (names == null) { + throw new IllegalStateException("Field names are not known"); + } + return (String[]) names.toArray(); + } + + /* + * (non-Javadoc) + * @see org.springframework.batch.io.file.mapping.IFieldSet#getValues() + */ + public String[] getValues() { + return tokens; + } + + /* + * (non-Javadoc) + * @see org.springframework.batch.io.file.mapping.IFieldSet#readString(int) + */ + public String readString(int index) { + return readAndTrim(index); + } + + /* + * (non-Javadoc) + * @see org.springframework.batch.io.file.mapping.IFieldSet#readString(java.lang.String) + */ + public String readString(String name) { + return readString(indexOf(name)); + } + + /* + * (non-Javadoc) + * @see org.springframework.batch.io.file.mapping.IFieldSet#readRawString(int) + */ + public String readRawString(int index) { + return tokens[index]; + } + + /* + * (non-Javadoc) + * @see org.springframework.batch.io.file.mapping.IFieldSet#readRawString(java.lang.String) + */ + public String readRawString(String name) { + return readRawString(indexOf(name)); + } + + /* + * (non-Javadoc) + * @see org.springframework.batch.io.file.mapping.IFieldSet#readBoolean(int) + */ + public boolean readBoolean(int index) { + return readBoolean(index, "true"); + } + + /* + * (non-Javadoc) + * @see org.springframework.batch.io.file.mapping.IFieldSet#readBoolean(java.lang.String) + */ + public boolean readBoolean(String name) { + return readBoolean(indexOf(name)); + } + + /* + * (non-Javadoc) + * @see org.springframework.batch.io.file.mapping.IFieldSet#readBoolean(int, + * java.lang.String) + */ + public boolean readBoolean(int index, String trueValue) { + Assert.notNull(trueValue, "'trueValue' cannot be null."); + + String value = readAndTrim(index); + + return trueValue.equals(value) ? true : false; + } + + /* + * (non-Javadoc) + * @see org.springframework.batch.io.file.mapping.IFieldSet#readBoolean(java.lang.String, + * java.lang.String) + */ + public boolean readBoolean(String name, String trueValue) { + return readBoolean(indexOf(name), trueValue); + } + + /* + * (non-Javadoc) + * @see org.springframework.batch.io.file.mapping.IFieldSet#readChar(int) + */ + public char readChar(int index) { + String value = readAndTrim(index); + + Assert.isTrue(value.length() == 1, "Cannot convert field value '" + value + "' to char."); + + return value.charAt(0); + } + + /* + * (non-Javadoc) + * @see org.springframework.batch.io.file.mapping.IFieldSet#readChar(java.lang.String) + */ + public char readChar(String name) { + return readChar(indexOf(name)); + } + + /* + * (non-Javadoc) + * @see org.springframework.batch.io.file.mapping.IFieldSet#readByte(int) + */ + public byte readByte(int index) { + return Byte.parseByte(readAndTrim(index)); + } + + /* + * (non-Javadoc) + * @see org.springframework.batch.io.file.mapping.IFieldSet#readByte(java.lang.String) + */ + public byte readByte(String name) { + return readByte(indexOf(name)); + } + + /* + * (non-Javadoc) + * @see org.springframework.batch.io.file.mapping.IFieldSet#readShort(int) + */ + public short readShort(int index) { + return Short.parseShort(readAndTrim(index)); + } + + /* + * (non-Javadoc) + * @see org.springframework.batch.io.file.mapping.IFieldSet#readShort(java.lang.String) + */ + public short readShort(String name) { + return readShort(indexOf(name)); + } + + /* + * (non-Javadoc) + * @see org.springframework.batch.io.file.mapping.IFieldSet#readInt(int) + */ + public int readInt(int index) { + return Integer.parseInt(readAndTrim(index)); + } + + /* + * (non-Javadoc) + * @see org.springframework.batch.io.file.mapping.IFieldSet#readInt(java.lang.String) + */ + public int readInt(String name) { + return readInt(indexOf(name)); + } + + /* + * (non-Javadoc) + * @see org.springframework.batch.io.file.mapping.IFieldSet#readInt(int, + * int) + */ + public int readInt(int index, int defaultValue) { + String value = readAndTrim(index); + + return StringUtils.hasLength(value) ? Integer.parseInt(value) : defaultValue; + } + + /* + * (non-Javadoc) + * @see org.springframework.batch.io.file.mapping.IFieldSet#readInt(java.lang.String, + * int) + */ + public int readInt(String name, int defaultValue) { + return readInt(indexOf(name), defaultValue); + } + + /* + * (non-Javadoc) + * @see org.springframework.batch.io.file.mapping.IFieldSet#readLong(int) + */ + public long readLong(int index) { + return Long.parseLong(readAndTrim(index)); + } + + /* + * (non-Javadoc) + * @see org.springframework.batch.io.file.mapping.IFieldSet#readLong(java.lang.String) + */ + public long readLong(String name) { + return readLong(indexOf(name)); + } + + /* + * (non-Javadoc) + * @see org.springframework.batch.io.file.mapping.IFieldSet#readLong(int, + * long) + */ + public long readLong(int index, long defaultValue) { + String value = readAndTrim(index); + + return StringUtils.hasLength(value) ? Long.parseLong(value) : defaultValue; + } + + /* + * (non-Javadoc) + * @see org.springframework.batch.io.file.mapping.IFieldSet#readLong(java.lang.String, + * long) + */ + public long readLong(String name, long defaultValue) { + return readLong(indexOf(name), defaultValue); + } + + /* + * (non-Javadoc) + * @see org.springframework.batch.io.file.mapping.IFieldSet#readFloat(int) + */ + public float readFloat(int index) { + return Float.parseFloat(readAndTrim(index)); + } + + /* + * (non-Javadoc) + * @see org.springframework.batch.io.file.mapping.IFieldSet#readFloat(java.lang.String) + */ + public float readFloat(String name) { + return readFloat(indexOf(name)); + } + + /* + * (non-Javadoc) + * @see org.springframework.batch.io.file.mapping.IFieldSet#readDouble(int) + */ + public double readDouble(int index) { + return Double.parseDouble(readAndTrim(index)); + } + + /* + * (non-Javadoc) + * @see org.springframework.batch.io.file.mapping.IFieldSet#readDouble(java.lang.String) + */ + public double readDouble(String name) { + return readDouble(indexOf(name)); + } + + /* + * (non-Javadoc) + * @see org.springframework.batch.io.file.mapping.IFieldSet#readBigDecimal(int) + */ + public BigDecimal readBigDecimal(int index) { + return readBigDecimal(index, null); + } + + /* + * (non-Javadoc) + * @see org.springframework.batch.io.file.mapping.IFieldSet#readBigDecimal(java.lang.String) + */ + public BigDecimal readBigDecimal(String name) { + return readBigDecimal(name, null); + } + + /* + * (non-Javadoc) + * @see org.springframework.batch.io.file.mapping.IFieldSet#readBigDecimal(int, + * java.math.BigDecimal) + */ + public BigDecimal readBigDecimal(int index, BigDecimal defaultValue) { + String candidate = readAndTrim(index); + + try { + return (StringUtils.hasText(candidate)) ? new BigDecimal(candidate) : defaultValue; + } + catch (NumberFormatException e) { + throw new IllegalArgumentException("Unparseable number: " + candidate); + } + } + + /* + * (non-Javadoc) + * @see org.springframework.batch.io.file.mapping.IFieldSet#readBigDecimal(java.lang.String, + * java.math.BigDecimal) + */ + public BigDecimal readBigDecimal(String name, BigDecimal defaultValue) { + try { + return readBigDecimal(indexOf(name), defaultValue); + } + catch (IllegalArgumentException e) { + throw new IllegalArgumentException(e.getMessage() + ", name: [" + name + "]"); + } + } + + /* + * (non-Javadoc) + * @see org.springframework.batch.io.file.mapping.IFieldSet#readDate(int) + */ + public Date readDate(int index) { + return readDate(index, DEFAULT_DATE_PATTERN); + } + + /* + * (non-Javadoc) + * @see org.springframework.batch.io.file.mapping.IFieldSet#readDate(java.lang.String) + */ + public Date readDate(String name) { + return readDate(name, DEFAULT_DATE_PATTERN); + } + + /* + * (non-Javadoc) + * @see org.springframework.batch.io.file.mapping.IFieldSet#readDate(int, + * java.lang.String) + */ + public Date readDate(int index, String pattern) { + SimpleDateFormat sdf = new SimpleDateFormat(pattern); + Date date; + String value = readAndTrim(index); + try { + date = sdf.parse(value); + } + catch (ParseException e) { + throw new IllegalArgumentException(e.getMessage() + ", pattern: [" + pattern + "]"); + } + return date; + } + + /* + * (non-Javadoc) + * @see org.springframework.batch.io.file.mapping.IFieldSet#readDate(java.lang.String, + * java.lang.String) + */ + public Date readDate(String name, String pattern) { + try { + return readDate(indexOf(name), pattern); + } + catch (IllegalArgumentException e) { + throw new IllegalArgumentException(e.getMessage() + ", name: [" + name + "]"); + } + } + + /* + * (non-Javadoc) + * @see org.springframework.batch.io.file.mapping.IFieldSet#getFieldCount() + */ + public int getFieldCount() { + return tokens.length; + } + + /** + * Read and trim the {@link String} value at 'index'. + * + * @throws NullPointerException if the field value is null. + */ + protected String readAndTrim(int index) { + String value = tokens[index]; + + if (value != null) { + return value.trim(); + } + else { + return null; + } + } + + /** + * Read and trim the {@link String} value from column with given 'name. + * + * @throws IllegalArgumentException if a column with given name is not + * defined. + */ + protected int indexOf(String name) { + if (names == null) { + throw new IllegalArgumentException("Cannot access columns by name without meta data"); + } + int index = names.indexOf(name); + if (index >= 0) { + return index; + } + throw new IllegalArgumentException("Cannot access column [" + name + "] from " + names); + } + + public String toString() { + if (names != null) { + return getProperties().toString(); + } + + return tokens == null ? "" : Arrays.asList(tokens).toString(); + } + + /** + * @see java.lang.Object#equals(java.lang.Object) + */ + public boolean equals(Object object) { + if (object instanceof DefaultFieldSet) { + DefaultFieldSet fs = (DefaultFieldSet) object; + + if (this.tokens == null) { + return fs.tokens == null; + } + else { + return Arrays.equals(this.tokens, fs.tokens); + } + } + + return false; + } + + public int hashCode() { + // this algorithm was taken from java 1.5 jdk Arrays.hashCode(Object[]) + if (tokens == null) { + return 0; + } + + int result = 1; + + for (int i = 0; i < tokens.length; i++) { + result = 31 * result + (tokens[i] == null ? 0 : tokens[i].hashCode()); + } + + return result; + } + + /* + * (non-Javadoc) + * @see org.springframework.batch.io.file.mapping.IFieldSet#getProperties() + */ + public Properties getProperties() { + if (names == null) { + throw new IllegalStateException("Cannot create properties without meta data"); + } + Properties props = new Properties(); + for (int i = 0; i < tokens.length; i++) { + String value = readAndTrim(i); + if (value != null) { + props.setProperty((String) names.get(i), value); + } + } + return props; + } + +} diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/file/mapping/PassThroughFieldSetMapper.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/file/mapping/PassThroughFieldSetMapper.java index d3ac1b7b71..2a92c073b4 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/file/mapping/PassThroughFieldSetMapper.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/file/mapping/PassThroughFieldSetMapper.java @@ -1,53 +1,53 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.io.file.mapping; - - -/** - * Pass through {@link FieldSetMapper} useful for passing a {@link FieldSet} - * back directly rather than a mapped object. - * - * @author Lucas Ward - * - */ -public class PassThroughFieldSetMapper implements FieldSetMapper, FieldSetCreator { - - /* - * (non-Javadoc) - * @see org.springframework.batch.io.file.FieldSetMapper#mapLine(org.springframework.batch.io.file.FieldSet) - */ - public Object mapLine(FieldSet fs) { - return fs; - } - - /** - * If the input is a {@link FieldSet} pass it to the caller. Otherwise - * convert to a String with toString() and convert it to a single field - * {@link FieldSet}. - * - * @see org.springframework.batch.io.file.mapping.FieldSetCreator#mapItem(java.lang.Object) - */ - public FieldSet mapItem(Object data) { - if (data instanceof FieldSet) { - return (FieldSet) data; - } - if (!(data instanceof String)) { - data = "" + data; - } - return new DefaultFieldSet(new String[] { (String) data }); - } - -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.io.file.mapping; + + +/** + * Pass through {@link FieldSetMapper} useful for passing a {@link FieldSet} + * back directly rather than a mapped object. + * + * @author Lucas Ward + * + */ +public class PassThroughFieldSetMapper implements FieldSetMapper, FieldSetCreator { + + /* + * (non-Javadoc) + * @see org.springframework.batch.io.file.FieldSetMapper#mapLine(org.springframework.batch.io.file.FieldSet) + */ + public Object mapLine(FieldSet fs) { + return fs; + } + + /** + * If the input is a {@link FieldSet} pass it to the caller. Otherwise + * convert to a String with toString() and convert it to a single field + * {@link FieldSet}. + * + * @see org.springframework.batch.io.file.mapping.FieldSetCreator#mapItem(java.lang.Object) + */ + public FieldSet mapItem(Object data) { + if (data instanceof FieldSet) { + return (FieldSet) data; + } + if (!(data instanceof String)) { + data = "" + data; + } + return new DefaultFieldSet(new String[] { (String) data }); + } + +} diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/file/separator/ResourceLineReader.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/file/separator/ResourceLineReader.java index 082a6a0ea7..635f5c18ad 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/file/separator/ResourceLineReader.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/file/separator/ResourceLineReader.java @@ -1,339 +1,339 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.batch.io.file.separator; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; -import java.util.Iterator; - -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.item.ItemReader; -import org.springframework.batch.item.ItemStream; -import org.springframework.batch.item.exception.MarkFailedException; -import org.springframework.batch.item.exception.ResetFailedException; -import org.springframework.batch.item.exception.StreamException; -import org.springframework.batch.item.stream.ItemStreamSupport; -import org.springframework.core.io.Resource; -import org.springframework.util.Assert; - -/** - * An input source that reads lines one by one from a resource.
- * - * A line can consist of multiple lines in the input resource, according to the - * {@link RecordSeparatorPolicy} in force. By default a line is either - * terminated by a newline (as per {@link BufferedReader#readLine()}), or can - * be continued onto the next line if a field surrounded by quotes (\") contains - * a newline.
- * - * Comment lines can be indicated using a line prefix (or collection of - * prefixes) and they will be ignored. The default is "#", so lines starting - * with a pound sign will be ignored.
- * - * All the public methods that interact with the underlying resource (open, - * close, read etc.) are synchronized on this.
- * - * Package private because this is not intended to be a public API - used - * internally by the flat file input sources. That makes abuses of the fact that - * it is stateful easier to control.
- * - * @author Dave Syer - * @author Rob Harrop - */ -public class ResourceLineReader extends ItemStreamSupport implements LineReader, ItemReader { - - private static final Collection DEFAULT_COMMENTS = Collections.singleton("#"); - - private static final String DEFAULT_ENCODING = "ISO-8859-1"; - - private static final int READ_AHEAD_LIMIT = 100000; - - private final Resource resource; - - private final String encoding; - - private Collection comments = DEFAULT_COMMENTS; - - // Encapsulates the state of the input source. - private State state = null; - - private RecordSeparatorPolicy recordSeparatorPolicy = new DefaultRecordSeparatorPolicy(); - - public ResourceLineReader(Resource resource) throws IOException { - this(resource, DEFAULT_ENCODING); - } - - public ResourceLineReader(Resource resource, String encoding) { - Assert.notNull(resource, "'resource' cannot be null."); - Assert.notNull(encoding, "'encoding' cannot be null."); - this.resource = resource; - this.encoding = encoding; - } - - /** - * Setter for the {@link RecordSeparatorPolicy}. Default value is a - * {@link DefaultRecordSeparatorPolicy}. Ideally should not be changed once - * a reader is in use, but it would not be fatal if it was. - * - * @param recordSeparatorPolicy the new {@link RecordSeparatorPolicy} - */ - public void setRecordSeparatorPolicy(RecordSeparatorPolicy recordSeparatorPolicy) { - /* - * The rest of the code accesses the policy in synchronized blocks, - * copying the reference before using it. So in principle it can be - * changed in flight - the results might not be what the user expected! - */ - this.recordSeparatorPolicy = recordSeparatorPolicy; - } - - /** - * Setter for comment prefixes. Can be used to ignore header lines as well - * by using e.g. the first couple of column names as a prefix. - * - * @param comments an array of comment line prefixes. - */ - public void setComments(String[] comments) { - this.comments = new HashSet(Arrays.asList(comments)); - } - - /** - * Read the next line from the input resource, ignoring comments, and - * according to the {@link RecordSeparatorPolicy}. - * - * @return a String. - * - * @see org.springframework.batch.item.reader.support.ItemReader#read() - */ - public synchronized Object read() { - // Make a copy of the recordSeparatorPolicy reference, in case it is - // changed during a read operation (unlikely, but you never know)... - RecordSeparatorPolicy recordSeparatorPolicy = this.recordSeparatorPolicy; - String line = readLine(); - String record = line; - if (line != null) { - while (line != null && !recordSeparatorPolicy.isEndOfRecord(record)) { - record = recordSeparatorPolicy.preProcess(record) + (line = readLine()); - } - } - return recordSeparatorPolicy.postProcess(record); - } - - /** - * @return the next non-comment line - */ - private String readLine() { - return getState().readLine(); - } - - /** - * @return - */ - private State getState() { - if (state == null) { - open(); - } - return state; - } - - /** - * A no-op because the oobject is initialized with all it needs to open in - * the constructor. - * - * @see org.springframework.batch.item.ResourceLifecycle#open() - */ - public synchronized void open() { - state = new State(); - state.open(); - } - - /** - * Close the reader associated with this input source. - * - * @see org.springframework.batch.item.stream.ItemStreamSupport#close(org.springframework.batch.item.ExecutionContext) - */ - public synchronized void close(ExecutionContext executionContext) { - if (state == null) { - return; - } - try { - state.close(); - } - finally { - state = null; - } - } - - /** - * Getter for current line count (not the current number of lines returned). - * - * @return the current line count. - */ - public int getPosition() { - return getState().getCurrentLineCount(); - } - - /** - * Mark the state for return later with reset. Uses the read-ahead limit - * from an underlying {@link BufferedReader}, which means that there is a - * limit to how much data can be recovered if the mark needs to be reset.
- * - * Mark is supported as long as this {@link ItemStream} is used in a - * single-threaded environment. The state backing the mark is a single - * counter, keeping track of the current position, so multiple threads - * cannot be accommodated. - * - * @see #reset() - * - * @throws MarkFailedException if the mark could not be set. - */ - public synchronized void mark() throws MarkFailedException { - getState().mark(); - } - - /** - * Reset the reader to the last mark. - * - * @see #mark() - * - * @throws ResetFailedException if the reset is unsuccessful, e.g. if - * the read-ahead limit was breached. - */ - public synchronized void reset() throws ResetFailedException { - getState().reset(); - } - - private boolean isComment(String line) { - for (Iterator iter = comments.iterator(); iter.hasNext();) { - String prefix = (String) iter.next(); - if (line.startsWith(prefix)) { - return true; - } - } - return false; - } - - private class State { - private BufferedReader reader; - - private int currentLineCount = 0; - - private int markedLineCount = -1; - - public String readLine() { - String line = null; - - try { - line = this.reader.readLine(); - if (line == null) { - return null; - } - currentLineCount++; - while (isComment(line)) { - line = reader.readLine(); - if (line == null) { - return null; - } - currentLineCount++; - } - } - catch (IOException e) { - throw new StreamException("Unable to read from resource '" + resource + "' at line " - + currentLineCount, e); - } - return line; - } - - /** - * - */ - public void open() { - try { - reader = new BufferedReader(new InputStreamReader(resource.getInputStream(), encoding)); - mark(); - } - catch (IOException e) { - throw new StreamException("Could not open resource", e); - } - } - - /** - * Close the reader and reset the counters. - */ - public void close() { - - if (reader == null) { - return; - } - try { - reader.close(); - } - catch (IOException e) { - throw new StreamException("Could not close reader", e); - } - finally { - currentLineCount = 0; - markedLineCount = -1; - } - - } - - /** - * @return the current line count - */ - public int getCurrentLineCount() { - return currentLineCount; - } - - /** - * Mark the underlying reader and set the line counters. - */ - public void mark() throws MarkFailedException { - try { - reader.mark(READ_AHEAD_LIMIT); - markedLineCount = currentLineCount; - } - catch (IOException e) { - throw new MarkFailedException("Could not mark reader", e); - } - } - - /** - * Reset the reader and line counters to the last marked position if - * possible. - */ - public void reset() throws ResetFailedException { - - if (markedLineCount < 0) { - return; - } - try { - this.reader.reset(); - currentLineCount = markedLineCount; - } - catch (IOException e) { - throw new ResetFailedException("Could not reset reader", e); - } - - } - - } - -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.batch.io.file.separator; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.Iterator; + +import org.springframework.batch.item.ExecutionContext; +import org.springframework.batch.item.ItemReader; +import org.springframework.batch.item.ItemStream; +import org.springframework.batch.item.exception.MarkFailedException; +import org.springframework.batch.item.exception.ResetFailedException; +import org.springframework.batch.item.exception.StreamException; +import org.springframework.batch.item.stream.ItemStreamSupport; +import org.springframework.core.io.Resource; +import org.springframework.util.Assert; + +/** + * An input source that reads lines one by one from a resource.
+ * + * A line can consist of multiple lines in the input resource, according to the + * {@link RecordSeparatorPolicy} in force. By default a line is either + * terminated by a newline (as per {@link BufferedReader#readLine()}), or can + * be continued onto the next line if a field surrounded by quotes (\") contains + * a newline.
+ * + * Comment lines can be indicated using a line prefix (or collection of + * prefixes) and they will be ignored. The default is "#", so lines starting + * with a pound sign will be ignored.
+ * + * All the public methods that interact with the underlying resource (open, + * close, read etc.) are synchronized on this.
+ * + * Package private because this is not intended to be a public API - used + * internally by the flat file input sources. That makes abuses of the fact that + * it is stateful easier to control.
+ * + * @author Dave Syer + * @author Rob Harrop + */ +public class ResourceLineReader extends ItemStreamSupport implements LineReader, ItemReader { + + private static final Collection DEFAULT_COMMENTS = Collections.singleton("#"); + + private static final String DEFAULT_ENCODING = "ISO-8859-1"; + + private static final int READ_AHEAD_LIMIT = 100000; + + private final Resource resource; + + private final String encoding; + + private Collection comments = DEFAULT_COMMENTS; + + // Encapsulates the state of the input source. + private State state = null; + + private RecordSeparatorPolicy recordSeparatorPolicy = new DefaultRecordSeparatorPolicy(); + + public ResourceLineReader(Resource resource) throws IOException { + this(resource, DEFAULT_ENCODING); + } + + public ResourceLineReader(Resource resource, String encoding) { + Assert.notNull(resource, "'resource' cannot be null."); + Assert.notNull(encoding, "'encoding' cannot be null."); + this.resource = resource; + this.encoding = encoding; + } + + /** + * Setter for the {@link RecordSeparatorPolicy}. Default value is a + * {@link DefaultRecordSeparatorPolicy}. Ideally should not be changed once + * a reader is in use, but it would not be fatal if it was. + * + * @param recordSeparatorPolicy the new {@link RecordSeparatorPolicy} + */ + public void setRecordSeparatorPolicy(RecordSeparatorPolicy recordSeparatorPolicy) { + /* + * The rest of the code accesses the policy in synchronized blocks, + * copying the reference before using it. So in principle it can be + * changed in flight - the results might not be what the user expected! + */ + this.recordSeparatorPolicy = recordSeparatorPolicy; + } + + /** + * Setter for comment prefixes. Can be used to ignore header lines as well + * by using e.g. the first couple of column names as a prefix. + * + * @param comments an array of comment line prefixes. + */ + public void setComments(String[] comments) { + this.comments = new HashSet(Arrays.asList(comments)); + } + + /** + * Read the next line from the input resource, ignoring comments, and + * according to the {@link RecordSeparatorPolicy}. + * + * @return a String. + * + * @see org.springframework.batch.item.reader.support.ItemReader#read() + */ + public synchronized Object read() { + // Make a copy of the recordSeparatorPolicy reference, in case it is + // changed during a read operation (unlikely, but you never know)... + RecordSeparatorPolicy recordSeparatorPolicy = this.recordSeparatorPolicy; + String line = readLine(); + String record = line; + if (line != null) { + while (line != null && !recordSeparatorPolicy.isEndOfRecord(record)) { + record = recordSeparatorPolicy.preProcess(record) + (line = readLine()); + } + } + return recordSeparatorPolicy.postProcess(record); + } + + /** + * @return the next non-comment line + */ + private String readLine() { + return getState().readLine(); + } + + /** + * @return + */ + private State getState() { + if (state == null) { + open(); + } + return state; + } + + /** + * A no-op because the oobject is initialized with all it needs to open in + * the constructor. + * + * @see org.springframework.batch.item.ResourceLifecycle#open() + */ + public synchronized void open() { + state = new State(); + state.open(); + } + + /** + * Close the reader associated with this input source. + * + * @see org.springframework.batch.item.stream.ItemStreamSupport#close(org.springframework.batch.item.ExecutionContext) + */ + public synchronized void close(ExecutionContext executionContext) { + if (state == null) { + return; + } + try { + state.close(); + } + finally { + state = null; + } + } + + /** + * Getter for current line count (not the current number of lines returned). + * + * @return the current line count. + */ + public int getPosition() { + return getState().getCurrentLineCount(); + } + + /** + * Mark the state for return later with reset. Uses the read-ahead limit + * from an underlying {@link BufferedReader}, which means that there is a + * limit to how much data can be recovered if the mark needs to be reset.
+ * + * Mark is supported as long as this {@link ItemStream} is used in a + * single-threaded environment. The state backing the mark is a single + * counter, keeping track of the current position, so multiple threads + * cannot be accommodated. + * + * @see #reset() + * + * @throws MarkFailedException if the mark could not be set. + */ + public synchronized void mark() throws MarkFailedException { + getState().mark(); + } + + /** + * Reset the reader to the last mark. + * + * @see #mark() + * + * @throws ResetFailedException if the reset is unsuccessful, e.g. if + * the read-ahead limit was breached. + */ + public synchronized void reset() throws ResetFailedException { + getState().reset(); + } + + private boolean isComment(String line) { + for (Iterator iter = comments.iterator(); iter.hasNext();) { + String prefix = (String) iter.next(); + if (line.startsWith(prefix)) { + return true; + } + } + return false; + } + + private class State { + private BufferedReader reader; + + private int currentLineCount = 0; + + private int markedLineCount = -1; + + public String readLine() { + String line = null; + + try { + line = this.reader.readLine(); + if (line == null) { + return null; + } + currentLineCount++; + while (isComment(line)) { + line = reader.readLine(); + if (line == null) { + return null; + } + currentLineCount++; + } + } + catch (IOException e) { + throw new StreamException("Unable to read from resource '" + resource + "' at line " + + currentLineCount, e); + } + return line; + } + + /** + * + */ + public void open() { + try { + reader = new BufferedReader(new InputStreamReader(resource.getInputStream(), encoding)); + mark(); + } + catch (IOException e) { + throw new StreamException("Could not open resource", e); + } + } + + /** + * Close the reader and reset the counters. + */ + public void close() { + + if (reader == null) { + return; + } + try { + reader.close(); + } + catch (IOException e) { + throw new StreamException("Could not close reader", e); + } + finally { + currentLineCount = 0; + markedLineCount = -1; + } + + } + + /** + * @return the current line count + */ + public int getCurrentLineCount() { + return currentLineCount; + } + + /** + * Mark the underlying reader and set the line counters. + */ + public void mark() throws MarkFailedException { + try { + reader.mark(READ_AHEAD_LIMIT); + markedLineCount = currentLineCount; + } + catch (IOException e) { + throw new MarkFailedException("Could not mark reader", e); + } + } + + /** + * Reset the reader and line counters to the last marked position if + * possible. + */ + public void reset() throws ResetFailedException { + + if (markedLineCount < 0) { + return; + } + try { + this.reader.reset(); + currentLineCount = markedLineCount; + } + catch (IOException e) { + throw new ResetFailedException("Could not reset reader", e); + } + + } + + } + +} diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/file/transform/AbstractLineTokenizer.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/file/transform/AbstractLineTokenizer.java index 52c54958b4..0cccacf0d2 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/file/transform/AbstractLineTokenizer.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/file/transform/AbstractLineTokenizer.java @@ -1,84 +1,84 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.batch.io.file.transform; - -import java.util.ArrayList; -import java.util.List; - -import org.springframework.batch.io.file.mapping.DefaultFieldSet; -import org.springframework.batch.io.file.mapping.FieldSet; - - -/** - * @author Dave Syer - * @author Robert Kasanicky - * - */ -public abstract class AbstractLineTokenizer implements LineTokenizer { - - protected String[] names = new String[0]; - - /** - * Setter for column names. Optional, but if set, then all lines must have - * as many or fewer tokens. - * - * @param names - */ - public void setNames(String[] names) { - this.names = names; - } - - /** - * @return true if column names have been specified - * @see #setNames(String[]) - */ - public boolean hasNames() { - if (names != null && names.length > 0) { - return true; - } - return false; - } - - /** - * Yields the tokens resulting from the splitting of the supplied - * line. - * - * @param line the line to be tokenised (can be null) - * - * @return the resulting tokens - */ - public FieldSet tokenize(String line) { - - if (line == null || line.length()==0) { - return new DefaultFieldSet(new String[0]); - } - - List tokens = new ArrayList(doTokenize(line)); - for (int i=tokens.size(); itrue if column names have been specified + * @see #setNames(String[]) + */ + public boolean hasNames() { + if (names != null && names.length > 0) { + return true; + } + return false; + } + + /** + * Yields the tokens resulting from the splitting of the supplied + * line. + * + * @param line the line to be tokenised (can be null) + * + * @return the resulting tokens + */ + public FieldSet tokenize(String line) { + + if (line == null || line.length()==0) { + return new DefaultFieldSet(new String[0]); + } + + List tokens = new ArrayList(doTokenize(line)); + for (int i=tokens.size(); iline. - * - * @param line the line to be tokenized - * - * @return the resulting tokens - */ - protected List doTokenize(String line) { - - List tokens = new ArrayList(); - - // line is never null in current implementation - // line is checked in parent: AbstractLineTokenizer.tokenize() - char[] chars = line.toCharArray(); - boolean inQuoted = false; - int lastCut = 0; - int length = chars.length; - - for (int i = 0; i < length; i++) { - - char currentChar = chars[i]; - boolean isEnd = (i == (length - 1)); - - if ((isDelimiterCharacter(currentChar) && !inQuoted) || isEnd) { - int endPosition = (isEnd ? (length - lastCut) : (i - lastCut)); - - if (isEnd && isDelimiterCharacter(currentChar)) { - endPosition--; - } - - String value = null; - - value = maybeStripQuotes(new String(chars, lastCut, endPosition)); - - tokens.add(value); - - if (isEnd && (isDelimiterCharacter(currentChar))) { - tokens.add(""); - } - - lastCut = i + 1; - } - else if (isQuoteCharacter(currentChar)) { - inQuoted = !inQuoted; - } - - } - - return tokens; - } - - /** - * If the string is quoted strip (possibly with whitespace outside the - * quotes (which will be stripped), replace escaped quotes inside the - * string. Quotes are escaped with double instances of the quote character. - * @param string - * @return the same string but stripped and unescaped if necessary - */ - private String maybeStripQuotes(String string) { - String value = string.trim(); - if (isQuoted(value)) { - value = StringUtils.replace(value, "" + quoteCharacter + quoteCharacter, "" + quoteCharacter); - int endLength = value.length() - 1; - // used to deal with empty quoted values - if(endLength == 0) { - endLength = 1; - } - string = value.substring(1, endLength); - } - return string; - } - - /** - * Is this string surrounded by quite characters? - * @param value - * @return true if the value starts and ends with the - * {@link #quoteCharacter} - */ - private boolean isQuoted(String value) { - if (value.startsWith(quoteString) && value.endsWith(quoteString)) { - return true; - } - return false; - } - - /** - * Is the supplied character the delimiter character? - * - * @param c the character to be checked - * @return true if the supplied character is the delimiter - * character - * @see DelimitedLineTokenizer#DelimitedLineTokenizer(char) - */ - private boolean isDelimiterCharacter(char c) { - return c == this.delimiter; - } - - /** - * Is the supplied character a quote character? - * - * @param c the character to be checked - * @return true if the supplied character is an quote - * character - * @see #setQuoteCharacter(char) - */ - protected boolean isQuoteCharacter(char c) { - return c == quoteCharacter; - } -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.batch.io.file.transform; + +import java.util.ArrayList; +import java.util.List; + +import org.springframework.batch.io.exception.ConfigurationException; +import org.springframework.util.StringUtils; + +/** + * + * @author Rob Harrop + * @author Dave Syer + * + */ +public class DelimitedLineTokenizer extends AbstractLineTokenizer { + /** + * Convenient constant for the common case of a tab delimiter. + */ + public static final char DELIMITER_TAB = '\t'; + + /** + * Convenient constant for the common case of a comma delimiter. + */ + public static final char DELIMITER_COMMA = ','; + + /** + * Convenient constant for the common case of a " character used to escape + * delimiters or line endings. + */ + public static final char DEFAULT_QUOTE_CHARACTER = '"'; + + // the delimiter character used when reading input. + private char delimiter; + + private char quoteCharacter = DEFAULT_QUOTE_CHARACTER; + + private String quoteString; + + /** + * Create a new instance of the {@link DelimitedLineTokenizer} class for the + * common case where the delimiter is a {@link #DELIMITER_COMMA comma}. + * + * @see #DelimitedLineTokenizer(char) + * @see #DELIMITER_COMMA + */ + public DelimitedLineTokenizer() { + this(DELIMITER_COMMA); + } + + /** + * Create a new instance of the {@link DelimitedLineTokenizer} class. + * + * @param delimiter the desired delimiter + */ + public DelimitedLineTokenizer(char delimiter) { + if (delimiter == DEFAULT_QUOTE_CHARACTER) { + throw new ConfigurationException("'" + DEFAULT_QUOTE_CHARACTER + + "' is not allowed as delimiter for tokenizers."); + } + + this.delimiter = delimiter; + setQuoteCharacter(DEFAULT_QUOTE_CHARACTER); + } + + /** + * Setter for the delimiter character. + * @param delimiter + */ + public void setDelimiter(char delimiter) { + this.delimiter = delimiter; + } + + /** + * Public setter for the quoteCharacter. The quote character can be used to + * extend a field across line endings or to enclose a String which contains + * the delimiter. Inside a quoted token the quote character can be used to + * escape itself, thus "a""b""c" is tokenized to a"b"c. + * + * @param quoteCharacter the quoteCharacter to set + * + * @see #DEFAULT_QUOTE_CHARACTER + */ + public void setQuoteCharacter(char quoteCharacter) { + this.quoteCharacter = quoteCharacter; + this.quoteString = "" + quoteCharacter; + } + + /** + * Yields the tokens resulting from the splitting of the supplied + * line. + * + * @param line the line to be tokenized + * + * @return the resulting tokens + */ + protected List doTokenize(String line) { + + List tokens = new ArrayList(); + + // line is never null in current implementation + // line is checked in parent: AbstractLineTokenizer.tokenize() + char[] chars = line.toCharArray(); + boolean inQuoted = false; + int lastCut = 0; + int length = chars.length; + + for (int i = 0; i < length; i++) { + + char currentChar = chars[i]; + boolean isEnd = (i == (length - 1)); + + if ((isDelimiterCharacter(currentChar) && !inQuoted) || isEnd) { + int endPosition = (isEnd ? (length - lastCut) : (i - lastCut)); + + if (isEnd && isDelimiterCharacter(currentChar)) { + endPosition--; + } + + String value = null; + + value = maybeStripQuotes(new String(chars, lastCut, endPosition)); + + tokens.add(value); + + if (isEnd && (isDelimiterCharacter(currentChar))) { + tokens.add(""); + } + + lastCut = i + 1; + } + else if (isQuoteCharacter(currentChar)) { + inQuoted = !inQuoted; + } + + } + + return tokens; + } + + /** + * If the string is quoted strip (possibly with whitespace outside the + * quotes (which will be stripped), replace escaped quotes inside the + * string. Quotes are escaped with double instances of the quote character. + * @param string + * @return the same string but stripped and unescaped if necessary + */ + private String maybeStripQuotes(String string) { + String value = string.trim(); + if (isQuoted(value)) { + value = StringUtils.replace(value, "" + quoteCharacter + quoteCharacter, "" + quoteCharacter); + int endLength = value.length() - 1; + // used to deal with empty quoted values + if(endLength == 0) { + endLength = 1; + } + string = value.substring(1, endLength); + } + return string; + } + + /** + * Is this string surrounded by quite characters? + * @param value + * @return true if the value starts and ends with the + * {@link #quoteCharacter} + */ + private boolean isQuoted(String value) { + if (value.startsWith(quoteString) && value.endsWith(quoteString)) { + return true; + } + return false; + } + + /** + * Is the supplied character the delimiter character? + * + * @param c the character to be checked + * @return true if the supplied character is the delimiter + * character + * @see DelimitedLineTokenizer#DelimitedLineTokenizer(char) + */ + private boolean isDelimiterCharacter(char c) { + return c == this.delimiter; + } + + /** + * Is the supplied character a quote character? + * + * @param c the character to be checked + * @return true if the supplied character is an quote + * character + * @see #setQuoteCharacter(char) + */ + protected boolean isQuoteCharacter(char c) { + return c == quoteCharacter; + } +} diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/file/transform/FixedLengthLineAggregator.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/file/transform/FixedLengthLineAggregator.java index 5a9aa38c42..023cfc9f53 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/file/transform/FixedLengthLineAggregator.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/file/transform/FixedLengthLineAggregator.java @@ -1,180 +1,180 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.batch.io.file.transform; - -import java.util.Arrays; - -import org.springframework.batch.io.file.mapping.FieldSet; -import org.springframework.util.Assert; - -/** - * LineAggregator implementation which produces line by aggregating provided - * strings into columns with fixed length. Columns are specified by array of - * ranges ({@link #setColumns(Range[])}.
- * - * @author tomas.slanina - * @author peter.zozom - * @author Dave Syer - */ -public class FixedLengthLineAggregator implements LineAggregator { - - private static final int ALIGN_CENTER = 1; - private static final int ALIGN_RIGHT = 2; - private static final int ALIGN_LEFT = 3; - - private Range[] ranges; - private int lastColumn; - private int align = ALIGN_LEFT; - private char padding = ' '; - - /** - * Set column ranges. Used in conjunction with the - * {@link RangeArrayPropertyEditor} this property can be set in the form of - * a String describing the range boundaries, e.g. "1,4,7" or "1-3,4-6,7" or - * "1-2,4-5,7-10". - * - * @param columns - * array of Range objects which specify column start and end - * position - */ - public void setColumns(Range[] columns) { - Assert.notNull(columns); - lastColumn = findLastColumn(columns); - this.ranges = columns; - } - - /** - * Aggregate provided strings into single line using specified column - * ranges. - * - * @param fieldSet - * arrays of strings representing data to be aggregated - * @return aggregated strings - */ - public String aggregate(FieldSet fieldSet) { - - Assert.notNull(fieldSet); - Assert.notNull(ranges); - - String[] args = fieldSet.getValues(); - Assert.isTrue(args.length <= ranges.length, - "Number of arguments must match number of fields in a record"); - - // calculate line length - int lineLength = ranges[lastColumn].hasMaxValue() ? ranges[lastColumn] - .getMax() : ranges[lastColumn].getMin() - + args[lastColumn].length() - 1; - - // create stringBuffer with length of line filled with padding - // characters - char[] emptyLine = new char[lineLength]; - Arrays.fill(emptyLine, padding); - - StringBuffer stringBuffer = new StringBuffer(lineLength); - stringBuffer.append(emptyLine); - - // aggregate all strings - for (int i = 0; i < args.length; i++) { - - // offset where text will be inserted - int start = ranges[i].getMin() - 1; - - // calculate column length - int columnLength; - if ((i == lastColumn) && (!ranges[lastColumn].hasMaxValue())) { - columnLength = args[lastColumn].length(); - } else { - columnLength = ranges[i].getMax() - ranges[i].getMin() + 1; - } - - String textToInsert = (args[i] == null) ? "" : args[i]; - - Assert - .isTrue(columnLength >= textToInsert.length(), - "Supplied text: " + textToInsert - + " is longer than defined length: " - + columnLength); - - switch (align) { - case ALIGN_RIGHT: - start += (columnLength - textToInsert.length()); - break; - case ALIGN_CENTER: - start += ((columnLength - textToInsert.length()) / 2); - break; - case ALIGN_LEFT: - // nothing to do - break; - } - - stringBuffer.replace(start, start + textToInsert.length(), - textToInsert); - } - - return stringBuffer.toString(); - } - - /** - * Recognized alignments are CENTER, RIGHT, LEFT. An - * IllegalArgumentException is thrown in case the argument does not match - * any of the recognized values. - * - * @param alignment - * the alignment to be used - */ - public void setAlignment(String alignment) { - if ("CENTER".equalsIgnoreCase(alignment)) { - this.align = ALIGN_CENTER; - } else if ("RIGHT".equalsIgnoreCase(alignment)) { - this.align = ALIGN_RIGHT; - } else if ("LEFT".equalsIgnoreCase(alignment)) { - this.align = ALIGN_LEFT; - } else { - throw new IllegalArgumentException( - "Only 'CENTER', 'RIGHT' or 'LEFT' are allowed alignment values"); - } - } - - /** - * Setter for padding (default is space). - * - * @param padding - * the padding character - */ - public void setPadding(char padding) { - this.padding = padding; - } - - /* - * Find last column. Columns are not sorted. Returns index of last column - * (column with highest offset). - */ - private int findLastColumn(Range[] columns) { - - int lastOffset = 1; - int lastIndex = 0; - - for (int i = 0; i < columns.length; i++) { - if (columns[i].getMin() > lastOffset) { - lastOffset = columns[i].getMin(); - lastIndex = i; - } - } - - return lastIndex; - } -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.batch.io.file.transform; + +import java.util.Arrays; + +import org.springframework.batch.io.file.mapping.FieldSet; +import org.springframework.util.Assert; + +/** + * LineAggregator implementation which produces line by aggregating provided + * strings into columns with fixed length. Columns are specified by array of + * ranges ({@link #setColumns(Range[])}.
+ * + * @author tomas.slanina + * @author peter.zozom + * @author Dave Syer + */ +public class FixedLengthLineAggregator implements LineAggregator { + + private static final int ALIGN_CENTER = 1; + private static final int ALIGN_RIGHT = 2; + private static final int ALIGN_LEFT = 3; + + private Range[] ranges; + private int lastColumn; + private int align = ALIGN_LEFT; + private char padding = ' '; + + /** + * Set column ranges. Used in conjunction with the + * {@link RangeArrayPropertyEditor} this property can be set in the form of + * a String describing the range boundaries, e.g. "1,4,7" or "1-3,4-6,7" or + * "1-2,4-5,7-10". + * + * @param columns + * array of Range objects which specify column start and end + * position + */ + public void setColumns(Range[] columns) { + Assert.notNull(columns); + lastColumn = findLastColumn(columns); + this.ranges = columns; + } + + /** + * Aggregate provided strings into single line using specified column + * ranges. + * + * @param fieldSet + * arrays of strings representing data to be aggregated + * @return aggregated strings + */ + public String aggregate(FieldSet fieldSet) { + + Assert.notNull(fieldSet); + Assert.notNull(ranges); + + String[] args = fieldSet.getValues(); + Assert.isTrue(args.length <= ranges.length, + "Number of arguments must match number of fields in a record"); + + // calculate line length + int lineLength = ranges[lastColumn].hasMaxValue() ? ranges[lastColumn] + .getMax() : ranges[lastColumn].getMin() + + args[lastColumn].length() - 1; + + // create stringBuffer with length of line filled with padding + // characters + char[] emptyLine = new char[lineLength]; + Arrays.fill(emptyLine, padding); + + StringBuffer stringBuffer = new StringBuffer(lineLength); + stringBuffer.append(emptyLine); + + // aggregate all strings + for (int i = 0; i < args.length; i++) { + + // offset where text will be inserted + int start = ranges[i].getMin() - 1; + + // calculate column length + int columnLength; + if ((i == lastColumn) && (!ranges[lastColumn].hasMaxValue())) { + columnLength = args[lastColumn].length(); + } else { + columnLength = ranges[i].getMax() - ranges[i].getMin() + 1; + } + + String textToInsert = (args[i] == null) ? "" : args[i]; + + Assert + .isTrue(columnLength >= textToInsert.length(), + "Supplied text: " + textToInsert + + " is longer than defined length: " + + columnLength); + + switch (align) { + case ALIGN_RIGHT: + start += (columnLength - textToInsert.length()); + break; + case ALIGN_CENTER: + start += ((columnLength - textToInsert.length()) / 2); + break; + case ALIGN_LEFT: + // nothing to do + break; + } + + stringBuffer.replace(start, start + textToInsert.length(), + textToInsert); + } + + return stringBuffer.toString(); + } + + /** + * Recognized alignments are CENTER, RIGHT, LEFT. An + * IllegalArgumentException is thrown in case the argument does not match + * any of the recognized values. + * + * @param alignment + * the alignment to be used + */ + public void setAlignment(String alignment) { + if ("CENTER".equalsIgnoreCase(alignment)) { + this.align = ALIGN_CENTER; + } else if ("RIGHT".equalsIgnoreCase(alignment)) { + this.align = ALIGN_RIGHT; + } else if ("LEFT".equalsIgnoreCase(alignment)) { + this.align = ALIGN_LEFT; + } else { + throw new IllegalArgumentException( + "Only 'CENTER', 'RIGHT' or 'LEFT' are allowed alignment values"); + } + } + + /** + * Setter for padding (default is space). + * + * @param padding + * the padding character + */ + public void setPadding(char padding) { + this.padding = padding; + } + + /* + * Find last column. Columns are not sorted. Returns index of last column + * (column with highest offset). + */ + private int findLastColumn(Range[] columns) { + + int lastOffset = 1; + int lastIndex = 0; + + for (int i = 0; i < columns.length; i++) { + if (columns[i].getMin() > lastOffset) { + lastOffset = columns[i].getMin(); + lastIndex = i; + } + } + + return lastIndex; + } +} diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/file/transform/FixedLengthTokenizer.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/file/transform/FixedLengthTokenizer.java index 1cbe97a4dc..ed6f8d7ae4 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/file/transform/FixedLengthTokenizer.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/file/transform/FixedLengthTokenizer.java @@ -1,80 +1,80 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.batch.io.file.transform; - -import java.util.ArrayList; -import java.util.List; - -/** - * Tokenizer used to process data obtained from files with fixed-length format. - * Columns are specified by array of Range objects ({@link #setColumns(Range[])}). - * - * @author tomas.slanina - * @author peter.zozom - * @author Dave Syer - */ -public class FixedLengthTokenizer extends AbstractLineTokenizer { - - private Range[] ranges; - - /** - * Set the column ranges. Used in conjunction with the - * {@link RangeArrayPropertyEditor} this property can be set in the form of - * a String describing the range boundaries, e.g. "1,4,7" or "1-3,4-6,7" or - * "1-2,4-5,7-10". - * - * @param ranges the column ranges expected in the input - */ - public void setColumns(Range[] ranges) { - this.ranges = ranges; - } - - /** - * Yields the tokens resulting from the splitting of the supplied - * line. - * - * @param line - * the line to be tokenised (can be null) - * - * @return the resulting tokens (empty if the line is null) - */ - protected List doTokenize(String line) { - List tokens = new ArrayList(ranges.length); - int lineLength; - String token; - - lineLength = line.length(); - - for (int i = 0; i < ranges.length; i++) { - - int startPos = ranges[i].getMin() - 1; - int endPos = ranges[i].getMax(); - - if (lineLength >= endPos) { - token = line.substring(startPos, endPos); - } else if (lineLength >= startPos) { - token = line.substring(startPos); - } else { - token = ""; - } - - tokens.add(token); - } - - return tokens; - } -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.batch.io.file.transform; + +import java.util.ArrayList; +import java.util.List; + +/** + * Tokenizer used to process data obtained from files with fixed-length format. + * Columns are specified by array of Range objects ({@link #setColumns(Range[])}). + * + * @author tomas.slanina + * @author peter.zozom + * @author Dave Syer + */ +public class FixedLengthTokenizer extends AbstractLineTokenizer { + + private Range[] ranges; + + /** + * Set the column ranges. Used in conjunction with the + * {@link RangeArrayPropertyEditor} this property can be set in the form of + * a String describing the range boundaries, e.g. "1,4,7" or "1-3,4-6,7" or + * "1-2,4-5,7-10". + * + * @param ranges the column ranges expected in the input + */ + public void setColumns(Range[] ranges) { + this.ranges = ranges; + } + + /** + * Yields the tokens resulting from the splitting of the supplied + * line. + * + * @param line + * the line to be tokenised (can be null) + * + * @return the resulting tokens (empty if the line is null) + */ + protected List doTokenize(String line) { + List tokens = new ArrayList(ranges.length); + int lineLength; + String token; + + lineLength = line.length(); + + for (int i = 0; i < ranges.length; i++) { + + int startPos = ranges[i].getMin() - 1; + int endPos = ranges[i].getMax(); + + if (lineLength >= endPos) { + token = line.substring(startPos, endPos); + } else if (lineLength >= startPos) { + token = line.substring(startPos); + } else { + token = ""; + } + + tokens.add(token); + } + + return tokens; + } +} diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/file/transform/Range.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/file/transform/Range.java index 3718d9b905..10fd33eb55 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/file/transform/Range.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/file/transform/Range.java @@ -1,62 +1,62 @@ -package org.springframework.batch.io.file.transform; - -import org.springframework.util.Assert; - -/** - * A class to represent ranges. A Range can have minimum/maximum values from - * interval <1,Integer.MAX_VALUE-1> A Range can be unbounded at maximum - * side. This can be specified by passing {@link Range#UPPER_BORDER_NOT_DEFINED}} as max - * value or using constructor {@link #Range(int)}. - * - * @author peter.zozom - */ -public class Range { - - private final static int UPPER_BORDER_NOT_DEFINED = Integer.MAX_VALUE; - - private int min; - private int max; - - public Range(int min) { - checkMinMaxValues(min, UPPER_BORDER_NOT_DEFINED); - this.min = min; - this.max = UPPER_BORDER_NOT_DEFINED; - } - - public Range(int min, int max) { - checkMinMaxValues(min, max); - this.min = min; - this.max = max; - } - - public int getMax() { - return max; - } - - public int getMin() { - return min; - } - - public void setMax(int max) { - checkMinMaxValues(this.min, max); - this.max = max; - } - - public void setMin(int min) { - checkMinMaxValues(min, this.max); - this.min = min; - } - - public boolean hasMaxValue() { - return max != UPPER_BORDER_NOT_DEFINED; - } - - public String toString() { - return hasMaxValue() ? min + "-" + max : String.valueOf(min); - } - - private void checkMinMaxValues(int min, int max) { - Assert.isTrue(min>0, "Min value must be higher than zero"); - Assert.isTrue(min<=max, "Min value should be lower or equal to max value"); - } -} +package org.springframework.batch.io.file.transform; + +import org.springframework.util.Assert; + +/** + * A class to represent ranges. A Range can have minimum/maximum values from + * interval <1,Integer.MAX_VALUE-1> A Range can be unbounded at maximum + * side. This can be specified by passing {@link Range#UPPER_BORDER_NOT_DEFINED}} as max + * value or using constructor {@link #Range(int)}. + * + * @author peter.zozom + */ +public class Range { + + private final static int UPPER_BORDER_NOT_DEFINED = Integer.MAX_VALUE; + + private int min; + private int max; + + public Range(int min) { + checkMinMaxValues(min, UPPER_BORDER_NOT_DEFINED); + this.min = min; + this.max = UPPER_BORDER_NOT_DEFINED; + } + + public Range(int min, int max) { + checkMinMaxValues(min, max); + this.min = min; + this.max = max; + } + + public int getMax() { + return max; + } + + public int getMin() { + return min; + } + + public void setMax(int max) { + checkMinMaxValues(this.min, max); + this.max = max; + } + + public void setMin(int min) { + checkMinMaxValues(min, this.max); + this.min = min; + } + + public boolean hasMaxValue() { + return max != UPPER_BORDER_NOT_DEFINED; + } + + public String toString() { + return hasMaxValue() ? min + "-" + max : String.valueOf(min); + } + + private void checkMinMaxValues(int min, int max) { + Assert.isTrue(min>0, "Min value must be higher than zero"); + Assert.isTrue(min<=max, "Min value should be lower or equal to max value"); + } +} diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/file/transform/RangeArrayPropertyEditor.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/file/transform/RangeArrayPropertyEditor.java index a802eeb32c..60bf140615 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/file/transform/RangeArrayPropertyEditor.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/file/transform/RangeArrayPropertyEditor.java @@ -1,131 +1,131 @@ -package org.springframework.batch.io.file.transform; - -import java.beans.PropertyEditorSupport; -import java.util.Arrays; -import java.util.Comparator; - -import org.springframework.util.Assert; -import org.springframework.util.StringUtils; - -/** - * Property editor implementation which parses string and creates array of - * ranges. Ranges can be provided in any order.
Input string should be - * provided in following format: 'range1, range2, range3,...' where range is - * specified as: - *
    - *
  • 'X-Y', where X is minimum value and Y is maximum value (condition X<=Y - * is verified)
  • - *
  • or 'Z', where Z is minimum and maximum is calculated as (minimum of - * adjacent range - 1). Maximum of the last range is never calculated. Range - * stays unbound at maximum side if maximum value is not provided.
  • - *
- * Minimum and maximum values can be from interval <1, Integer.MAX_VALUE-1> - *

- * Examples:
- * '1, 15, 25, 38, 55-60' is equal to '1-14, 15-24, 25-37, 38-54, 55-60'
- * '36, 14, 1-10, 15, 49-57' is equal to '36-48, 14-14, 1-10, 15-35, 49-57' - *

- * Property editor also allows to validate whether ranges are disjoint. Validation - * can be turned on/off by using {@link #forceDisjointRanges}. By default - * validation is turned off. - * - * @author peter.zozom - */ -public class RangeArrayPropertyEditor extends PropertyEditorSupport { - - private boolean forceDisjointRanges = false; - - /** - * Set force disjoint ranges. If set to TRUE, ranges are validated to be disjoint. - * For example: defining ranges '1-10, 5-15' will cause IllegalArgumentException in - * case of forceDisjointRanges=TRUE. - * @param forceDisjointRanges - */ - public void setForceDisjointRanges(boolean forceDisjointRanges) { - this.forceDisjointRanges = forceDisjointRanges; - } - - public void setAsText(String text) throws IllegalArgumentException { - - //split text into ranges - String[] strRanges = text.split(","); - Range[] ranges = new Range[strRanges.length]; - - //parse ranges and create array of Range objects - for (int i = 0; i < strRanges.length; i++) { - String[] range = strRanges[i].split("-"); - - int min; - int max; - - if ((range.length == 1) && (StringUtils.hasText(range[0]))) { - min = Integer.parseInt(range[0].trim()); - // correct max value will be assigned later - ranges[i] = new Range(min); - } else if ((range.length == 2) && (StringUtils.hasText(range[0])) - && (StringUtils.hasText(range[1]))) { - min = Integer.parseInt(range[0].trim()); - max = Integer.parseInt(range[1].trim()); - ranges[i] = new Range(min,max); - } else { - throw new IllegalArgumentException("Range[" + i + "]: range (" + strRanges[i] + ") is invalid"); - } - - } - - setMaxValues(ranges); - setValue(ranges); - } - - public String getAsText() { - Range[] ranges = (Range[])getValue(); - - StringBuffer sb = new StringBuffer(); - - for (int i = 0; i < ranges.length; i++) { - if(i>0) { - sb.append(", "); - } - sb.append(ranges[i]); - } - return sb.toString(); - } - - private void setMaxValues(Range[] ranges) { - - //clone array, original array should stay same - Range[] c = (Range[])ranges.clone(); - - //sort array of Ranges - Arrays.sort(c, new Comparator() { - public int compare(Object o1, Object o2) { - Range c1 = (Range)o1; - Range c2 = (Range)o2; - return c1.getMin()-c2.getMin(); - } - } - ); - - //set max values for all unbound ranges (except last range) - for (int i = 0; i < c.length - 1; i++) { - if (!c[i].hasMaxValue()) { - //set max value to (min value - 1) of the next range - c[i].setMax(c[i+1].getMin() - 1); - } - } - - if (forceDisjointRanges) { - verifyRanges(c); - } - } - - - private void verifyRanges(Range[] ranges) { - //verify that ranges are disjoint - for(int i = 1; i < ranges.length;i++) { - Assert.isTrue(ranges[i-1].getMax() < ranges[i].getMin(), - "Ranges must be disjoint. Range[" + (i-1) + "]: (" + ranges[i-1] + - ") Range[" + i +"]: (" + ranges[i] + ")"); - } - } -} +package org.springframework.batch.io.file.transform; + +import java.beans.PropertyEditorSupport; +import java.util.Arrays; +import java.util.Comparator; + +import org.springframework.util.Assert; +import org.springframework.util.StringUtils; + +/** + * Property editor implementation which parses string and creates array of + * ranges. Ranges can be provided in any order.
Input string should be + * provided in following format: 'range1, range2, range3,...' where range is + * specified as: + *

    + *
  • 'X-Y', where X is minimum value and Y is maximum value (condition X<=Y + * is verified)
  • + *
  • or 'Z', where Z is minimum and maximum is calculated as (minimum of + * adjacent range - 1). Maximum of the last range is never calculated. Range + * stays unbound at maximum side if maximum value is not provided.
  • + *
+ * Minimum and maximum values can be from interval <1, Integer.MAX_VALUE-1> + *

+ * Examples:
+ * '1, 15, 25, 38, 55-60' is equal to '1-14, 15-24, 25-37, 38-54, 55-60'
+ * '36, 14, 1-10, 15, 49-57' is equal to '36-48, 14-14, 1-10, 15-35, 49-57' + *

+ * Property editor also allows to validate whether ranges are disjoint. Validation + * can be turned on/off by using {@link #forceDisjointRanges}. By default + * validation is turned off. + * + * @author peter.zozom + */ +public class RangeArrayPropertyEditor extends PropertyEditorSupport { + + private boolean forceDisjointRanges = false; + + /** + * Set force disjoint ranges. If set to TRUE, ranges are validated to be disjoint. + * For example: defining ranges '1-10, 5-15' will cause IllegalArgumentException in + * case of forceDisjointRanges=TRUE. + * @param forceDisjointRanges + */ + public void setForceDisjointRanges(boolean forceDisjointRanges) { + this.forceDisjointRanges = forceDisjointRanges; + } + + public void setAsText(String text) throws IllegalArgumentException { + + //split text into ranges + String[] strRanges = text.split(","); + Range[] ranges = new Range[strRanges.length]; + + //parse ranges and create array of Range objects + for (int i = 0; i < strRanges.length; i++) { + String[] range = strRanges[i].split("-"); + + int min; + int max; + + if ((range.length == 1) && (StringUtils.hasText(range[0]))) { + min = Integer.parseInt(range[0].trim()); + // correct max value will be assigned later + ranges[i] = new Range(min); + } else if ((range.length == 2) && (StringUtils.hasText(range[0])) + && (StringUtils.hasText(range[1]))) { + min = Integer.parseInt(range[0].trim()); + max = Integer.parseInt(range[1].trim()); + ranges[i] = new Range(min,max); + } else { + throw new IllegalArgumentException("Range[" + i + "]: range (" + strRanges[i] + ") is invalid"); + } + + } + + setMaxValues(ranges); + setValue(ranges); + } + + public String getAsText() { + Range[] ranges = (Range[])getValue(); + + StringBuffer sb = new StringBuffer(); + + for (int i = 0; i < ranges.length; i++) { + if(i>0) { + sb.append(", "); + } + sb.append(ranges[i]); + } + return sb.toString(); + } + + private void setMaxValues(Range[] ranges) { + + //clone array, original array should stay same + Range[] c = (Range[])ranges.clone(); + + //sort array of Ranges + Arrays.sort(c, new Comparator() { + public int compare(Object o1, Object o2) { + Range c1 = (Range)o1; + Range c2 = (Range)o2; + return c1.getMin()-c2.getMin(); + } + } + ); + + //set max values for all unbound ranges (except last range) + for (int i = 0; i < c.length - 1; i++) { + if (!c[i].hasMaxValue()) { + //set max value to (min value - 1) of the next range + c[i].setMax(c[i+1].getMin() - 1); + } + } + + if (forceDisjointRanges) { + verifyRanges(c); + } + } + + + private void verifyRanges(Range[] ranges) { + //verify that ranges are disjoint + for(int i = 1; i < ranges.length;i++) { + Assert.isTrue(ranges[i-1].getMax() < ranges[i].getMin(), + "Ranges must be disjoint. Range[" + (i-1) + "]: (" + ranges[i-1] + + ") Range[" + i +"]: (" + ranges[i] + ")"); + } + } +} diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/support/BatchSqlUpdateItemWriter.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/support/BatchSqlUpdateItemWriter.java index be0f410431..33a006da03 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/support/BatchSqlUpdateItemWriter.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/support/BatchSqlUpdateItemWriter.java @@ -1,227 +1,227 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.io.support; - -import java.sql.PreparedStatement; -import java.sql.SQLException; -import java.util.HashSet; -import java.util.Iterator; -import java.util.Set; - -import org.springframework.batch.item.ItemWriter; -import org.springframework.batch.item.exception.ClearFailedException; -import org.springframework.batch.item.exception.FlushFailedException; -import org.springframework.batch.repeat.RepeatContext; -import org.springframework.batch.repeat.synch.RepeatSynchronizationManager; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.dao.DataAccessException; -import org.springframework.jdbc.core.JdbcOperations; -import org.springframework.jdbc.core.PreparedStatementCallback; -import org.springframework.transaction.support.TransactionSynchronizationManager; -import org.springframework.util.Assert; - -/** - * {@link ItemWriter} that uses the batching features from - * {@link PreparedStatement} if available and can take some rudimentary steps to - * locate a failure during a flush, and identify the items that failed. When one - * of those items is encountered again the batch is flushed aggressively so that - * the bad item is eventually identified and can be dealt with in isolation.
- * - * The user must provide an SQL query and a special callback - * {@link ItemPreparedStatementSetter}, which is responsible for mapping the - * item to a PreparedStatement. - * - * @author Dave Syer - * - */ -public class BatchSqlUpdateItemWriter implements ItemWriter, InitializingBean { - - /** - * Key for items processed in the current transaction {@link RepeatContext}. - */ - protected static final String ITEMS_PROCESSED = BatchSqlUpdateItemWriter.class.getName() + ".ITEMS_PROCESSED"; - - private Set failed = new HashSet(); - - private JdbcOperations jdbcTemplate; - - private ItemPreparedStatementSetter preparedStatementSetter; - - private String sql; - - /** - * Public setter for the query string to execute on write. The parameters - * should correspond to those known to the - * {@link ItemPreparedStatementSetter}. - * @param sql the query to set - */ - public void setSql(String sql) { - this.sql = sql; - } - - /** - * Public setter for the {@link ItemPreparedStatementSetter}. - * @param preparedStatementSetter the {@link ItemPreparedStatementSetter} to - * set - */ - public void setItemPreparedStatementSetter(ItemPreparedStatementSetter preparedStatementSetter) { - this.preparedStatementSetter = preparedStatementSetter; - } - - /** - * Public setter for the {@link JdbcOperations}. - * @param jdbcTemplate the {@link JdbcOperations} to set - */ - public void setJdbcTemplate(JdbcOperations jdbcTemplate) { - this.jdbcTemplate = jdbcTemplate; - } - - /** - * Check mandatory properties - there must be a delegate. - * - * @see org.springframework.dao.support.DaoSupport#initDao() - */ - public void afterPropertiesSet() throws Exception { - Assert.notNull(jdbcTemplate, "BatchSqlUpdateItemWriter requires an data source."); - Assert.notNull(preparedStatementSetter, "BatchSqlUpdateItemWriter requires a ItemPreparedStatementSetter"); - } - - /** - * Buffer the item in a transaction resource, but flush aggressively if the - * item was previously part of a failed chunk. - * - * @throws Exception - * - * @see org.springframework.batch.io.OutputSource#write(java.lang.Object) - */ - public void write(Object output) throws Exception { - bindTransactionResources(); - getProcessed().add(output); - flushIfNecessary(output); - } - - /** - * Accessor for the list of processed items in this transaction. - * - * @return the processed - */ - private Set getProcessed() { - Assert.state(TransactionSynchronizationManager.hasResource(ITEMS_PROCESSED), - "Processed items not bound to transaction."); - Set processed = (Set) TransactionSynchronizationManager.getResource(ITEMS_PROCESSED); - return processed; - } - - /** - * Set up the {@link RepeatContext} as a transaction resource. - * - * @param context the context to set - */ - private void bindTransactionResources() { - if (TransactionSynchronizationManager.hasResource(ITEMS_PROCESSED)) { - return; - } - TransactionSynchronizationManager.bindResource(ITEMS_PROCESSED, new HashSet()); - } - - /** - * Remove the transaction resource associated with this context. - */ - private void unbindTransactionResources() { - if (!TransactionSynchronizationManager.hasResource(ITEMS_PROCESSED)) { - return; - } - TransactionSynchronizationManager.unbindResource(ITEMS_PROCESSED); - } - - /** - * Accessor for the context property. - * - * @param output - * - * @return the context - */ - private void flushIfNecessary(Object output) throws Exception { - boolean flush; - synchronized (failed) { - flush = failed.contains(output); - } - if (flush) { - RepeatContext context = RepeatSynchronizationManager.getContext(); - // Force early completion to commit aggressively if we encounter a - // failed item (from a failed chunk but we don't know which one was - // the problem). - context.setCompleteOnly(); - // Flush now, so that if there is a failure this record can be - // skipped. - doFlush(); - } - } - - /** - * Flush the hibernate session from within a repeat context. - */ - private void doFlush() { - final Set processed = getProcessed(); - try { - if (!processed.isEmpty()) { - jdbcTemplate.execute(sql, new PreparedStatementCallback() { - public Object doInPreparedStatement(PreparedStatement ps) throws SQLException, DataAccessException { - for (Iterator iterator = processed.iterator(); iterator.hasNext();) { - Object item = (Object) iterator.next(); - preparedStatementSetter.setValues(item, ps); - ps.addBatch(); - } - return ps.executeBatch(); - } - }); - } - } - catch (RuntimeException e) { - synchronized (failed) { - failed.addAll(processed); - } - throw e; - } - finally { - getProcessed().clear(); - } - } - - /** - * Unbind transaction resources, effectively clearing the item buffer. - * - * @see org.springframework.batch.item.ItemWriter#clear() - */ - public void clear() throws ClearFailedException { - unbindTransactionResources(); - } - - /** - * Flush the internal item buffer and record failures if there are any. - * - * @see org.springframework.batch.item.ItemWriter#flush() - */ - public void flush() throws FlushFailedException { - try { - doFlush(); - } - finally { - unbindTransactionResources(); - } - } - -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.io.support; + +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; + +import org.springframework.batch.item.ItemWriter; +import org.springframework.batch.item.exception.ClearFailedException; +import org.springframework.batch.item.exception.FlushFailedException; +import org.springframework.batch.repeat.RepeatContext; +import org.springframework.batch.repeat.synch.RepeatSynchronizationManager; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.dao.DataAccessException; +import org.springframework.jdbc.core.JdbcOperations; +import org.springframework.jdbc.core.PreparedStatementCallback; +import org.springframework.transaction.support.TransactionSynchronizationManager; +import org.springframework.util.Assert; + +/** + * {@link ItemWriter} that uses the batching features from + * {@link PreparedStatement} if available and can take some rudimentary steps to + * locate a failure during a flush, and identify the items that failed. When one + * of those items is encountered again the batch is flushed aggressively so that + * the bad item is eventually identified and can be dealt with in isolation.
+ * + * The user must provide an SQL query and a special callback + * {@link ItemPreparedStatementSetter}, which is responsible for mapping the + * item to a PreparedStatement. + * + * @author Dave Syer + * + */ +public class BatchSqlUpdateItemWriter implements ItemWriter, InitializingBean { + + /** + * Key for items processed in the current transaction {@link RepeatContext}. + */ + protected static final String ITEMS_PROCESSED = BatchSqlUpdateItemWriter.class.getName() + ".ITEMS_PROCESSED"; + + private Set failed = new HashSet(); + + private JdbcOperations jdbcTemplate; + + private ItemPreparedStatementSetter preparedStatementSetter; + + private String sql; + + /** + * Public setter for the query string to execute on write. The parameters + * should correspond to those known to the + * {@link ItemPreparedStatementSetter}. + * @param sql the query to set + */ + public void setSql(String sql) { + this.sql = sql; + } + + /** + * Public setter for the {@link ItemPreparedStatementSetter}. + * @param preparedStatementSetter the {@link ItemPreparedStatementSetter} to + * set + */ + public void setItemPreparedStatementSetter(ItemPreparedStatementSetter preparedStatementSetter) { + this.preparedStatementSetter = preparedStatementSetter; + } + + /** + * Public setter for the {@link JdbcOperations}. + * @param jdbcTemplate the {@link JdbcOperations} to set + */ + public void setJdbcTemplate(JdbcOperations jdbcTemplate) { + this.jdbcTemplate = jdbcTemplate; + } + + /** + * Check mandatory properties - there must be a delegate. + * + * @see org.springframework.dao.support.DaoSupport#initDao() + */ + public void afterPropertiesSet() throws Exception { + Assert.notNull(jdbcTemplate, "BatchSqlUpdateItemWriter requires an data source."); + Assert.notNull(preparedStatementSetter, "BatchSqlUpdateItemWriter requires a ItemPreparedStatementSetter"); + } + + /** + * Buffer the item in a transaction resource, but flush aggressively if the + * item was previously part of a failed chunk. + * + * @throws Exception + * + * @see org.springframework.batch.io.OutputSource#write(java.lang.Object) + */ + public void write(Object output) throws Exception { + bindTransactionResources(); + getProcessed().add(output); + flushIfNecessary(output); + } + + /** + * Accessor for the list of processed items in this transaction. + * + * @return the processed + */ + private Set getProcessed() { + Assert.state(TransactionSynchronizationManager.hasResource(ITEMS_PROCESSED), + "Processed items not bound to transaction."); + Set processed = (Set) TransactionSynchronizationManager.getResource(ITEMS_PROCESSED); + return processed; + } + + /** + * Set up the {@link RepeatContext} as a transaction resource. + * + * @param context the context to set + */ + private void bindTransactionResources() { + if (TransactionSynchronizationManager.hasResource(ITEMS_PROCESSED)) { + return; + } + TransactionSynchronizationManager.bindResource(ITEMS_PROCESSED, new HashSet()); + } + + /** + * Remove the transaction resource associated with this context. + */ + private void unbindTransactionResources() { + if (!TransactionSynchronizationManager.hasResource(ITEMS_PROCESSED)) { + return; + } + TransactionSynchronizationManager.unbindResource(ITEMS_PROCESSED); + } + + /** + * Accessor for the context property. + * + * @param output + * + * @return the context + */ + private void flushIfNecessary(Object output) throws Exception { + boolean flush; + synchronized (failed) { + flush = failed.contains(output); + } + if (flush) { + RepeatContext context = RepeatSynchronizationManager.getContext(); + // Force early completion to commit aggressively if we encounter a + // failed item (from a failed chunk but we don't know which one was + // the problem). + context.setCompleteOnly(); + // Flush now, so that if there is a failure this record can be + // skipped. + doFlush(); + } + } + + /** + * Flush the hibernate session from within a repeat context. + */ + private void doFlush() { + final Set processed = getProcessed(); + try { + if (!processed.isEmpty()) { + jdbcTemplate.execute(sql, new PreparedStatementCallback() { + public Object doInPreparedStatement(PreparedStatement ps) throws SQLException, DataAccessException { + for (Iterator iterator = processed.iterator(); iterator.hasNext();) { + Object item = (Object) iterator.next(); + preparedStatementSetter.setValues(item, ps); + ps.addBatch(); + } + return ps.executeBatch(); + } + }); + } + } + catch (RuntimeException e) { + synchronized (failed) { + failed.addAll(processed); + } + throw e; + } + finally { + getProcessed().clear(); + } + } + + /** + * Unbind transaction resources, effectively clearing the item buffer. + * + * @see org.springframework.batch.item.ItemWriter#clear() + */ + public void clear() throws ClearFailedException { + unbindTransactionResources(); + } + + /** + * Flush the internal item buffer and record failures if there are any. + * + * @see org.springframework.batch.item.ItemWriter#flush() + */ + public void flush() throws FlushFailedException { + try { + doFlush(); + } + finally { + unbindTransactionResources(); + } + } + +} diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/support/FileUtils.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/support/FileUtils.java index fbd5b8391b..82f2e79d76 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/support/FileUtils.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/support/FileUtils.java @@ -1,66 +1,66 @@ -package org.springframework.batch.io.support; - -import java.io.File; -import java.io.IOException; - -import org.springframework.dao.DataAccessResourceFailureException; -import org.springframework.util.Assert; - -/** - * Utility methods for files used in batch processing. - * - * @author Peter Zozom - */ -public class FileUtils { - - // forbids instantiation - private FileUtils() {} - - /** - * Set up output file for batch processing. This method implements common logic for - * handling output files when starting or restarting job/step. - * When starting output file processing, method creates/overwrites new file. - * When restarting output file processing, method checks whether file is writable. - * - * @param file file to be set up - * @param restarted TRUE signalizes that we are restarting output file processing - * @param overwriteOutputFile If set to TRUE, output file will be overwritten - * (this flag is ignored when processing is restart) - * - * @throws IllegalArgumentException when file is NULL - * @throws IllegalStateException when staring output file processing, file exists and - * flag "shouldDeleteExisting" is set to FALSE - * @throws DataAccessResourceFailureException when unable to create file or file is not writable - */ - public static void setUpOutputFile(File file, boolean restarted, - boolean overwriteOutputFile) { - - Assert.notNull(file); - - try { - if (!restarted) { - if (file.exists()) { - if(!overwriteOutputFile){ - throw new DataAccessResourceFailureException("File already exists: [" - + file.getAbsolutePath() + "]"); - } - file.delete(); - } - - if (file.getParent() != null ) { - new File(file.getParent()).mkdirs(); - } - file.createNewFile(); - } - } catch (IOException ioe) { - throw new DataAccessResourceFailureException( - "Unable to create file: [" + file.getAbsolutePath() + "]", - ioe); - } - - if (!file.canWrite()) { - throw new DataAccessResourceFailureException( - "File is not writable: [" + file.getAbsolutePath() + "]"); - } - } -} +package org.springframework.batch.io.support; + +import java.io.File; +import java.io.IOException; + +import org.springframework.dao.DataAccessResourceFailureException; +import org.springframework.util.Assert; + +/** + * Utility methods for files used in batch processing. + * + * @author Peter Zozom + */ +public class FileUtils { + + // forbids instantiation + private FileUtils() {} + + /** + * Set up output file for batch processing. This method implements common logic for + * handling output files when starting or restarting job/step. + * When starting output file processing, method creates/overwrites new file. + * When restarting output file processing, method checks whether file is writable. + * + * @param file file to be set up + * @param restarted TRUE signalizes that we are restarting output file processing + * @param overwriteOutputFile If set to TRUE, output file will be overwritten + * (this flag is ignored when processing is restart) + * + * @throws IllegalArgumentException when file is NULL + * @throws IllegalStateException when staring output file processing, file exists and + * flag "shouldDeleteExisting" is set to FALSE + * @throws DataAccessResourceFailureException when unable to create file or file is not writable + */ + public static void setUpOutputFile(File file, boolean restarted, + boolean overwriteOutputFile) { + + Assert.notNull(file); + + try { + if (!restarted) { + if (file.exists()) { + if(!overwriteOutputFile){ + throw new DataAccessResourceFailureException("File already exists: [" + + file.getAbsolutePath() + "]"); + } + file.delete(); + } + + if (file.getParent() != null ) { + new File(file.getParent()).mkdirs(); + } + file.createNewFile(); + } + } catch (IOException ioe) { + throw new DataAccessResourceFailureException( + "Unable to create file: [" + file.getAbsolutePath() + "]", + ioe); + } + + if (!file.canWrite()) { + throw new DataAccessResourceFailureException( + "File is not writable: [" + file.getAbsolutePath() + "]"); + } + } +} diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/support/HibernateAwareItemWriter.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/support/HibernateAwareItemWriter.java index 46a003acec..f8f5f71ce8 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/support/HibernateAwareItemWriter.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/support/HibernateAwareItemWriter.java @@ -1,210 +1,210 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.io.support; - -import java.util.HashSet; -import java.util.Set; - -import org.hibernate.SessionFactory; -import org.springframework.batch.item.ItemWriter; -import org.springframework.batch.item.exception.ClearFailedException; -import org.springframework.batch.item.exception.FlushFailedException; -import org.springframework.batch.repeat.RepeatContext; -import org.springframework.batch.repeat.synch.RepeatSynchronizationManager; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.orm.hibernate3.HibernateOperations; -import org.springframework.orm.hibernate3.HibernateTemplate; -import org.springframework.transaction.support.TransactionSynchronizationManager; -import org.springframework.util.Assert; - -/** - * {@link ItemWriter} that is aware of the Hibernate session and can take some - * responsibilities to do with chunk boundaries away from a less smart - * {@link ItemWriter} (the delegate). A delegate is required, and will be used - * to do the actual writing of the item.
- * - * @author Dave Syer - * - */ -public class HibernateAwareItemWriter implements ItemWriter, InitializingBean { - - /** - * Key for items processed in the current transaction {@link RepeatContext}. - */ - private static final String ITEMS_PROCESSED = HibernateAwareItemWriter.class.getName() + ".ITEMS_PROCESSED"; - - private Set failed = new HashSet(); - - private ItemWriter delegate; - - private HibernateOperations hibernateTemplate; - - /** - * Public setter for the {@link ItemWriter} property. - * - * @param delegate the delegate to set - */ - public void setDelegate(ItemWriter delegate) { - this.delegate = delegate; - } - - /** - * Public setter for the {@link HibernateOperations} property. - * - * @param hibernateTemplate the hibernateTemplate to set - */ - public void setHibernateTemplate(HibernateOperations hibernateTemplate) { - this.hibernateTemplate = hibernateTemplate; - } - - /** - * Set the Hibernate SessionFactory to be used internally. Will - * automatically create a HibernateTemplate for the given SessionFactory. - * - * @see #setHibernateTemplate - */ - public final void setSessionFactory(SessionFactory sessionFactory) { - this.hibernateTemplate = new HibernateTemplate(sessionFactory); - } - - /** - * Check mandatory properties - there must be a delegate. - * - * @see org.springframework.dao.support.DaoSupport#initDao() - */ - public void afterPropertiesSet() throws Exception { - Assert.notNull(delegate, "HibernateAwareItemWriter requires an ItemWriter as a delegate."); - Assert.notNull(hibernateTemplate, "HibernateAwareItemWriter requires a HibernateOperations"); - } - - /** - * Use the delegate to actually do the writing, but flush aggressively if - * the item was previously part of a failed chunk. - * - * @throws Exception - * - * @see org.springframework.batch.io.OutputSource#write(java.lang.Object) - */ - public void write(Object output) throws Exception { - bindTransactionResources(); - getProcessed().add(output); - delegate.write(output); - flushIfNecessary(output); - } - - /** - * Accessor for the list of processed items in this transaction. - * - * @return the processed - */ - private Set getProcessed() { - Assert.state(TransactionSynchronizationManager.hasResource(ITEMS_PROCESSED), - "Processed items not bound to transaction."); - Set processed = (Set) TransactionSynchronizationManager.getResource(ITEMS_PROCESSED); - return processed; - } - - /** - * Set up the {@link RepeatContext} as a transaction resource. - * - * @param context the context to set - */ - private void bindTransactionResources() { - if (TransactionSynchronizationManager.hasResource(ITEMS_PROCESSED)) { - return; - } - TransactionSynchronizationManager.bindResource(ITEMS_PROCESSED, new HashSet()); - } - - /** - * Remove the transaction resource associated with this context. - */ - private void unbindTransactionResources() { - if (!TransactionSynchronizationManager.hasResource(ITEMS_PROCESSED)) { - return; - } - TransactionSynchronizationManager.unbindResource(ITEMS_PROCESSED); - } - - /** - * Accessor for the context property. - * - * @param output - * - * @return the context - */ - private void flushIfNecessary(Object output) throws Exception { - boolean flush; - synchronized (failed) { - flush = failed.contains(output); - } - if (flush) { - RepeatContext context = RepeatSynchronizationManager.getContext(); - // Force early completion to commit aggressively if we encounter a - // failed item (from a failed chunk but we don't know which one was - // the problem). - context.setCompleteOnly(); - // Flush now, so that if there is a failure this record can be - // skipped. - doHibernateFlush(); - } - } - - /** - * Flush the hibernate session from within a repeat context. - */ - private void doHibernateFlush() { - try { - hibernateTemplate.flush(); - // This should happen when the transaction commits anyway, but to be - // sure... - hibernateTemplate.clear(); - } - catch (RuntimeException e) { - synchronized (failed) { - failed.addAll(getProcessed()); - } - // This used to contain a call to onError, however, I think this - // should be handled within the step. - throw e; - } - } - - /** - * Call the delegate clear() method, and then clear the hibernate session. - * - * @see org.springframework.batch.item.ItemWriter#clear() - */ - public void clear() throws ClearFailedException { - unbindTransactionResources(); - hibernateTemplate.clear(); - delegate.clear(); - } - - /** - * Flush the Hibernate session and record failures if there are any. The - * delegate flush will also be called. - * - * @see org.springframework.batch.item.ItemWriter#flush() - */ - public void flush() throws FlushFailedException { - bindTransactionResources(); - doHibernateFlush(); - unbindTransactionResources(); - delegate.flush(); - } - -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.io.support; + +import java.util.HashSet; +import java.util.Set; + +import org.hibernate.SessionFactory; +import org.springframework.batch.item.ItemWriter; +import org.springframework.batch.item.exception.ClearFailedException; +import org.springframework.batch.item.exception.FlushFailedException; +import org.springframework.batch.repeat.RepeatContext; +import org.springframework.batch.repeat.synch.RepeatSynchronizationManager; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.orm.hibernate3.HibernateOperations; +import org.springframework.orm.hibernate3.HibernateTemplate; +import org.springframework.transaction.support.TransactionSynchronizationManager; +import org.springframework.util.Assert; + +/** + * {@link ItemWriter} that is aware of the Hibernate session and can take some + * responsibilities to do with chunk boundaries away from a less smart + * {@link ItemWriter} (the delegate). A delegate is required, and will be used + * to do the actual writing of the item.
+ * + * @author Dave Syer + * + */ +public class HibernateAwareItemWriter implements ItemWriter, InitializingBean { + + /** + * Key for items processed in the current transaction {@link RepeatContext}. + */ + private static final String ITEMS_PROCESSED = HibernateAwareItemWriter.class.getName() + ".ITEMS_PROCESSED"; + + private Set failed = new HashSet(); + + private ItemWriter delegate; + + private HibernateOperations hibernateTemplate; + + /** + * Public setter for the {@link ItemWriter} property. + * + * @param delegate the delegate to set + */ + public void setDelegate(ItemWriter delegate) { + this.delegate = delegate; + } + + /** + * Public setter for the {@link HibernateOperations} property. + * + * @param hibernateTemplate the hibernateTemplate to set + */ + public void setHibernateTemplate(HibernateOperations hibernateTemplate) { + this.hibernateTemplate = hibernateTemplate; + } + + /** + * Set the Hibernate SessionFactory to be used internally. Will + * automatically create a HibernateTemplate for the given SessionFactory. + * + * @see #setHibernateTemplate + */ + public final void setSessionFactory(SessionFactory sessionFactory) { + this.hibernateTemplate = new HibernateTemplate(sessionFactory); + } + + /** + * Check mandatory properties - there must be a delegate. + * + * @see org.springframework.dao.support.DaoSupport#initDao() + */ + public void afterPropertiesSet() throws Exception { + Assert.notNull(delegate, "HibernateAwareItemWriter requires an ItemWriter as a delegate."); + Assert.notNull(hibernateTemplate, "HibernateAwareItemWriter requires a HibernateOperations"); + } + + /** + * Use the delegate to actually do the writing, but flush aggressively if + * the item was previously part of a failed chunk. + * + * @throws Exception + * + * @see org.springframework.batch.io.OutputSource#write(java.lang.Object) + */ + public void write(Object output) throws Exception { + bindTransactionResources(); + getProcessed().add(output); + delegate.write(output); + flushIfNecessary(output); + } + + /** + * Accessor for the list of processed items in this transaction. + * + * @return the processed + */ + private Set getProcessed() { + Assert.state(TransactionSynchronizationManager.hasResource(ITEMS_PROCESSED), + "Processed items not bound to transaction."); + Set processed = (Set) TransactionSynchronizationManager.getResource(ITEMS_PROCESSED); + return processed; + } + + /** + * Set up the {@link RepeatContext} as a transaction resource. + * + * @param context the context to set + */ + private void bindTransactionResources() { + if (TransactionSynchronizationManager.hasResource(ITEMS_PROCESSED)) { + return; + } + TransactionSynchronizationManager.bindResource(ITEMS_PROCESSED, new HashSet()); + } + + /** + * Remove the transaction resource associated with this context. + */ + private void unbindTransactionResources() { + if (!TransactionSynchronizationManager.hasResource(ITEMS_PROCESSED)) { + return; + } + TransactionSynchronizationManager.unbindResource(ITEMS_PROCESSED); + } + + /** + * Accessor for the context property. + * + * @param output + * + * @return the context + */ + private void flushIfNecessary(Object output) throws Exception { + boolean flush; + synchronized (failed) { + flush = failed.contains(output); + } + if (flush) { + RepeatContext context = RepeatSynchronizationManager.getContext(); + // Force early completion to commit aggressively if we encounter a + // failed item (from a failed chunk but we don't know which one was + // the problem). + context.setCompleteOnly(); + // Flush now, so that if there is a failure this record can be + // skipped. + doHibernateFlush(); + } + } + + /** + * Flush the hibernate session from within a repeat context. + */ + private void doHibernateFlush() { + try { + hibernateTemplate.flush(); + // This should happen when the transaction commits anyway, but to be + // sure... + hibernateTemplate.clear(); + } + catch (RuntimeException e) { + synchronized (failed) { + failed.addAll(getProcessed()); + } + // This used to contain a call to onError, however, I think this + // should be handled within the step. + throw e; + } + } + + /** + * Call the delegate clear() method, and then clear the hibernate session. + * + * @see org.springframework.batch.item.ItemWriter#clear() + */ + public void clear() throws ClearFailedException { + unbindTransactionResources(); + hibernateTemplate.clear(); + delegate.clear(); + } + + /** + * Flush the Hibernate session and record failures if there are any. The + * delegate flush will also be called. + * + * @see org.springframework.batch.item.ItemWriter#flush() + */ + public void flush() throws FlushFailedException { + bindTransactionResources(); + doHibernateFlush(); + unbindTransactionResources(); + delegate.flush(); + } + +} diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/xml/EventReaderDeserializer.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/xml/EventReaderDeserializer.java index b4bfea8ebe..1036ca2442 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/xml/EventReaderDeserializer.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/xml/EventReaderDeserializer.java @@ -1,14 +1,14 @@ -package org.springframework.batch.io.xml; - -import javax.xml.stream.XMLEventReader; - -/** - * Deserializes XML fragment to domain object. - * XML fragment is a standalone XML document corresponding to a single record. - * - * @author Robert Kasanicky - */ -public interface EventReaderDeserializer { - - Object deserializeFragment(XMLEventReader eventReader); -} +package org.springframework.batch.io.xml; + +import javax.xml.stream.XMLEventReader; + +/** + * Deserializes XML fragment to domain object. + * XML fragment is a standalone XML document corresponding to a single record. + * + * @author Robert Kasanicky + */ +public interface EventReaderDeserializer { + + Object deserializeFragment(XMLEventReader eventReader); +} diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/xml/EventWriterSerializer.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/xml/EventWriterSerializer.java index 0f665ce5b8..e2dbde1776 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/xml/EventWriterSerializer.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/xml/EventWriterSerializer.java @@ -1,21 +1,21 @@ -package org.springframework.batch.io.xml; - -import javax.xml.stream.XMLEventWriter; - -/** - * Interface wrapping the serialization of an object - * to xml. Primarily useful for abstracting how an object - * is serialized to an XMLEvent from a specific marshaller. - * - * @author Lucas Ward - * - */ -public interface EventWriterSerializer { - - /** - * Serialize an Object. - * - * @param output - */ - void serializeObject(XMLEventWriter writer, Object output); -} +package org.springframework.batch.io.xml; + +import javax.xml.stream.XMLEventWriter; + +/** + * Interface wrapping the serialization of an object + * to xml. Primarily useful for abstracting how an object + * is serialized to an XMLEvent from a specific marshaller. + * + * @author Lucas Ward + * + */ +public interface EventWriterSerializer { + + /** + * Serialize an Object. + * + * @param output + */ + void serializeObject(XMLEventWriter writer, Object output); +} diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/xml/StaxEventItemReader.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/xml/StaxEventItemReader.java index 2f1d1586f7..491a3bd341 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/xml/StaxEventItemReader.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/xml/StaxEventItemReader.java @@ -1,269 +1,269 @@ -package org.springframework.batch.io.xml; - -import java.io.IOException; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.List; - -import javax.xml.namespace.QName; -import javax.xml.stream.XMLEventReader; -import javax.xml.stream.XMLInputFactory; -import javax.xml.stream.XMLStreamException; -import javax.xml.stream.events.StartElement; - -import org.springframework.batch.io.Skippable; -import org.springframework.batch.io.xml.stax.DefaultFragmentEventReader; -import org.springframework.batch.io.xml.stax.DefaultTransactionalEventReader; -import org.springframework.batch.io.xml.stax.FragmentEventReader; -import org.springframework.batch.io.xml.stax.TransactionalEventReader; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.item.ExecutionContextUserSupport; -import org.springframework.batch.item.ItemReader; -import org.springframework.batch.item.ItemStream; -import org.springframework.batch.item.exception.StreamException; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.core.io.Resource; -import org.springframework.dao.DataAccessResourceFailureException; -import org.springframework.util.Assert; - -/** - * Input source for reading XML input based on StAX. - * - * It extracts fragments from the input XML document which correspond to records - * for processing. The fragments are wrapped with StartDocument and EndDocument - * events so that the fragments can be further processed like standalone XML - * documents. - * - * @author Robert Kasanicky - */ -public class StaxEventItemReader extends ExecutionContextUserSupport implements ItemReader, Skippable, ItemStream, - InitializingBean { - - private static final String READ_COUNT_STATISTICS_NAME = "read.count"; - - private FragmentEventReader fragmentReader; - - private TransactionalEventReader txReader; - - private EventReaderDeserializer eventReaderDeserializer; - - private Resource resource; - - private InputStream inputStream; - - private String fragmentRootElementName; - - private boolean initialized = false; - - private long lastCommitPointRecordCount = 0; - - private long currentRecordCount = 0; - - private List skipRecords = new ArrayList(); - - private boolean saveState = false; - - public StaxEventItemReader() { - setName(StaxEventItemReader.class.getSimpleName()); - } - - /** - * Read in the next root element from the file, and return it. - * - * @return the next available record, if none exist, return null - * @see org.springframework.batch.io.ItemReader#read() - */ - public Object read() { - if (!initialized) { - throw new StreamException("ItemStream must be open before it can be read."); - } - Object item = null; - - do { - currentRecordCount++; - if (moveCursorToNextFragment(fragmentReader)) { - fragmentReader.markStartFragment(); - item = eventReaderDeserializer.deserializeFragment(fragmentReader); - fragmentReader.markFragmentProcessed(); - } - } while (skipRecords.contains(new Long(currentRecordCount))); - - if (item == null) { - currentRecordCount--; - } - return item; - } - - public void close(ExecutionContext executionContext) { - initialized = false; - if (fragmentReader == null && inputStream == null) { - return; - } - try { - fragmentReader.close(); - inputStream.close(); - } - catch (XMLStreamException e) { - throw new DataAccessResourceFailureException("Error while closing event reader", e); - } - catch (IOException e) { - throw new DataAccessResourceFailureException("Error while closing input stream", e); - } - finally { - fragmentReader = null; - inputStream = null; - } - } - - public void open(ExecutionContext executionContext) { - Assert.state(resource.exists(), "Input resource does not exist: [" + resource + "]"); - - try { - inputStream = resource.getInputStream(); - txReader = new DefaultTransactionalEventReader(XMLInputFactory.newInstance().createXMLEventReader( - inputStream)); - fragmentReader = new DefaultFragmentEventReader(txReader); - } - catch (XMLStreamException xse) { - throw new DataAccessResourceFailureException("Unable to create XML reader", xse); - } - catch (IOException ioe) { - throw new DataAccessResourceFailureException("Unable to get input stream", ioe); - } - initialized = true; - - if (executionContext.containsKey(getKey(READ_COUNT_STATISTICS_NAME))) { - long restoredRecordCount = executionContext.getLong(getKey(READ_COUNT_STATISTICS_NAME)); - int REASONABLE_ADHOC_COMMIT_FREQUENCY = 100; - while (currentRecordCount <= restoredRecordCount) { - currentRecordCount++; - if (currentRecordCount % REASONABLE_ADHOC_COMMIT_FREQUENCY == 0) { - txReader.onCommit(); // reset the history buffer - } - if (!fragmentReader.hasNext()) { - throw new StreamException("Restore point must be before end of input"); - } - fragmentReader.next(); - moveCursorToNextFragment(fragmentReader); - } - mark(); // reset the history buffer - } - } - - public void setResource(Resource resource) { - this.resource = resource; - } - - /** - * @param eventReaderDeserializer maps xml fragments corresponding to - * records to objects - */ - public void setFragmentDeserializer(EventReaderDeserializer eventReaderDeserializer) { - this.eventReaderDeserializer = eventReaderDeserializer; - } - - /** - * @param fragmentRootElementName name of the root element of the fragment - * TODO String can be ambiguous due to namespaces, use QName? - */ - public void setFragmentRootElementName(String fragmentRootElementName) { - this.fragmentRootElementName = fragmentRootElementName; - } - - /** - * Mark the last read record as 'skipped', so that I will not be returned - * from read() in the case of a rollback. - * - * @see Skippable#skip() - */ - public void skip() { - skipRecords.add(new Long(currentRecordCount)); - } - - /** - * Ensure that all required dependencies for the ItemReader to run are - * provided after all properties have been set. - * - * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet() - * @throws IllegalArgumentException if the Resource, FragmentDeserializer or - * FragmentRootElementName is null, or if the root element is empty. - * @throws IllegalStateException if the Resource does not exist. - */ - public void afterPropertiesSet() throws Exception { - Assert.notNull(resource, "The Resource must not be null."); - Assert.notNull(eventReaderDeserializer, "The FragmentDeserializer must not be null."); - Assert.hasLength(fragmentRootElementName, "The FragmentRootElementName must not be null"); - } - - /** - * @see ItemStream#update(ExecutionContext) - */ - public void update(ExecutionContext executionContext) { - if(saveState){ - Assert.notNull(executionContext, "ExecutionContext must not be null"); - executionContext.putLong(getKey(READ_COUNT_STATISTICS_NAME), currentRecordCount); - } - } - - /** - * Responsible for moving the cursor before the StartElement of the fragment - * root. - * - * This implementation simply looks for the next corresponding element, it - * does not care about element nesting. You will need to override this - * method to correctly handle composite fragments. - * - * @return true if next fragment was found, - * false otherwise. - */ - protected boolean moveCursorToNextFragment(XMLEventReader reader) { - try { - while (true) { - while (reader.peek() != null && !reader.peek().isStartElement()) { - reader.nextEvent(); - } - if (reader.peek() == null) { - return false; - } - QName startElementName = ((StartElement) reader.peek()).getName(); - if (startElementName.getLocalPart().equals(fragmentRootElementName)) { - return true; - } - else { - reader.nextEvent(); - } - } - } - catch (XMLStreamException e) { - throw new DataAccessResourceFailureException("Error while reading from event reader", e); - } - } - - /** - * Mark is supported as long as this {@link ItemStream} is used in a - * single-threaded environment. The state backing the mark is a single - * counter, keeping track of the current position, so multiple threads - * cannot be accommodated. - * - * @see org.springframework.batch.item.reader.AbstractItemReader#mark() - */ - public void mark() { - lastCommitPointRecordCount = currentRecordCount; - txReader.onCommit(); - skipRecords = new ArrayList(); - } - - /* - * (non-Javadoc) - * @see org.springframework.batch.item.ItemStream#reset(org.springframework.batch.item.ExecutionContext) - */ - public void reset() { - currentRecordCount = lastCommitPointRecordCount; - txReader.onRollback(); - fragmentReader.reset(); - } - - public void setSaveState(boolean saveState) { - this.saveState = saveState; - } -} +package org.springframework.batch.io.xml; + +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; + +import javax.xml.namespace.QName; +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.events.StartElement; + +import org.springframework.batch.io.Skippable; +import org.springframework.batch.io.xml.stax.DefaultFragmentEventReader; +import org.springframework.batch.io.xml.stax.DefaultTransactionalEventReader; +import org.springframework.batch.io.xml.stax.FragmentEventReader; +import org.springframework.batch.io.xml.stax.TransactionalEventReader; +import org.springframework.batch.item.ExecutionContext; +import org.springframework.batch.item.ExecutionContextUserSupport; +import org.springframework.batch.item.ItemReader; +import org.springframework.batch.item.ItemStream; +import org.springframework.batch.item.exception.StreamException; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.core.io.Resource; +import org.springframework.dao.DataAccessResourceFailureException; +import org.springframework.util.Assert; + +/** + * Input source for reading XML input based on StAX. + * + * It extracts fragments from the input XML document which correspond to records + * for processing. The fragments are wrapped with StartDocument and EndDocument + * events so that the fragments can be further processed like standalone XML + * documents. + * + * @author Robert Kasanicky + */ +public class StaxEventItemReader extends ExecutionContextUserSupport implements ItemReader, Skippable, ItemStream, + InitializingBean { + + private static final String READ_COUNT_STATISTICS_NAME = "read.count"; + + private FragmentEventReader fragmentReader; + + private TransactionalEventReader txReader; + + private EventReaderDeserializer eventReaderDeserializer; + + private Resource resource; + + private InputStream inputStream; + + private String fragmentRootElementName; + + private boolean initialized = false; + + private long lastCommitPointRecordCount = 0; + + private long currentRecordCount = 0; + + private List skipRecords = new ArrayList(); + + private boolean saveState = false; + + public StaxEventItemReader() { + setName(StaxEventItemReader.class.getSimpleName()); + } + + /** + * Read in the next root element from the file, and return it. + * + * @return the next available record, if none exist, return null + * @see org.springframework.batch.io.ItemReader#read() + */ + public Object read() { + if (!initialized) { + throw new StreamException("ItemStream must be open before it can be read."); + } + Object item = null; + + do { + currentRecordCount++; + if (moveCursorToNextFragment(fragmentReader)) { + fragmentReader.markStartFragment(); + item = eventReaderDeserializer.deserializeFragment(fragmentReader); + fragmentReader.markFragmentProcessed(); + } + } while (skipRecords.contains(new Long(currentRecordCount))); + + if (item == null) { + currentRecordCount--; + } + return item; + } + + public void close(ExecutionContext executionContext) { + initialized = false; + if (fragmentReader == null && inputStream == null) { + return; + } + try { + fragmentReader.close(); + inputStream.close(); + } + catch (XMLStreamException e) { + throw new DataAccessResourceFailureException("Error while closing event reader", e); + } + catch (IOException e) { + throw new DataAccessResourceFailureException("Error while closing input stream", e); + } + finally { + fragmentReader = null; + inputStream = null; + } + } + + public void open(ExecutionContext executionContext) { + Assert.state(resource.exists(), "Input resource does not exist: [" + resource + "]"); + + try { + inputStream = resource.getInputStream(); + txReader = new DefaultTransactionalEventReader(XMLInputFactory.newInstance().createXMLEventReader( + inputStream)); + fragmentReader = new DefaultFragmentEventReader(txReader); + } + catch (XMLStreamException xse) { + throw new DataAccessResourceFailureException("Unable to create XML reader", xse); + } + catch (IOException ioe) { + throw new DataAccessResourceFailureException("Unable to get input stream", ioe); + } + initialized = true; + + if (executionContext.containsKey(getKey(READ_COUNT_STATISTICS_NAME))) { + long restoredRecordCount = executionContext.getLong(getKey(READ_COUNT_STATISTICS_NAME)); + int REASONABLE_ADHOC_COMMIT_FREQUENCY = 100; + while (currentRecordCount <= restoredRecordCount) { + currentRecordCount++; + if (currentRecordCount % REASONABLE_ADHOC_COMMIT_FREQUENCY == 0) { + txReader.onCommit(); // reset the history buffer + } + if (!fragmentReader.hasNext()) { + throw new StreamException("Restore point must be before end of input"); + } + fragmentReader.next(); + moveCursorToNextFragment(fragmentReader); + } + mark(); // reset the history buffer + } + } + + public void setResource(Resource resource) { + this.resource = resource; + } + + /** + * @param eventReaderDeserializer maps xml fragments corresponding to + * records to objects + */ + public void setFragmentDeserializer(EventReaderDeserializer eventReaderDeserializer) { + this.eventReaderDeserializer = eventReaderDeserializer; + } + + /** + * @param fragmentRootElementName name of the root element of the fragment + * TODO String can be ambiguous due to namespaces, use QName? + */ + public void setFragmentRootElementName(String fragmentRootElementName) { + this.fragmentRootElementName = fragmentRootElementName; + } + + /** + * Mark the last read record as 'skipped', so that I will not be returned + * from read() in the case of a rollback. + * + * @see Skippable#skip() + */ + public void skip() { + skipRecords.add(new Long(currentRecordCount)); + } + + /** + * Ensure that all required dependencies for the ItemReader to run are + * provided after all properties have been set. + * + * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet() + * @throws IllegalArgumentException if the Resource, FragmentDeserializer or + * FragmentRootElementName is null, or if the root element is empty. + * @throws IllegalStateException if the Resource does not exist. + */ + public void afterPropertiesSet() throws Exception { + Assert.notNull(resource, "The Resource must not be null."); + Assert.notNull(eventReaderDeserializer, "The FragmentDeserializer must not be null."); + Assert.hasLength(fragmentRootElementName, "The FragmentRootElementName must not be null"); + } + + /** + * @see ItemStream#update(ExecutionContext) + */ + public void update(ExecutionContext executionContext) { + if(saveState){ + Assert.notNull(executionContext, "ExecutionContext must not be null"); + executionContext.putLong(getKey(READ_COUNT_STATISTICS_NAME), currentRecordCount); + } + } + + /** + * Responsible for moving the cursor before the StartElement of the fragment + * root. + * + * This implementation simply looks for the next corresponding element, it + * does not care about element nesting. You will need to override this + * method to correctly handle composite fragments. + * + * @return true if next fragment was found, + * false otherwise. + */ + protected boolean moveCursorToNextFragment(XMLEventReader reader) { + try { + while (true) { + while (reader.peek() != null && !reader.peek().isStartElement()) { + reader.nextEvent(); + } + if (reader.peek() == null) { + return false; + } + QName startElementName = ((StartElement) reader.peek()).getName(); + if (startElementName.getLocalPart().equals(fragmentRootElementName)) { + return true; + } + else { + reader.nextEvent(); + } + } + } + catch (XMLStreamException e) { + throw new DataAccessResourceFailureException("Error while reading from event reader", e); + } + } + + /** + * Mark is supported as long as this {@link ItemStream} is used in a + * single-threaded environment. The state backing the mark is a single + * counter, keeping track of the current position, so multiple threads + * cannot be accommodated. + * + * @see org.springframework.batch.item.reader.AbstractItemReader#mark() + */ + public void mark() { + lastCommitPointRecordCount = currentRecordCount; + txReader.onCommit(); + skipRecords = new ArrayList(); + } + + /* + * (non-Javadoc) + * @see org.springframework.batch.item.ItemStream#reset(org.springframework.batch.item.ExecutionContext) + */ + public void reset() { + currentRecordCount = lastCommitPointRecordCount; + txReader.onRollback(); + fragmentReader.reset(); + } + + public void setSaveState(boolean saveState) { + this.saveState = saveState; + } +} diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/xml/StaxEventItemWriter.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/xml/StaxEventItemWriter.java index ec3de640f9..32e2341936 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/xml/StaxEventItemWriter.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/xml/StaxEventItemWriter.java @@ -1,447 +1,447 @@ -package org.springframework.batch.io.xml; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.nio.ByteBuffer; -import java.nio.channels.FileChannel; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -import javax.xml.stream.XMLEventFactory; -import javax.xml.stream.XMLEventWriter; -import javax.xml.stream.XMLOutputFactory; -import javax.xml.stream.XMLStreamException; - -import org.springframework.batch.io.support.FileUtils; -import org.springframework.batch.io.xml.stax.NoStartEndDocumentStreamWriter; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.item.ExecutionContextUserSupport; -import org.springframework.batch.item.ItemStream; -import org.springframework.batch.item.ItemWriter; -import org.springframework.batch.item.exception.ClearFailedException; -import org.springframework.batch.item.exception.FlushFailedException; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.core.io.Resource; -import org.springframework.dao.DataAccessResourceFailureException; -import org.springframework.util.Assert; -import org.springframework.util.CollectionUtils; - -/** - * An implementation of {@link ItemWriter} which uses StAX and - * {@link EventWriterSerializer} for serializing object to XML. - * - * This item writer also provides restart, statistics and transaction features - * by implementing corresponding interfaces. - * - * Output is buffered until {@link #flush()} is called - only then the actual - * writing to file takes place. - * - * @author Peter Zozom - * @author Robert Kasanicky - * - */ -public class StaxEventItemWriter extends ExecutionContextUserSupport implements ItemWriter, ItemStream, - InitializingBean { - - // default encoding - private static final String DEFAULT_ENCODING = "UTF-8"; - - // default encoding - private static final String DEFAULT_XML_VERSION = "1.0"; - - // default root tag name - private static final String DEFAULT_ROOT_TAG_NAME = "root"; - - // restart data property name - private static final String RESTART_DATA_NAME = "position"; - - // restart data property name - private static final String WRITE_STATISTICS_NAME = "record.count"; - - // file system resource - private Resource resource; - - // xml serializer - private EventWriterSerializer serializer; - - // encoding to be used while reading from the resource - private String encoding = DEFAULT_ENCODING; - - // XML version - private String version = DEFAULT_XML_VERSION; - - // name of the root tag - private String rootTagName = DEFAULT_ROOT_TAG_NAME; - - // root element attributes - private Map rootElementAttributes = null; - - // signalizes that marshalling was restarted - private boolean restarted = false; - - // TRUE means, that output file will be overwritten if exists - default is - // TRUE - private boolean overwriteOutput = true; - - // file channel - private FileChannel channel; - - // wrapper for XML event writer that swallows StartDocument and EndDocument - // events - private XMLEventWriter eventWriter; - - // XML event writer - private XMLEventWriter delegateEventWriter; - - // byte offset in file channel at last commit point - private long lastCommitPointPosition = 0; - - // processed record count at last commit point - private long lastCommitPointRecordCount = 0; - - // current count of processed records - private long currentRecordCount = 0; - - private boolean saveState = false; - - // holds the list of items for writing before they are actually written on - // #flush() - private List buffer = new ArrayList(); - - public StaxEventItemWriter() { - setName(StaxEventItemWriter.class.getSimpleName()); - } - - /** - * Set output file. - * - * @param resource the output file - */ - public void setResource(Resource resource) { - this.resource = resource; - } - - /** - * Set Object to XML serializer. - * - * @param serializer the Object to XML serializer - */ - public void setSerializer(EventWriterSerializer serializer) { - this.serializer = serializer; - } - - /** - * Get used encoding. - * - * @return the encoding used - */ - public String getEncoding() { - return encoding; - } - - /** - * Set encoding to be used for output file. - * - * @param encoding the encoding to be used - */ - public void setEncoding(String encoding) { - this.encoding = encoding; - } - - /** - * Get XML version. - * - * @return the XML version used - */ - public String getVersion() { - return version; - } - - /** - * Set XML version to be used for output XML. - * - * @param version the XML version to be used - */ - public void setVersion(String version) { - this.version = version; - } - - /** - * Get the tag name of the root element. - * - * @return the root element tag name - */ - public String getRootTagName() { - return rootTagName; - } - - /** - * Set the tag name of the root element. If not set, default name is used - * ("root"). - * - * @param rootTagName the tag name to be used for the root element - */ - public void setRootTagName(String rootTagName) { - this.rootTagName = rootTagName; - } - - /** - * Get attributes of the root element. - * - * @return attributes of the root element - */ - public Map getRootElementAttributes() { - return rootElementAttributes; - } - - /** - * Set the root element attributes to be written. - * - * @param rootElementAttributes attributes of the root element - */ - public void setRootElementAttributes(Map rootElementAttributes) { - this.rootElementAttributes = rootElementAttributes; - } - - /** - * Set "overwrite" flag for the output file. Flag is ignored when output - * file processing is restarted. - * - * @param shouldDeleteIfExists - */ - public void setOverwriteOutput(boolean overwriteOutput) { - this.overwriteOutput = overwriteOutput; - } - - /** - * @throws Exception - * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet() - */ - public void afterPropertiesSet() throws Exception { - Assert.notNull(resource); - Assert.notNull(serializer); - } - - /** - * Open the output source - * - * @see org.springframework.batch.item.ResourceLifecycle#open() - */ - public void open(ExecutionContext executionContext) { - long startAtPosition = 0; - - // if restart data is provided, restart from provided offset - // otherwise start from beginning - if (executionContext.containsKey(getKey(RESTART_DATA_NAME))) { - startAtPosition = executionContext.getLong(getKey(RESTART_DATA_NAME)); - restarted = true; - } - - open(startAtPosition); - } - - /** - * Helper method for opening output source at given file position - */ - private void open(long position) { - - File file; - FileOutputStream os = null; - - try { - file = resource.getFile(); - FileUtils.setUpOutputFile(file, restarted, overwriteOutput); - os = new FileOutputStream(file, true); - channel = os.getChannel(); - setPosition(position); - } - catch (IOException ioe) { - throw new DataAccessResourceFailureException("Unable to write to file resource: [" + resource + "]", ioe); - } - - XMLOutputFactory outputFactory = XMLOutputFactory.newInstance(); - - try { - delegateEventWriter = outputFactory.createXMLEventWriter(os, encoding); - eventWriter = new NoStartEndDocumentStreamWriter(delegateEventWriter); - if (!restarted) { - startDocument(delegateEventWriter); - } - } - catch (XMLStreamException xse) { - throw new DataAccessResourceFailureException("Unable to write to file resource: [" + resource + "]", xse); - } - - } - - /** - * Writes simple XML header containing: - *

    - *
  • xml declaration - defines encoding and XML version
  • - *
  • opening tag of the root element and its attributes
  • - *
- * If this is not sufficient for you, simply override this method. Encoding, - * version and root tag name can be retrieved with corresponding getters. - * - * @param writer XML event writer - * @throws XMLStreamException - */ - private void startDocument(XMLEventWriter writer) throws XMLStreamException { - - XMLEventFactory factory = XMLEventFactory.newInstance(); - - // write start document - writer.add(factory.createStartDocument(getEncoding(), getVersion())); - - // write root tag - writer.add(factory.createStartElement("", "", getRootTagName())); - - // write root tag attributes - if (!CollectionUtils.isEmpty(getRootElementAttributes())) { - - for (Iterator i = getRootElementAttributes().entrySet().iterator(); i.hasNext();) { - Map.Entry entry = (Map.Entry) i.next(); - writer.add(factory.createAttribute((String) entry.getKey(), (String) entry.getValue())); - } - - } - - } - - /** - * Finishes the XML document. It closes any start tag and writes - * corresponding end tags. - * - * @param writer XML event writer - * @throws XMLStreamException - */ - private void endDocument(XMLEventWriter writer) throws XMLStreamException { - - // writer.writeEndDocument(); <- this doesn't work after restart - // we need to write end tag of the root element manually - writer.flush(); - ByteBuffer bbuf = ByteBuffer.wrap(("").getBytes()); - try { - channel.write(bbuf); - } - catch (IOException ioe) { - throw new DataAccessResourceFailureException("Unable to close file resource: [" + resource + "]", ioe); - } - } - - /** - * Flush and close the output source. - * - * @see org.springframework.batch.item.ResourceLifecycle#close(ExecutionContext) - */ - public void close(ExecutionContext executionContext) { - flush(); - try { - endDocument(delegateEventWriter); - eventWriter.close(); - channel.close(); - } - catch (XMLStreamException xse) { - throw new DataAccessResourceFailureException("Unable to close file resource: [" + resource + "]", xse); - } - catch (IOException ioe) { - throw new DataAccessResourceFailureException("Unable to close file resource: [" + resource + "]", ioe); - } - } - - /** - * Write the value object to internal buffer. - * - * @param item the value object - * @see #flush() - */ - public void write(Object item) { - - currentRecordCount++; - buffer.add(item); - } - - /** - * Get the restart data. - * @see org.springframework.batch.item.ItemStream#update(ExecutionContext) - */ - public void update(ExecutionContext executionContext) { - - if (saveState) { - Assert.notNull(executionContext, "ExecutionContext must not be null"); - executionContext.putLong(getKey(RESTART_DATA_NAME), getPosition()); - executionContext.putLong(getKey(WRITE_STATISTICS_NAME), currentRecordCount); - } - } - - /* - * Get the actual position in file channel. This method flushes any buffered - * data before position is read. - * - * @return byte offset in file channel - */ - private long getPosition() { - - long position; - - try { - eventWriter.flush(); - position = channel.position(); - } - catch (Exception e) { - throw new DataAccessResourceFailureException("Unable to write to file resource: [" + resource + "]", e); - } - - return position; - } - - /** - * Set the file channel position. - * - * @param newPosition new file channel position - */ - private void setPosition(long newPosition) { - - try { - Assert.state(channel.size() >= lastCommitPointPosition, - "Current file size is smaller than size at last commit"); - channel.truncate(newPosition); - channel.position(newPosition); - } - catch (IOException e) { - throw new DataAccessResourceFailureException("Unable to write to file resource: [" + resource + "]", e); - } - - } - - /** - * Writes buffered items to XML stream and marks restore point. - */ - public void flush() throws FlushFailedException { - - for (Iterator iterator = buffer.listIterator(); iterator.hasNext();) { - Object item = iterator.next(); - serializer.serializeObject(eventWriter, item); - } - buffer.clear(); - - lastCommitPointPosition = getPosition(); - lastCommitPointRecordCount = currentRecordCount; - } - - /** - * Clear the output buffer - */ - public void clear() throws ClearFailedException { - currentRecordCount = lastCommitPointRecordCount; - buffer.clear(); - } - - public void setSaveState(boolean saveState) { - this.saveState = saveState; - } - -} +package org.springframework.batch.io.xml; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.channels.FileChannel; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import javax.xml.stream.XMLEventFactory; +import javax.xml.stream.XMLEventWriter; +import javax.xml.stream.XMLOutputFactory; +import javax.xml.stream.XMLStreamException; + +import org.springframework.batch.io.support.FileUtils; +import org.springframework.batch.io.xml.stax.NoStartEndDocumentStreamWriter; +import org.springframework.batch.item.ExecutionContext; +import org.springframework.batch.item.ExecutionContextUserSupport; +import org.springframework.batch.item.ItemStream; +import org.springframework.batch.item.ItemWriter; +import org.springframework.batch.item.exception.ClearFailedException; +import org.springframework.batch.item.exception.FlushFailedException; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.core.io.Resource; +import org.springframework.dao.DataAccessResourceFailureException; +import org.springframework.util.Assert; +import org.springframework.util.CollectionUtils; + +/** + * An implementation of {@link ItemWriter} which uses StAX and + * {@link EventWriterSerializer} for serializing object to XML. + * + * This item writer also provides restart, statistics and transaction features + * by implementing corresponding interfaces. + * + * Output is buffered until {@link #flush()} is called - only then the actual + * writing to file takes place. + * + * @author Peter Zozom + * @author Robert Kasanicky + * + */ +public class StaxEventItemWriter extends ExecutionContextUserSupport implements ItemWriter, ItemStream, + InitializingBean { + + // default encoding + private static final String DEFAULT_ENCODING = "UTF-8"; + + // default encoding + private static final String DEFAULT_XML_VERSION = "1.0"; + + // default root tag name + private static final String DEFAULT_ROOT_TAG_NAME = "root"; + + // restart data property name + private static final String RESTART_DATA_NAME = "position"; + + // restart data property name + private static final String WRITE_STATISTICS_NAME = "record.count"; + + // file system resource + private Resource resource; + + // xml serializer + private EventWriterSerializer serializer; + + // encoding to be used while reading from the resource + private String encoding = DEFAULT_ENCODING; + + // XML version + private String version = DEFAULT_XML_VERSION; + + // name of the root tag + private String rootTagName = DEFAULT_ROOT_TAG_NAME; + + // root element attributes + private Map rootElementAttributes = null; + + // signalizes that marshalling was restarted + private boolean restarted = false; + + // TRUE means, that output file will be overwritten if exists - default is + // TRUE + private boolean overwriteOutput = true; + + // file channel + private FileChannel channel; + + // wrapper for XML event writer that swallows StartDocument and EndDocument + // events + private XMLEventWriter eventWriter; + + // XML event writer + private XMLEventWriter delegateEventWriter; + + // byte offset in file channel at last commit point + private long lastCommitPointPosition = 0; + + // processed record count at last commit point + private long lastCommitPointRecordCount = 0; + + // current count of processed records + private long currentRecordCount = 0; + + private boolean saveState = false; + + // holds the list of items for writing before they are actually written on + // #flush() + private List buffer = new ArrayList(); + + public StaxEventItemWriter() { + setName(StaxEventItemWriter.class.getSimpleName()); + } + + /** + * Set output file. + * + * @param resource the output file + */ + public void setResource(Resource resource) { + this.resource = resource; + } + + /** + * Set Object to XML serializer. + * + * @param serializer the Object to XML serializer + */ + public void setSerializer(EventWriterSerializer serializer) { + this.serializer = serializer; + } + + /** + * Get used encoding. + * + * @return the encoding used + */ + public String getEncoding() { + return encoding; + } + + /** + * Set encoding to be used for output file. + * + * @param encoding the encoding to be used + */ + public void setEncoding(String encoding) { + this.encoding = encoding; + } + + /** + * Get XML version. + * + * @return the XML version used + */ + public String getVersion() { + return version; + } + + /** + * Set XML version to be used for output XML. + * + * @param version the XML version to be used + */ + public void setVersion(String version) { + this.version = version; + } + + /** + * Get the tag name of the root element. + * + * @return the root element tag name + */ + public String getRootTagName() { + return rootTagName; + } + + /** + * Set the tag name of the root element. If not set, default name is used + * ("root"). + * + * @param rootTagName the tag name to be used for the root element + */ + public void setRootTagName(String rootTagName) { + this.rootTagName = rootTagName; + } + + /** + * Get attributes of the root element. + * + * @return attributes of the root element + */ + public Map getRootElementAttributes() { + return rootElementAttributes; + } + + /** + * Set the root element attributes to be written. + * + * @param rootElementAttributes attributes of the root element + */ + public void setRootElementAttributes(Map rootElementAttributes) { + this.rootElementAttributes = rootElementAttributes; + } + + /** + * Set "overwrite" flag for the output file. Flag is ignored when output + * file processing is restarted. + * + * @param shouldDeleteIfExists + */ + public void setOverwriteOutput(boolean overwriteOutput) { + this.overwriteOutput = overwriteOutput; + } + + /** + * @throws Exception + * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet() + */ + public void afterPropertiesSet() throws Exception { + Assert.notNull(resource); + Assert.notNull(serializer); + } + + /** + * Open the output source + * + * @see org.springframework.batch.item.ResourceLifecycle#open() + */ + public void open(ExecutionContext executionContext) { + long startAtPosition = 0; + + // if restart data is provided, restart from provided offset + // otherwise start from beginning + if (executionContext.containsKey(getKey(RESTART_DATA_NAME))) { + startAtPosition = executionContext.getLong(getKey(RESTART_DATA_NAME)); + restarted = true; + } + + open(startAtPosition); + } + + /** + * Helper method for opening output source at given file position + */ + private void open(long position) { + + File file; + FileOutputStream os = null; + + try { + file = resource.getFile(); + FileUtils.setUpOutputFile(file, restarted, overwriteOutput); + os = new FileOutputStream(file, true); + channel = os.getChannel(); + setPosition(position); + } + catch (IOException ioe) { + throw new DataAccessResourceFailureException("Unable to write to file resource: [" + resource + "]", ioe); + } + + XMLOutputFactory outputFactory = XMLOutputFactory.newInstance(); + + try { + delegateEventWriter = outputFactory.createXMLEventWriter(os, encoding); + eventWriter = new NoStartEndDocumentStreamWriter(delegateEventWriter); + if (!restarted) { + startDocument(delegateEventWriter); + } + } + catch (XMLStreamException xse) { + throw new DataAccessResourceFailureException("Unable to write to file resource: [" + resource + "]", xse); + } + + } + + /** + * Writes simple XML header containing: + *
    + *
  • xml declaration - defines encoding and XML version
  • + *
  • opening tag of the root element and its attributes
  • + *
+ * If this is not sufficient for you, simply override this method. Encoding, + * version and root tag name can be retrieved with corresponding getters. + * + * @param writer XML event writer + * @throws XMLStreamException + */ + private void startDocument(XMLEventWriter writer) throws XMLStreamException { + + XMLEventFactory factory = XMLEventFactory.newInstance(); + + // write start document + writer.add(factory.createStartDocument(getEncoding(), getVersion())); + + // write root tag + writer.add(factory.createStartElement("", "", getRootTagName())); + + // write root tag attributes + if (!CollectionUtils.isEmpty(getRootElementAttributes())) { + + for (Iterator i = getRootElementAttributes().entrySet().iterator(); i.hasNext();) { + Map.Entry entry = (Map.Entry) i.next(); + writer.add(factory.createAttribute((String) entry.getKey(), (String) entry.getValue())); + } + + } + + } + + /** + * Finishes the XML document. It closes any start tag and writes + * corresponding end tags. + * + * @param writer XML event writer + * @throws XMLStreamException + */ + private void endDocument(XMLEventWriter writer) throws XMLStreamException { + + // writer.writeEndDocument(); <- this doesn't work after restart + // we need to write end tag of the root element manually + writer.flush(); + ByteBuffer bbuf = ByteBuffer.wrap(("").getBytes()); + try { + channel.write(bbuf); + } + catch (IOException ioe) { + throw new DataAccessResourceFailureException("Unable to close file resource: [" + resource + "]", ioe); + } + } + + /** + * Flush and close the output source. + * + * @see org.springframework.batch.item.ResourceLifecycle#close(ExecutionContext) + */ + public void close(ExecutionContext executionContext) { + flush(); + try { + endDocument(delegateEventWriter); + eventWriter.close(); + channel.close(); + } + catch (XMLStreamException xse) { + throw new DataAccessResourceFailureException("Unable to close file resource: [" + resource + "]", xse); + } + catch (IOException ioe) { + throw new DataAccessResourceFailureException("Unable to close file resource: [" + resource + "]", ioe); + } + } + + /** + * Write the value object to internal buffer. + * + * @param item the value object + * @see #flush() + */ + public void write(Object item) { + + currentRecordCount++; + buffer.add(item); + } + + /** + * Get the restart data. + * @see org.springframework.batch.item.ItemStream#update(ExecutionContext) + */ + public void update(ExecutionContext executionContext) { + + if (saveState) { + Assert.notNull(executionContext, "ExecutionContext must not be null"); + executionContext.putLong(getKey(RESTART_DATA_NAME), getPosition()); + executionContext.putLong(getKey(WRITE_STATISTICS_NAME), currentRecordCount); + } + } + + /* + * Get the actual position in file channel. This method flushes any buffered + * data before position is read. + * + * @return byte offset in file channel + */ + private long getPosition() { + + long position; + + try { + eventWriter.flush(); + position = channel.position(); + } + catch (Exception e) { + throw new DataAccessResourceFailureException("Unable to write to file resource: [" + resource + "]", e); + } + + return position; + } + + /** + * Set the file channel position. + * + * @param newPosition new file channel position + */ + private void setPosition(long newPosition) { + + try { + Assert.state(channel.size() >= lastCommitPointPosition, + "Current file size is smaller than size at last commit"); + channel.truncate(newPosition); + channel.position(newPosition); + } + catch (IOException e) { + throw new DataAccessResourceFailureException("Unable to write to file resource: [" + resource + "]", e); + } + + } + + /** + * Writes buffered items to XML stream and marks restore point. + */ + public void flush() throws FlushFailedException { + + for (Iterator iterator = buffer.listIterator(); iterator.hasNext();) { + Object item = iterator.next(); + serializer.serializeObject(eventWriter, item); + } + buffer.clear(); + + lastCommitPointPosition = getPosition(); + lastCommitPointRecordCount = currentRecordCount; + } + + /** + * Clear the output buffer + */ + public void clear() throws ClearFailedException { + currentRecordCount = lastCommitPointRecordCount; + buffer.clear(); + } + + public void setSaveState(boolean saveState) { + this.saveState = saveState; + } + +} diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/xml/oxm/MarshallingEventWriterSerializer.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/xml/oxm/MarshallingEventWriterSerializer.java index 5057916b71..ea5790e038 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/xml/oxm/MarshallingEventWriterSerializer.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/xml/oxm/MarshallingEventWriterSerializer.java @@ -1,37 +1,37 @@ -package org.springframework.batch.io.xml.oxm; - -import java.io.IOException; - -import javax.xml.stream.XMLEventWriter; -import javax.xml.transform.Result; - -import org.springframework.batch.io.xml.EventWriterSerializer; -import org.springframework.dao.DataAccessResourceFailureException; -import org.springframework.oxm.Marshaller; -import org.springframework.xml.transform.StaxResult; - -/** - * Object to xml serializer that wraps a Spring OXM {@link Marshaller} object. - * - * @author Lucas Ward - * - */ -public class MarshallingEventWriterSerializer implements EventWriterSerializer { - - private Marshaller marshaller; - - public MarshallingEventWriterSerializer(Marshaller marshaller) { - this.marshaller = marshaller; - } - - public void serializeObject(XMLEventWriter writer, Object output) { - Result result = new StaxResult(writer); - try { - marshaller.marshal(output, result); - } - catch (IOException xse) { - throw new DataAccessResourceFailureException("Unable to write to file resource: [" + result.getSystemId() - + "]", xse); - } - } -} +package org.springframework.batch.io.xml.oxm; + +import java.io.IOException; + +import javax.xml.stream.XMLEventWriter; +import javax.xml.transform.Result; + +import org.springframework.batch.io.xml.EventWriterSerializer; +import org.springframework.dao.DataAccessResourceFailureException; +import org.springframework.oxm.Marshaller; +import org.springframework.xml.transform.StaxResult; + +/** + * Object to xml serializer that wraps a Spring OXM {@link Marshaller} object. + * + * @author Lucas Ward + * + */ +public class MarshallingEventWriterSerializer implements EventWriterSerializer { + + private Marshaller marshaller; + + public MarshallingEventWriterSerializer(Marshaller marshaller) { + this.marshaller = marshaller; + } + + public void serializeObject(XMLEventWriter writer, Object output) { + Result result = new StaxResult(writer); + try { + marshaller.marshal(output, result); + } + catch (IOException xse) { + throw new DataAccessResourceFailureException("Unable to write to file resource: [" + result.getSystemId() + + "]", xse); + } + } +} diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/xml/oxm/UnmarshallingEventReaderDeserializer.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/xml/oxm/UnmarshallingEventReaderDeserializer.java index d337c49aad..1301496d29 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/xml/oxm/UnmarshallingEventReaderDeserializer.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/xml/oxm/UnmarshallingEventReaderDeserializer.java @@ -1,38 +1,38 @@ -package org.springframework.batch.io.xml.oxm; - -import java.io.IOException; - -import javax.xml.stream.XMLEventReader; - -import org.springframework.batch.io.xml.EventReaderDeserializer; -import org.springframework.dao.DataAccessResourceFailureException; -import org.springframework.oxm.Unmarshaller; -import org.springframework.util.Assert; -import org.springframework.xml.transform.StaxSource; - -/** - * Delegates deserializing to Spring OXM {@link Unmarshaller}. - * - * @author Robert Kasanicky - * @author Lucas Ward - */ -public class UnmarshallingEventReaderDeserializer implements EventReaderDeserializer { - - private Unmarshaller unmarshaller; - - public UnmarshallingEventReaderDeserializer(Unmarshaller unmarshaller){ - Assert.notNull(unmarshaller); - this.unmarshaller = unmarshaller; - } - - public Object deserializeFragment(XMLEventReader eventReader) { - Object item = null; - try { - item = unmarshaller.unmarshal(new StaxSource(eventReader)); - } - catch (IOException e) { - throw new DataAccessResourceFailureException("IO error during unmarshalling", e); - } - return item; - } -} +package org.springframework.batch.io.xml.oxm; + +import java.io.IOException; + +import javax.xml.stream.XMLEventReader; + +import org.springframework.batch.io.xml.EventReaderDeserializer; +import org.springframework.dao.DataAccessResourceFailureException; +import org.springframework.oxm.Unmarshaller; +import org.springframework.util.Assert; +import org.springframework.xml.transform.StaxSource; + +/** + * Delegates deserializing to Spring OXM {@link Unmarshaller}. + * + * @author Robert Kasanicky + * @author Lucas Ward + */ +public class UnmarshallingEventReaderDeserializer implements EventReaderDeserializer { + + private Unmarshaller unmarshaller; + + public UnmarshallingEventReaderDeserializer(Unmarshaller unmarshaller){ + Assert.notNull(unmarshaller); + this.unmarshaller = unmarshaller; + } + + public Object deserializeFragment(XMLEventReader eventReader) { + Object item = null; + try { + item = unmarshaller.unmarshal(new StaxSource(eventReader)); + } + catch (IOException e) { + throw new DataAccessResourceFailureException("IO error during unmarshalling", e); + } + return item; + } +} diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/xml/stax/AbstractEventReaderWrapper.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/xml/stax/AbstractEventReaderWrapper.java index 630e167100..a87086f56b 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/xml/stax/AbstractEventReaderWrapper.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/xml/stax/AbstractEventReaderWrapper.java @@ -1,58 +1,58 @@ -package org.springframework.batch.io.xml.stax; - -import javax.xml.stream.XMLEventReader; -import javax.xml.stream.XMLStreamException; -import javax.xml.stream.events.XMLEvent; - -/** - * Delegates all functionality to the wrapped reader allowing - * subclasses to override only the methods they want to change. - * - * @author Robert Kasanicky - */ -abstract class AbstractEventReaderWrapper implements XMLEventReader { - - protected XMLEventReader wrappedEventReader; - - public AbstractEventReaderWrapper(XMLEventReader wrappedEventReader) { - this.wrappedEventReader = wrappedEventReader; - } - - public void close() throws XMLStreamException { - wrappedEventReader.close(); - - } - - public String getElementText() throws XMLStreamException { - return wrappedEventReader.getElementText(); - } - - public Object getProperty(String name) throws IllegalArgumentException { - return wrappedEventReader.getProperty(name); - } - - public boolean hasNext() { - return wrappedEventReader.hasNext(); - } - - public XMLEvent nextEvent() throws XMLStreamException { - return wrappedEventReader.nextEvent(); - } - - public XMLEvent nextTag() throws XMLStreamException { - return wrappedEventReader.nextTag(); - } - - public XMLEvent peek() throws XMLStreamException { - return wrappedEventReader.peek(); - } - - public Object next() { - return wrappedEventReader.next(); - } - - public void remove() { - wrappedEventReader.remove(); - } - -} +package org.springframework.batch.io.xml.stax; + +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.events.XMLEvent; + +/** + * Delegates all functionality to the wrapped reader allowing + * subclasses to override only the methods they want to change. + * + * @author Robert Kasanicky + */ +abstract class AbstractEventReaderWrapper implements XMLEventReader { + + protected XMLEventReader wrappedEventReader; + + public AbstractEventReaderWrapper(XMLEventReader wrappedEventReader) { + this.wrappedEventReader = wrappedEventReader; + } + + public void close() throws XMLStreamException { + wrappedEventReader.close(); + + } + + public String getElementText() throws XMLStreamException { + return wrappedEventReader.getElementText(); + } + + public Object getProperty(String name) throws IllegalArgumentException { + return wrappedEventReader.getProperty(name); + } + + public boolean hasNext() { + return wrappedEventReader.hasNext(); + } + + public XMLEvent nextEvent() throws XMLStreamException { + return wrappedEventReader.nextEvent(); + } + + public XMLEvent nextTag() throws XMLStreamException { + return wrappedEventReader.nextTag(); + } + + public XMLEvent peek() throws XMLStreamException { + return wrappedEventReader.peek(); + } + + public Object next() { + return wrappedEventReader.next(); + } + + public void remove() { + wrappedEventReader.remove(); + } + +} diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/xml/stax/AbstractEventWriterWrapper.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/xml/stax/AbstractEventWriterWrapper.java index 57464e91d0..a690e37b1d 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/xml/stax/AbstractEventWriterWrapper.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/xml/stax/AbstractEventWriterWrapper.java @@ -1,58 +1,58 @@ -package org.springframework.batch.io.xml.stax; - -import javax.xml.namespace.NamespaceContext; -import javax.xml.stream.XMLEventReader; -import javax.xml.stream.XMLEventWriter; -import javax.xml.stream.XMLStreamException; -import javax.xml.stream.events.XMLEvent; - -/** - * Delegates all functionality to the wrapped writer allowing - * subclasses to override only the methods they want to change. - * - * @author Robert Kasanicky - */ -abstract class AbstractEventWriterWrapper implements XMLEventWriter { - - protected XMLEventWriter wrappedEventWriter; - - public AbstractEventWriterWrapper(XMLEventWriter wrappedEventWriter) { - this.wrappedEventWriter = wrappedEventWriter; - } - - public void add(XMLEvent event) throws XMLStreamException { - wrappedEventWriter.add(event); - } - - public void add(XMLEventReader reader) throws XMLStreamException { - wrappedEventWriter.add(reader); - } - - public void close() throws XMLStreamException { - wrappedEventWriter.close(); - } - - public void flush() throws XMLStreamException { - wrappedEventWriter.flush(); - } - - public NamespaceContext getNamespaceContext() { - return wrappedEventWriter.getNamespaceContext(); - } - - public String getPrefix(String uri) throws XMLStreamException { - return wrappedEventWriter.getPrefix(uri); - } - - public void setDefaultNamespace(String uri) throws XMLStreamException { - wrappedEventWriter.setDefaultNamespace(uri); - } - - public void setNamespaceContext(NamespaceContext context) throws XMLStreamException { - wrappedEventWriter.setNamespaceContext(context); - } - - public void setPrefix(String prefix, String uri) throws XMLStreamException { - wrappedEventWriter.setPrefix(prefix, uri); - } -} +package org.springframework.batch.io.xml.stax; + +import javax.xml.namespace.NamespaceContext; +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.XMLEventWriter; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.events.XMLEvent; + +/** + * Delegates all functionality to the wrapped writer allowing + * subclasses to override only the methods they want to change. + * + * @author Robert Kasanicky + */ +abstract class AbstractEventWriterWrapper implements XMLEventWriter { + + protected XMLEventWriter wrappedEventWriter; + + public AbstractEventWriterWrapper(XMLEventWriter wrappedEventWriter) { + this.wrappedEventWriter = wrappedEventWriter; + } + + public void add(XMLEvent event) throws XMLStreamException { + wrappedEventWriter.add(event); + } + + public void add(XMLEventReader reader) throws XMLStreamException { + wrappedEventWriter.add(reader); + } + + public void close() throws XMLStreamException { + wrappedEventWriter.close(); + } + + public void flush() throws XMLStreamException { + wrappedEventWriter.flush(); + } + + public NamespaceContext getNamespaceContext() { + return wrappedEventWriter.getNamespaceContext(); + } + + public String getPrefix(String uri) throws XMLStreamException { + return wrappedEventWriter.getPrefix(uri); + } + + public void setDefaultNamespace(String uri) throws XMLStreamException { + wrappedEventWriter.setDefaultNamespace(uri); + } + + public void setNamespaceContext(NamespaceContext context) throws XMLStreamException { + wrappedEventWriter.setNamespaceContext(context); + } + + public void setPrefix(String prefix, String uri) throws XMLStreamException { + wrappedEventWriter.setPrefix(prefix, uri); + } +} diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/xml/stax/DefaultFragmentEventReader.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/xml/stax/DefaultFragmentEventReader.java index 996d71f8eb..43e43dbf86 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/xml/stax/DefaultFragmentEventReader.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/xml/stax/DefaultFragmentEventReader.java @@ -1,180 +1,180 @@ -package org.springframework.batch.io.xml.stax; - -import java.util.NoSuchElementException; - -import javax.xml.namespace.QName; -import javax.xml.stream.XMLEventFactory; -import javax.xml.stream.XMLEventReader; -import javax.xml.stream.XMLStreamException; -import javax.xml.stream.events.EndDocument; -import javax.xml.stream.events.EndElement; -import javax.xml.stream.events.StartDocument; -import javax.xml.stream.events.StartElement; -import javax.xml.stream.events.XMLEvent; - -import org.springframework.dao.DataAccessResourceFailureException; - -/** - * Default implementation of {@link FragmentEventReader} - * - * @author Robert Kasanicky - */ -public class DefaultFragmentEventReader extends AbstractEventReaderWrapper implements FragmentEventReader { - - // true when the next event is the StartElement of next fragment - private boolean startFragmentFollows = false; - - // true when the next event is the EndElement of current fragment - private boolean endFragmentFollows = false; - - // true while cursor is inside fragment - private boolean insideFragment = false; - - // true when reader should behave like the cursor was at the end of document - private boolean fakeDocumentEnd = false; - - private StartDocument startDocumentEvent = null; - - private EndDocument endDocumentEvent = null; - - // fragment root name is remembered so that the matching closing element can - // be identified - private QName fragmentRootName = null; - - // counts the occurrences of current fragmentRootName (increased for - // StartElement, decreased for EndElement) - private int matchCounter = 0; - - /** - * Caches the StartDocument event for later use. - * @param wrappedEventReader the original wrapped event reader - */ - public DefaultFragmentEventReader(XMLEventReader wrappedEventReader) { - super(wrappedEventReader); - try { - startDocumentEvent = (StartDocument) wrappedEventReader.peek(); - } - catch (XMLStreamException e) { - throw new DataAccessResourceFailureException("Error reading start document from event reader", e); - } - - endDocumentEvent = XMLEventFactory.newInstance().createEndDocument(); - } - - public void markStartFragment() { - startFragmentFollows = true; - fragmentRootName = null; - } - - public boolean hasNext() { - try { - if (peek() != null) { - return true; - } - } - catch (XMLStreamException e) { - throw new DataAccessResourceFailureException("Error reading XML stream", e); - } - return false; - } - - public Object next() { - try { - return nextEvent(); - } - catch (XMLStreamException e) { - throw new DataAccessResourceFailureException("Error reading XML stream", e); - } - } - - public XMLEvent nextEvent() throws XMLStreamException { - if (fakeDocumentEnd) { - throw new NoSuchElementException(); - } - XMLEvent event = wrappedEventReader.peek(); - XMLEvent proxyEvent = alterEvent(event, false); - checkFragmentEnd(proxyEvent); - if (event == proxyEvent) { - wrappedEventReader.nextEvent(); - } - - return proxyEvent; - } - - /** - * Sets the endFragmentFollows flag to true if next event is the last event - * of the fragment. - * @param event peek() from wrapped event reader - */ - private void checkFragmentEnd(XMLEvent event) { - if (event.isStartElement() && ((StartElement) event).getName().equals(fragmentRootName)) { - matchCounter++; - } - else if (event.isEndElement() && ((EndElement) event).getName().equals(fragmentRootName)) { - matchCounter--; - if (matchCounter == 0) { - endFragmentFollows = true; - } - } - } - - /** - * @param event peek() from wrapped event reader - * @param peek if true do not change the internal state - * @return StartDocument event if peek() points to beginning of fragment - * EndDocument event if cursor is right behind the end of fragment original - * event otherwise - */ - private XMLEvent alterEvent(XMLEvent event, boolean peek) { - if (startFragmentFollows) { - fragmentRootName = ((StartElement) event).getName(); - if (!peek) { - startFragmentFollows = false; - insideFragment = true; - } - return startDocumentEvent; - } - else if (endFragmentFollows) { - if (!peek) { - endFragmentFollows = false; - insideFragment = false; - fakeDocumentEnd = true; - } - return endDocumentEvent; - } - return event; - } - - public XMLEvent peek() throws XMLStreamException { - if (fakeDocumentEnd) { - return null; - } - return alterEvent(wrappedEventReader.peek(), true); - } - - /** - * Finishes reading the fragment in case the fragment was processed without - * being read until the end. - */ - public void markFragmentProcessed() { - if (insideFragment|| startFragmentFollows) { - try { - while (!(nextEvent() instanceof EndDocument)) { - // just read all events until EndDocument - } - } - catch (XMLStreamException e) { - throw new DataAccessResourceFailureException("Error reading XML stream", e); - } - } - fakeDocumentEnd = false; - } - - public void reset() { - insideFragment = false; - startFragmentFollows = false; - endFragmentFollows = false; - fakeDocumentEnd = false; - } - -} +package org.springframework.batch.io.xml.stax; + +import java.util.NoSuchElementException; + +import javax.xml.namespace.QName; +import javax.xml.stream.XMLEventFactory; +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.events.EndDocument; +import javax.xml.stream.events.EndElement; +import javax.xml.stream.events.StartDocument; +import javax.xml.stream.events.StartElement; +import javax.xml.stream.events.XMLEvent; + +import org.springframework.dao.DataAccessResourceFailureException; + +/** + * Default implementation of {@link FragmentEventReader} + * + * @author Robert Kasanicky + */ +public class DefaultFragmentEventReader extends AbstractEventReaderWrapper implements FragmentEventReader { + + // true when the next event is the StartElement of next fragment + private boolean startFragmentFollows = false; + + // true when the next event is the EndElement of current fragment + private boolean endFragmentFollows = false; + + // true while cursor is inside fragment + private boolean insideFragment = false; + + // true when reader should behave like the cursor was at the end of document + private boolean fakeDocumentEnd = false; + + private StartDocument startDocumentEvent = null; + + private EndDocument endDocumentEvent = null; + + // fragment root name is remembered so that the matching closing element can + // be identified + private QName fragmentRootName = null; + + // counts the occurrences of current fragmentRootName (increased for + // StartElement, decreased for EndElement) + private int matchCounter = 0; + + /** + * Caches the StartDocument event for later use. + * @param wrappedEventReader the original wrapped event reader + */ + public DefaultFragmentEventReader(XMLEventReader wrappedEventReader) { + super(wrappedEventReader); + try { + startDocumentEvent = (StartDocument) wrappedEventReader.peek(); + } + catch (XMLStreamException e) { + throw new DataAccessResourceFailureException("Error reading start document from event reader", e); + } + + endDocumentEvent = XMLEventFactory.newInstance().createEndDocument(); + } + + public void markStartFragment() { + startFragmentFollows = true; + fragmentRootName = null; + } + + public boolean hasNext() { + try { + if (peek() != null) { + return true; + } + } + catch (XMLStreamException e) { + throw new DataAccessResourceFailureException("Error reading XML stream", e); + } + return false; + } + + public Object next() { + try { + return nextEvent(); + } + catch (XMLStreamException e) { + throw new DataAccessResourceFailureException("Error reading XML stream", e); + } + } + + public XMLEvent nextEvent() throws XMLStreamException { + if (fakeDocumentEnd) { + throw new NoSuchElementException(); + } + XMLEvent event = wrappedEventReader.peek(); + XMLEvent proxyEvent = alterEvent(event, false); + checkFragmentEnd(proxyEvent); + if (event == proxyEvent) { + wrappedEventReader.nextEvent(); + } + + return proxyEvent; + } + + /** + * Sets the endFragmentFollows flag to true if next event is the last event + * of the fragment. + * @param event peek() from wrapped event reader + */ + private void checkFragmentEnd(XMLEvent event) { + if (event.isStartElement() && ((StartElement) event).getName().equals(fragmentRootName)) { + matchCounter++; + } + else if (event.isEndElement() && ((EndElement) event).getName().equals(fragmentRootName)) { + matchCounter--; + if (matchCounter == 0) { + endFragmentFollows = true; + } + } + } + + /** + * @param event peek() from wrapped event reader + * @param peek if true do not change the internal state + * @return StartDocument event if peek() points to beginning of fragment + * EndDocument event if cursor is right behind the end of fragment original + * event otherwise + */ + private XMLEvent alterEvent(XMLEvent event, boolean peek) { + if (startFragmentFollows) { + fragmentRootName = ((StartElement) event).getName(); + if (!peek) { + startFragmentFollows = false; + insideFragment = true; + } + return startDocumentEvent; + } + else if (endFragmentFollows) { + if (!peek) { + endFragmentFollows = false; + insideFragment = false; + fakeDocumentEnd = true; + } + return endDocumentEvent; + } + return event; + } + + public XMLEvent peek() throws XMLStreamException { + if (fakeDocumentEnd) { + return null; + } + return alterEvent(wrappedEventReader.peek(), true); + } + + /** + * Finishes reading the fragment in case the fragment was processed without + * being read until the end. + */ + public void markFragmentProcessed() { + if (insideFragment|| startFragmentFollows) { + try { + while (!(nextEvent() instanceof EndDocument)) { + // just read all events until EndDocument + } + } + catch (XMLStreamException e) { + throw new DataAccessResourceFailureException("Error reading XML stream", e); + } + } + fakeDocumentEnd = false; + } + + public void reset() { + insideFragment = false; + startFragmentFollows = false; + endFragmentFollows = false; + fakeDocumentEnd = false; + } + +} diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/xml/stax/DefaultTransactionalEventReader.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/xml/stax/DefaultTransactionalEventReader.java index 101e3df293..fb5aed6607 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/xml/stax/DefaultTransactionalEventReader.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/xml/stax/DefaultTransactionalEventReader.java @@ -1,96 +1,96 @@ -package org.springframework.batch.io.xml.stax; - -import java.util.NoSuchElementException; - -import javax.xml.stream.XMLEventReader; -import javax.xml.stream.XMLStreamException; -import javax.xml.stream.events.XMLEvent; - -import org.springframework.beans.factory.InitializingBean; -import org.springframework.util.Assert; - -/** - * Class used to wrap XMLEventReader. Events from wrapped reader are stored in - * {@link EventSequence} to support transactions. - * - * @author Tomas Slanina - * @author Robert Kasanicky - */ -public class DefaultTransactionalEventReader extends AbstractEventReaderWrapper implements TransactionalEventReader, InitializingBean { - - private EventSequence recorder = new EventSequence(); - - - /** - * Creates instance of this class and wraps XMLEventReader. - * - * @param parent event reader to be wrapped. - */ - public DefaultTransactionalEventReader(XMLEventReader wrappedReader) { - super(wrappedReader); - } - - public void afterPropertiesSet() throws Exception { - Assert.notNull(wrappedEventReader); - } - - /** - * Callback on transaction rollback. - */ - public void onRollback() { - recorder.reset(); - } - - /** - * Callback on transacion commit. - * - */ - public void onCommit() { - recorder.clear(); - } - - - /** - * Check if there are more events. Returns true if there are more events and - * false otherwise. - * - * @return true if the event reader has more events, false otherwise - */ - public boolean hasNext() { - return recorder.hasNext() || wrappedEventReader.hasNext(); - } - - /** - * Get the next XMLEvent - * - * @see XMLEvent - * @throws XMLStreamException if there is an error with the underlying XML. - * @throws NoSuchElementException iteration has no more elements. - */ - public XMLEvent nextEvent() throws XMLStreamException { - if (!recorder.hasNext()) { - recorder.addEvent(wrappedEventReader.nextEvent()); - } - return recorder.nextEvent(); - } - - /** - * Check the next XMLEvent without reading it from the stream. Returns null - * if the stream is at EOF or has no more XMLEvents. A call to peek() will - * be equal to the next return of next(). - * - * @see XMLEvent - * @throws XMLStreamException - */ - public XMLEvent peek() throws XMLStreamException { - return (recorder.hasNext()) ? recorder.peek() : wrappedEventReader.peek(); - } - - - /** - * In this implementation throws UnsupportedOperationException. - */ - public void remove() { - throw new UnsupportedOperationException(); - } -} +package org.springframework.batch.io.xml.stax; + +import java.util.NoSuchElementException; + +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.events.XMLEvent; + +import org.springframework.beans.factory.InitializingBean; +import org.springframework.util.Assert; + +/** + * Class used to wrap XMLEventReader. Events from wrapped reader are stored in + * {@link EventSequence} to support transactions. + * + * @author Tomas Slanina + * @author Robert Kasanicky + */ +public class DefaultTransactionalEventReader extends AbstractEventReaderWrapper implements TransactionalEventReader, InitializingBean { + + private EventSequence recorder = new EventSequence(); + + + /** + * Creates instance of this class and wraps XMLEventReader. + * + * @param parent event reader to be wrapped. + */ + public DefaultTransactionalEventReader(XMLEventReader wrappedReader) { + super(wrappedReader); + } + + public void afterPropertiesSet() throws Exception { + Assert.notNull(wrappedEventReader); + } + + /** + * Callback on transaction rollback. + */ + public void onRollback() { + recorder.reset(); + } + + /** + * Callback on transacion commit. + * + */ + public void onCommit() { + recorder.clear(); + } + + + /** + * Check if there are more events. Returns true if there are more events and + * false otherwise. + * + * @return true if the event reader has more events, false otherwise + */ + public boolean hasNext() { + return recorder.hasNext() || wrappedEventReader.hasNext(); + } + + /** + * Get the next XMLEvent + * + * @see XMLEvent + * @throws XMLStreamException if there is an error with the underlying XML. + * @throws NoSuchElementException iteration has no more elements. + */ + public XMLEvent nextEvent() throws XMLStreamException { + if (!recorder.hasNext()) { + recorder.addEvent(wrappedEventReader.nextEvent()); + } + return recorder.nextEvent(); + } + + /** + * Check the next XMLEvent without reading it from the stream. Returns null + * if the stream is at EOF or has no more XMLEvents. A call to peek() will + * be equal to the next return of next(). + * + * @see XMLEvent + * @throws XMLStreamException + */ + public XMLEvent peek() throws XMLStreamException { + return (recorder.hasNext()) ? recorder.peek() : wrappedEventReader.peek(); + } + + + /** + * In this implementation throws UnsupportedOperationException. + */ + public void remove() { + throw new UnsupportedOperationException(); + } +} diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/xml/stax/EventSequence.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/xml/stax/EventSequence.java index de75e88fdb..bd8d6d4e7b 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/xml/stax/EventSequence.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/xml/stax/EventSequence.java @@ -1,92 +1,92 @@ -package org.springframework.batch.io.xml.stax; - -import java.util.ArrayList; -import java.util.List; - -import javax.xml.stream.events.XMLEvent; - -/** - * Holds a list of XML events, typically corresponding to a single record. - * - * @author tomas.slanina - */ -class EventSequence { - - private static final int BEFORE_BEGINNING = -1; - - private List events; - - private int currentIndex; - - /** - * Creates instance of this class. - * - */ - public EventSequence() { - init(); - } - - /** - * Adds event to the list of stored events. - * - * @param event - */ - public void addEvent(XMLEvent event) { - events.add(event); - } - - /** - * Gets next XMLEvent from cache and moves cursor to next event. - * If cache contains no more events, null is returned. - * - * @return - */ - public XMLEvent nextEvent() { - return (hasNext()) ? (XMLEvent)events.get(++currentIndex) :null; - } - - /** - * Gets next XMLEvent from cache but cursor remains on the same position. - * If cache contains no more events, null is returned. - * - * @return - */ - public XMLEvent peek() { - return (hasNext()) ? (XMLEvent)events.get(currentIndex+1) :null; - } - - /** - * Removes events from the internal cache. - * - */ - public void clear() { - init(); - } - - /** - * Resets cursor to the cache start. - * - */ - public void reset() { - currentIndex = BEFORE_BEGINNING; - } - - /** - * Check if there are more events. Returns true if there are more events and - * false otherwise. - * - * @return true if the event reader has more events, false otherwise - */ - public boolean hasNext() { - return currentIndex + 1 < events.size(); - } - - private void init() { - events = (events != null) ? new ArrayList(events.size()) - : new ArrayList(1000); - - reset(); - } - - -} +package org.springframework.batch.io.xml.stax; + +import java.util.ArrayList; +import java.util.List; + +import javax.xml.stream.events.XMLEvent; + +/** + * Holds a list of XML events, typically corresponding to a single record. + * + * @author tomas.slanina + */ +class EventSequence { + + private static final int BEFORE_BEGINNING = -1; + + private List events; + + private int currentIndex; + + /** + * Creates instance of this class. + * + */ + public EventSequence() { + init(); + } + + /** + * Adds event to the list of stored events. + * + * @param event + */ + public void addEvent(XMLEvent event) { + events.add(event); + } + + /** + * Gets next XMLEvent from cache and moves cursor to next event. + * If cache contains no more events, null is returned. + * + * @return + */ + public XMLEvent nextEvent() { + return (hasNext()) ? (XMLEvent)events.get(++currentIndex) :null; + } + + /** + * Gets next XMLEvent from cache but cursor remains on the same position. + * If cache contains no more events, null is returned. + * + * @return + */ + public XMLEvent peek() { + return (hasNext()) ? (XMLEvent)events.get(currentIndex+1) :null; + } + + /** + * Removes events from the internal cache. + * + */ + public void clear() { + init(); + } + + /** + * Resets cursor to the cache start. + * + */ + public void reset() { + currentIndex = BEFORE_BEGINNING; + } + + /** + * Check if there are more events. Returns true if there are more events and + * false otherwise. + * + * @return true if the event reader has more events, false otherwise + */ + public boolean hasNext() { + return currentIndex + 1 < events.size(); + } + + private void init() { + events = (events != null) ? new ArrayList(events.size()) + : new ArrayList(1000); + + reset(); + } + + +} diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/xml/stax/FragmentEventReader.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/xml/stax/FragmentEventReader.java index 1edcc837d7..6607d3762f 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/xml/stax/FragmentEventReader.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/xml/stax/FragmentEventReader.java @@ -1,33 +1,33 @@ -package org.springframework.batch.io.xml.stax; - -import javax.xml.stream.XMLEventReader; - - -/** - * Interface for event readers which support treating XML fragments as standalone XML documents - * by wrapping the fragments with StartDocument and EndDocument events. - * - * @author Robert Kasanicky - */ -public interface FragmentEventReader extends XMLEventReader { - - /** - * Tells the event reader its cursor position is exactly before the fragment. - */ - void markStartFragment(); - - /** - * Tells the event reader the current fragment has been processed. - * If the cursor is still inside the fragment it should be moved - * after the end of the fragment. - */ - void markFragmentProcessed(); - - /** - * Reset the state of the fragment reader - make it forget - * it assumptions about current position of cursor - * (e.g. in case of rollback of the wrapped reader). - */ - void reset(); - -} +package org.springframework.batch.io.xml.stax; + +import javax.xml.stream.XMLEventReader; + + +/** + * Interface for event readers which support treating XML fragments as standalone XML documents + * by wrapping the fragments with StartDocument and EndDocument events. + * + * @author Robert Kasanicky + */ +public interface FragmentEventReader extends XMLEventReader { + + /** + * Tells the event reader its cursor position is exactly before the fragment. + */ + void markStartFragment(); + + /** + * Tells the event reader the current fragment has been processed. + * If the cursor is still inside the fragment it should be moved + * after the end of the fragment. + */ + void markFragmentProcessed(); + + /** + * Reset the state of the fragment reader - make it forget + * it assumptions about current position of cursor + * (e.g. in case of rollback of the wrapped reader). + */ + void reset(); + +} diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/xml/stax/NoStartEndDocumentStreamWriter.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/xml/stax/NoStartEndDocumentStreamWriter.java index 39f4da37af..d4f8bc298b 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/xml/stax/NoStartEndDocumentStreamWriter.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/xml/stax/NoStartEndDocumentStreamWriter.java @@ -1,25 +1,25 @@ -package org.springframework.batch.io.xml.stax; - -import javax.xml.stream.XMLEventWriter; -import javax.xml.stream.XMLStreamException; -import javax.xml.stream.events.XMLEvent; - -/** - * Delegating XMLEventWriter, which ignores start and end document events, - * but passes through everything else. - * - * @author peter.zozom - * @author Robert Kasanicky - */ -public class NoStartEndDocumentStreamWriter extends AbstractEventWriterWrapper { - - public NoStartEndDocumentStreamWriter(XMLEventWriter wrappedEventWriter) { - super(wrappedEventWriter); - } - - public void add(XMLEvent event) throws XMLStreamException { - if ((!event.isStartDocument()) && (!event.isEndDocument())) { - wrappedEventWriter.add(event); - } - } -} +package org.springframework.batch.io.xml.stax; + +import javax.xml.stream.XMLEventWriter; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.events.XMLEvent; + +/** + * Delegating XMLEventWriter, which ignores start and end document events, + * but passes through everything else. + * + * @author peter.zozom + * @author Robert Kasanicky + */ +public class NoStartEndDocumentStreamWriter extends AbstractEventWriterWrapper { + + public NoStartEndDocumentStreamWriter(XMLEventWriter wrappedEventWriter) { + super(wrappedEventWriter); + } + + public void add(XMLEvent event) throws XMLStreamException { + if ((!event.isStartDocument()) && (!event.isEndDocument())) { + wrappedEventWriter.add(event); + } + } +} diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/xml/stax/TransactionalEventReader.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/xml/stax/TransactionalEventReader.java index 22e69cc575..06da7b4754 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/xml/stax/TransactionalEventReader.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/io/xml/stax/TransactionalEventReader.java @@ -1,22 +1,22 @@ -package org.springframework.batch.io.xml.stax; - -import javax.xml.stream.XMLEventReader; - -/** - * XMLEventReader with transactional capabilities (ability to rollback to last commit point). - * - * @author Robert Kasanicky - */ -public interface TransactionalEventReader extends XMLEventReader{ - - /** - * Callback on transaction rollback. - */ - public void onRollback(); - - /** - * Callback on transaction commit. - */ - public void onCommit(); - -} +package org.springframework.batch.io.xml.stax; + +import javax.xml.stream.XMLEventReader; + +/** + * XMLEventReader with transactional capabilities (ability to rollback to last commit point). + * + * @author Robert Kasanicky + */ +public interface TransactionalEventReader extends XMLEventReader{ + + /** + * Callback on transaction rollback. + */ + public void onRollback(); + + /** + * Callback on transaction commit. + */ + public void onCommit(); + +} diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ExecutionContextUserSupport.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ExecutionContextUserSupport.java index 5529c8a0a1..67e6d3a195 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ExecutionContextUserSupport.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ExecutionContextUserSupport.java @@ -1,49 +1,49 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.item; - -import org.springframework.util.Assert; - -/** - * Facilitates assigning names to objects persisting data in - * {@link ExecutionContext} and generating keys for {@link ExecutionContext} - * based on the name. - * - * @author Robert Kasanicky - */ -public class ExecutionContextUserSupport { - - private String name; - - /** - * @param name unique name for the item stream used to create execution - * context keys. - */ - public void setName(String name) { - this.name = name; - } - - /** - * Prefix the argument with the name of the item stream to create a unique - * key that can be safely used to identify data stored in - * {@link ExecutionContext}. - */ - protected String getKey(String s) { - Assert.hasLength(name, "ItemStream must have a name assigned."); - return name + "." + s; - } - -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.item; + +import org.springframework.util.Assert; + +/** + * Facilitates assigning names to objects persisting data in + * {@link ExecutionContext} and generating keys for {@link ExecutionContext} + * based on the name. + * + * @author Robert Kasanicky + */ +public class ExecutionContextUserSupport { + + private String name; + + /** + * @param name unique name for the item stream used to create execution + * context keys. + */ + public void setName(String name) { + this.name = name; + } + + /** + * Prefix the argument with the name of the item stream to create a unique + * key that can be safely used to identify data stored in + * {@link ExecutionContext}. + */ + protected String getKey(String s) { + Assert.hasLength(name, "ItemStream must have a name assigned."); + return name + "." + s; + } + +} diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/reader/AggregateItemReader.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/reader/AggregateItemReader.java index 80814b4e52..6e4f1d5146 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/reader/AggregateItemReader.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/reader/AggregateItemReader.java @@ -1,113 +1,113 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.batch.item.reader; - -import java.util.ArrayList; -import java.util.Collection; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.springframework.batch.io.file.mapping.FieldSetMapper; -import org.springframework.batch.item.ItemReader; - -/** - * An {@link ItemReader} that delivers a list as its item, storing up objects - * from the injected {@link ItemReader} until they are ready to be packed out - * as a collection. The {@link ItemReader} should mark the beginning and end of - * records with the constant values in {@link FieldSetMapper} ({@link AggregateItemReader#BEGIN_RECORD} - * and {@link AggregateItemReader#END_RECORD}).
- * - * This class is thread safe (it can be used concurrently by multiple threads) - * as long as the {@link ItemReader} is also thread safe. - * - * @author Dave Syer - * - */ -public class AggregateItemReader extends DelegatingItemReader { - - private static final Log log = LogFactory - .getLog(AggregateItemReader.class); - - /** - * Marker for the end of a multi-object record. - */ - public static final Object END_RECORD = new Object(); - - /** - * Marker for the beginning of a multi-object record. - */ - public static final Object BEGIN_RECORD = new Object(); - - /** - * Get the next list of records. - * @throws Exception - * - * @see org.springframework.batch.item.ItemReader#read() - */ - public Object read() throws Exception { - ResultHolder holder = new ResultHolder(); - - while (process(super.read(), holder)) { - continue; - } - - if (!holder.exhausted) { - return holder.records; - } else { - return null; - } - } - - private boolean process(Object value, ResultHolder holder) { - // finish processing if we hit the end of file - if (value == null) { - log.debug("Exhausted ItemReader"); - holder.exhausted = true; - return false; - } - - // start a new collection - if (value == AggregateItemReader.BEGIN_RECORD) { - log.debug("Start of new record detected"); - return true; - } - - // mark we are finished with current collection - if (value == AggregateItemReader.END_RECORD) { - log.debug("End of record detected"); - return false; - } - - // add a simple record to the current collection - log.debug("Mapping: " + value); - holder.records.add(value); - return true; - } - - /** - * Private class for temporary state management while item is being - * collected. - * - * @author Dave Syer - * - */ - private static class ResultHolder { - Collection records = new ArrayList(); - boolean exhausted = false; - } - -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.batch.item.reader; + +import java.util.ArrayList; +import java.util.Collection; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.batch.io.file.mapping.FieldSetMapper; +import org.springframework.batch.item.ItemReader; + +/** + * An {@link ItemReader} that delivers a list as its item, storing up objects + * from the injected {@link ItemReader} until they are ready to be packed out + * as a collection. The {@link ItemReader} should mark the beginning and end of + * records with the constant values in {@link FieldSetMapper} ({@link AggregateItemReader#BEGIN_RECORD} + * and {@link AggregateItemReader#END_RECORD}).
+ * + * This class is thread safe (it can be used concurrently by multiple threads) + * as long as the {@link ItemReader} is also thread safe. + * + * @author Dave Syer + * + */ +public class AggregateItemReader extends DelegatingItemReader { + + private static final Log log = LogFactory + .getLog(AggregateItemReader.class); + + /** + * Marker for the end of a multi-object record. + */ + public static final Object END_RECORD = new Object(); + + /** + * Marker for the beginning of a multi-object record. + */ + public static final Object BEGIN_RECORD = new Object(); + + /** + * Get the next list of records. + * @throws Exception + * + * @see org.springframework.batch.item.ItemReader#read() + */ + public Object read() throws Exception { + ResultHolder holder = new ResultHolder(); + + while (process(super.read(), holder)) { + continue; + } + + if (!holder.exhausted) { + return holder.records; + } else { + return null; + } + } + + private boolean process(Object value, ResultHolder holder) { + // finish processing if we hit the end of file + if (value == null) { + log.debug("Exhausted ItemReader"); + holder.exhausted = true; + return false; + } + + // start a new collection + if (value == AggregateItemReader.BEGIN_RECORD) { + log.debug("Start of new record detected"); + return true; + } + + // mark we are finished with current collection + if (value == AggregateItemReader.END_RECORD) { + log.debug("End of record detected"); + return false; + } + + // add a simple record to the current collection + log.debug("Mapping: " + value); + holder.records.add(value); + return true; + } + + /** + * Private class for temporary state management while item is being + * collected. + * + * @author Dave Syer + * + */ + private static class ResultHolder { + Collection records = new ArrayList(); + boolean exhausted = false; + } + +} diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/reader/DelegatingItemReader.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/reader/DelegatingItemReader.java index be1f52c263..59aafd0ed7 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/reader/DelegatingItemReader.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/reader/DelegatingItemReader.java @@ -1,92 +1,92 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.batch.item.reader; - -import org.springframework.batch.io.Skippable; -import org.springframework.batch.item.ItemReader; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.util.Assert; - -/** - * Simple wrapper around {@link ItemReader}. The input source is expected to - * take care of open and close operations. If necessary it should be registered - * as a step scoped bean to ensure that the lifecycle methods are called. - * - * @author Dave Syer - */ -public class DelegatingItemReader extends AbstractItemReader implements Skippable, InitializingBean { - - private ItemReader itemReader; - - /** - * Default constructor. - */ - public DelegatingItemReader() { - super(); - } - - /** - * Convenience constructor for setting mandatory property. - */ - public DelegatingItemReader(ItemReader itemReader) { - this(); - this.itemReader = itemReader; - } - - public void afterPropertiesSet() throws Exception { - Assert.notNull(itemReader, "ItemReader must not be null."); - } - - /** - * Get the next object from the input source. - * @throws Exception - * @see org.springframework.batch.item.ItemReader#read() - */ - public Object read() throws Exception { - return itemReader.read(); - } - - /** - * Setter for input source. - * @param source - */ - public void setItemReader(ItemReader source) { - this.itemReader = source; - } - - public void skip() { - if (itemReader instanceof Skippable) { - ((Skippable) itemReader).skip(); - } - } - - /* - * (non-Javadoc) - * @see org.springframework.batch.item.ItemStream#mark(org.springframework.batch.item.ExecutionContext) - */ - public void mark() { - itemReader.mark(); - } - - /* - * (non-Javadoc) - * @see org.springframework.batch.item.ItemStream#reset(org.springframework.batch.item.ExecutionContext) - */ - public void reset() { - itemReader.reset(); - } -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.batch.item.reader; + +import org.springframework.batch.io.Skippable; +import org.springframework.batch.item.ItemReader; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.util.Assert; + +/** + * Simple wrapper around {@link ItemReader}. The input source is expected to + * take care of open and close operations. If necessary it should be registered + * as a step scoped bean to ensure that the lifecycle methods are called. + * + * @author Dave Syer + */ +public class DelegatingItemReader extends AbstractItemReader implements Skippable, InitializingBean { + + private ItemReader itemReader; + + /** + * Default constructor. + */ + public DelegatingItemReader() { + super(); + } + + /** + * Convenience constructor for setting mandatory property. + */ + public DelegatingItemReader(ItemReader itemReader) { + this(); + this.itemReader = itemReader; + } + + public void afterPropertiesSet() throws Exception { + Assert.notNull(itemReader, "ItemReader must not be null."); + } + + /** + * Get the next object from the input source. + * @throws Exception + * @see org.springframework.batch.item.ItemReader#read() + */ + public Object read() throws Exception { + return itemReader.read(); + } + + /** + * Setter for input source. + * @param source + */ + public void setItemReader(ItemReader source) { + this.itemReader = source; + } + + public void skip() { + if (itemReader instanceof Skippable) { + ((Skippable) itemReader).skip(); + } + } + + /* + * (non-Javadoc) + * @see org.springframework.batch.item.ItemStream#mark(org.springframework.batch.item.ExecutionContext) + */ + public void mark() { + itemReader.mark(); + } + + /* + * (non-Javadoc) + * @see org.springframework.batch.item.ItemStream#reset(org.springframework.batch.item.ExecutionContext) + */ + public void reset() { + itemReader.reset(); + } +} diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/reader/ItemReaderAdapter.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/reader/ItemReaderAdapter.java index 8c9f66ed18..fb6b591178 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/reader/ItemReaderAdapter.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/reader/ItemReaderAdapter.java @@ -1,55 +1,55 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.batch.item.reader; - -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.item.ItemReader; -import org.springframework.batch.item.exception.MarkFailedException; -import org.springframework.batch.item.exception.ResetFailedException; -import org.springframework.batch.item.exception.StreamException; -import org.springframework.batch.support.AbstractMethodInvokingDelegator; - -/** - * Invokes a custom method on a delegate plain old Java object which itself - * provides an item. - * - * @author Robert Kasanicky - */ -public class ItemReaderAdapter extends AbstractMethodInvokingDelegator implements ItemReader { - - /** - * @return return value of the target method. - */ - public Object read() throws Exception { - return invokeDelegateMethod(); - } - - /** - * Do nothing. - * - * @see org.springframework.batch.item.ItemReader#close(ExecutionContext) - */ - public void close() throws StreamException { - - } - - public void mark() throws MarkFailedException { - } - - public void reset() throws ResetFailedException { - } -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.batch.item.reader; + +import org.springframework.batch.item.ExecutionContext; +import org.springframework.batch.item.ItemReader; +import org.springframework.batch.item.exception.MarkFailedException; +import org.springframework.batch.item.exception.ResetFailedException; +import org.springframework.batch.item.exception.StreamException; +import org.springframework.batch.support.AbstractMethodInvokingDelegator; + +/** + * Invokes a custom method on a delegate plain old Java object which itself + * provides an item. + * + * @author Robert Kasanicky + */ +public class ItemReaderAdapter extends AbstractMethodInvokingDelegator implements ItemReader { + + /** + * @return return value of the target method. + */ + public Object read() throws Exception { + return invokeDelegateMethod(); + } + + /** + * Do nothing. + * + * @see org.springframework.batch.item.ItemReader#close(ExecutionContext) + */ + public void close() throws StreamException { + + } + + public void mark() throws MarkFailedException { + } + + public void reset() throws ResetFailedException { + } +} diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/reader/ValidatingItemReader.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/reader/ValidatingItemReader.java index 32bb57ebdf..53877ff141 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/reader/ValidatingItemReader.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/reader/ValidatingItemReader.java @@ -1,59 +1,59 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.item.reader; - -import org.springframework.batch.item.validator.Validator; -import org.springframework.util.Assert; - -/** - * Simple extension of {@link DelegatingItemReader} that provides for - * validation before returning input. - * - * @author Lucas Ward - * - */ -public class ValidatingItemReader extends DelegatingItemReader { - - private Validator validator; - - /* (non-Javadoc) - * @see org.springframework.batch.item.reader.DelegatingItemReader#afterPropertiesSet() - */ - public void afterPropertiesSet() throws Exception { - super.afterPropertiesSet(); - Assert.notNull(validator, "Validator must not be null."); - } - - /* (non-Javadoc) - * @see org.springframework.batch.item.reader.DelegatingItemReader#read() - */ - public Object read() throws Exception { - Object input = super.read(); - if(input != null){ - validator.validate(input); - } - return input; - } - - /** - * Set the validator used to validate each item. - * - * @param validator - */ - public void setValidator(Validator validator) { - this.validator = validator; - } -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.item.reader; + +import org.springframework.batch.item.validator.Validator; +import org.springframework.util.Assert; + +/** + * Simple extension of {@link DelegatingItemReader} that provides for + * validation before returning input. + * + * @author Lucas Ward + * + */ +public class ValidatingItemReader extends DelegatingItemReader { + + private Validator validator; + + /* (non-Javadoc) + * @see org.springframework.batch.item.reader.DelegatingItemReader#afterPropertiesSet() + */ + public void afterPropertiesSet() throws Exception { + super.afterPropertiesSet(); + Assert.notNull(validator, "Validator must not be null."); + } + + /* (non-Javadoc) + * @see org.springframework.batch.item.reader.DelegatingItemReader#read() + */ + public Object read() throws Exception { + Object input = super.read(); + if(input != null){ + validator.validate(input); + } + return input; + } + + /** + * Set the validator used to validate each item. + * + * @param validator + */ + public void setValidator(Validator validator) { + this.validator = validator; + } +} diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/writer/CompositeItemWriter.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/writer/CompositeItemWriter.java index 6a73114af2..dc87eb9269 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/writer/CompositeItemWriter.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/writer/CompositeItemWriter.java @@ -1,30 +1,30 @@ -package org.springframework.batch.item.writer; - -import java.util.Iterator; -import java.util.List; - -import org.springframework.batch.item.ItemWriter; - -/** - * Runs a collection of ItemProcessors in fixed-order sequence. - * - * @author Robert Kasanicky - */ -public class CompositeItemWriter extends AbstractItemWriter { - - private List delegates; - - public void setDelegates(List delegates) { - this.delegates = delegates; - } - - /** - * Calls injected ItemProcessors in order. - */ - public void write(Object data) throws Exception { - for (Iterator iterator = delegates.listIterator(); iterator.hasNext();) { - ((ItemWriter) iterator.next()).write(data); - } - } - -} +package org.springframework.batch.item.writer; + +import java.util.Iterator; +import java.util.List; + +import org.springframework.batch.item.ItemWriter; + +/** + * Runs a collection of ItemProcessors in fixed-order sequence. + * + * @author Robert Kasanicky + */ +public class CompositeItemWriter extends AbstractItemWriter { + + private List delegates; + + public void setDelegates(List delegates) { + this.delegates = delegates; + } + + /** + * Calls injected ItemProcessors in order. + */ + public void write(Object data) throws Exception { + for (Iterator iterator = delegates.listIterator(); iterator.hasNext();) { + ((ItemWriter) iterator.next()).write(data); + } + } + +} diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/writer/DelegatingItemWriter.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/writer/DelegatingItemWriter.java index ac1743731e..1077b20198 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/writer/DelegatingItemWriter.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/writer/DelegatingItemWriter.java @@ -1,80 +1,80 @@ -package org.springframework.batch.item.writer; - -import org.springframework.batch.item.ItemWriter; -import org.springframework.batch.item.exception.ClearFailedException; -import org.springframework.batch.item.exception.FlushFailedException; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.util.Assert; - -/** - * Simple wrapper around {@link ItemWriter}. - * - * @author Dave Syer - * @author Robert Kasanicky - */ -public class DelegatingItemWriter implements ItemWriter, InitializingBean { - - private ItemWriter writer; - - /** - * Default constructor. - */ - public DelegatingItemWriter() { - super(); - } - - /** - * @param itemWriter - */ - public DelegatingItemWriter(ItemWriter itemWriter) { - this(); - this.writer = itemWriter; - } - - /** - * Calls {@link #doProcess(Object)} and then writes the result to the - * delegate {@link ItemWriter}. - * @throws Exception - * - * @see ItemWriter#process(java.lang.Object) - */ - public void write(Object item) throws Exception { - Object result = doProcess(item); - writer.write(result); - } - - /** - * By default returns the argument. This method is an extension point meant - * to be overridden by subclasses that implement processing logic. - * @throws Exception - */ - protected Object doProcess(Object item) throws Exception { - return item; - } - - /** - * Setter for {@link ItemWriter}. - */ - public void setDelegate(ItemWriter writer) { - this.writer = writer; - } - - public void afterPropertiesSet() throws Exception { - Assert.notNull(writer); - } - - /** - * Delegates to {@link ItemWriter#clear()} - */ - public void clear() throws ClearFailedException { - writer.clear(); - } - - /** - * Delegates to {@link ItemWriter#flush()} - */ - public void flush() throws FlushFailedException { - writer.flush(); - } - -} +package org.springframework.batch.item.writer; + +import org.springframework.batch.item.ItemWriter; +import org.springframework.batch.item.exception.ClearFailedException; +import org.springframework.batch.item.exception.FlushFailedException; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.util.Assert; + +/** + * Simple wrapper around {@link ItemWriter}. + * + * @author Dave Syer + * @author Robert Kasanicky + */ +public class DelegatingItemWriter implements ItemWriter, InitializingBean { + + private ItemWriter writer; + + /** + * Default constructor. + */ + public DelegatingItemWriter() { + super(); + } + + /** + * @param itemWriter + */ + public DelegatingItemWriter(ItemWriter itemWriter) { + this(); + this.writer = itemWriter; + } + + /** + * Calls {@link #doProcess(Object)} and then writes the result to the + * delegate {@link ItemWriter}. + * @throws Exception + * + * @see ItemWriter#process(java.lang.Object) + */ + public void write(Object item) throws Exception { + Object result = doProcess(item); + writer.write(result); + } + + /** + * By default returns the argument. This method is an extension point meant + * to be overridden by subclasses that implement processing logic. + * @throws Exception + */ + protected Object doProcess(Object item) throws Exception { + return item; + } + + /** + * Setter for {@link ItemWriter}. + */ + public void setDelegate(ItemWriter writer) { + this.writer = writer; + } + + public void afterPropertiesSet() throws Exception { + Assert.notNull(writer); + } + + /** + * Delegates to {@link ItemWriter#clear()} + */ + public void clear() throws ClearFailedException { + writer.clear(); + } + + /** + * Delegates to {@link ItemWriter#flush()} + */ + public void flush() throws FlushFailedException { + writer.flush(); + } + +} diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/writer/ItemWriterAdapter.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/writer/ItemWriterAdapter.java index 9d85ddd964..962511b62b 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/writer/ItemWriterAdapter.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/writer/ItemWriterAdapter.java @@ -1,54 +1,54 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.batch.item.writer; - -import org.springframework.batch.item.ItemWriter; -import org.springframework.batch.item.exception.ClearFailedException; -import org.springframework.batch.item.exception.FlushFailedException; -import org.springframework.batch.support.AbstractMethodInvokingDelegator; - - -/** - * Delegates item processing to a custom method - - * passes the item as an argument for the delegate method. - * - * @see PropertyExtractingDelegatingItemWriter - * - * @author Robert Kasanicky - */ -public class ItemWriterAdapter extends AbstractMethodInvokingDelegator implements ItemWriter { - - public void write(Object item) throws Exception { - invokeDelegateMethodWithArgument(item); - } - - /* - * No-op, can't call more than one method. - * - */ - public void clear() throws ClearFailedException { - } - - /* - * No-op, can't call more than one method. - * - */ - public void flush() throws FlushFailedException { - } - -} - +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.batch.item.writer; + +import org.springframework.batch.item.ItemWriter; +import org.springframework.batch.item.exception.ClearFailedException; +import org.springframework.batch.item.exception.FlushFailedException; +import org.springframework.batch.support.AbstractMethodInvokingDelegator; + + +/** + * Delegates item processing to a custom method - + * passes the item as an argument for the delegate method. + * + * @see PropertyExtractingDelegatingItemWriter + * + * @author Robert Kasanicky + */ +public class ItemWriterAdapter extends AbstractMethodInvokingDelegator implements ItemWriter { + + public void write(Object item) throws Exception { + invokeDelegateMethodWithArgument(item); + } + + /* + * No-op, can't call more than one method. + * + */ + public void clear() throws ClearFailedException { + } + + /* + * No-op, can't call more than one method. + * + */ + public void flush() throws FlushFailedException { + } + +} + diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/writer/PropertyExtractingDelegatingItemWriter.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/writer/PropertyExtractingDelegatingItemWriter.java index f237e7bbc8..460fcb6ddb 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/writer/PropertyExtractingDelegatingItemWriter.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/writer/PropertyExtractingDelegatingItemWriter.java @@ -1,77 +1,77 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.batch.item.writer; - -import org.springframework.batch.item.ItemWriter; -import org.springframework.batch.item.exception.ClearFailedException; -import org.springframework.batch.item.exception.FlushFailedException; -import org.springframework.batch.support.AbstractMethodInvokingDelegator; -import org.springframework.beans.BeanWrapper; -import org.springframework.beans.BeanWrapperImpl; -import org.springframework.util.Assert; - -/** - * Delegates processing to a custom method - extracts property values - * from item object and uses them as arguments for the delegate method. - * - * @see ItemWriterAdapter - * - * @author Robert Kasanicky - */ -public class PropertyExtractingDelegatingItemWriter extends AbstractMethodInvokingDelegator implements ItemWriter { - - private String[] fieldsUsedAsTargetMethodArguments; - - /** - * Extracts values from item's fields named in fieldsUsedAsTargetMethodArguments - * and passes them as arguments to the delegate method. - */ - public void write(Object item) throws Exception { - // helper for extracting property values from a bean - BeanWrapper beanWrapper = new BeanWrapperImpl(item); - - Object[] methodArguments = new Object[fieldsUsedAsTargetMethodArguments.length]; - for (int i = 0; i < fieldsUsedAsTargetMethodArguments.length; i++) { - methodArguments[i] = beanWrapper.getPropertyValue(fieldsUsedAsTargetMethodArguments[i]); - } - - invokeDelegateMethodWithArguments(methodArguments); - } - - - public void afterPropertiesSet() throws Exception { - super.afterPropertiesSet(); - Assert.notEmpty(fieldsUsedAsTargetMethodArguments); - } - - /** - * @param fieldsUsedAsTargetMethodArguments the values of the these item's fields - * will be used as arguments for the delegate method. Nested property values are - * supported, e.g. address.city - */ - public void setFieldsUsedAsTargetMethodArguments(String[] fieldsUsedAsMethodArguments) { - this.fieldsUsedAsTargetMethodArguments = fieldsUsedAsMethodArguments; - } - - - public void clear() throws ClearFailedException { - } - - - public void flush() throws FlushFailedException { - } -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.batch.item.writer; + +import org.springframework.batch.item.ItemWriter; +import org.springframework.batch.item.exception.ClearFailedException; +import org.springframework.batch.item.exception.FlushFailedException; +import org.springframework.batch.support.AbstractMethodInvokingDelegator; +import org.springframework.beans.BeanWrapper; +import org.springframework.beans.BeanWrapperImpl; +import org.springframework.util.Assert; + +/** + * Delegates processing to a custom method - extracts property values + * from item object and uses them as arguments for the delegate method. + * + * @see ItemWriterAdapter + * + * @author Robert Kasanicky + */ +public class PropertyExtractingDelegatingItemWriter extends AbstractMethodInvokingDelegator implements ItemWriter { + + private String[] fieldsUsedAsTargetMethodArguments; + + /** + * Extracts values from item's fields named in fieldsUsedAsTargetMethodArguments + * and passes them as arguments to the delegate method. + */ + public void write(Object item) throws Exception { + // helper for extracting property values from a bean + BeanWrapper beanWrapper = new BeanWrapperImpl(item); + + Object[] methodArguments = new Object[fieldsUsedAsTargetMethodArguments.length]; + for (int i = 0; i < fieldsUsedAsTargetMethodArguments.length; i++) { + methodArguments[i] = beanWrapper.getPropertyValue(fieldsUsedAsTargetMethodArguments[i]); + } + + invokeDelegateMethodWithArguments(methodArguments); + } + + + public void afterPropertiesSet() throws Exception { + super.afterPropertiesSet(); + Assert.notEmpty(fieldsUsedAsTargetMethodArguments); + } + + /** + * @param fieldsUsedAsTargetMethodArguments the values of the these item's fields + * will be used as arguments for the delegate method. Nested property values are + * supported, e.g. address.city + */ + public void setFieldsUsedAsTargetMethodArguments(String[] fieldsUsedAsMethodArguments) { + this.fieldsUsedAsTargetMethodArguments = fieldsUsedAsMethodArguments; + } + + + public void clear() throws ClearFailedException { + } + + + public void flush() throws FlushFailedException { + } +} diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/ExitStatus.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/ExitStatus.java index a88f8c4b0b..de02c66d11 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/ExitStatus.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/ExitStatus.java @@ -1,223 +1,223 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.repeat; - -import java.io.Serializable; - -import org.springframework.util.StringUtils; - -/** - * Value object used to carry information about the status of a - * {@link RepeatOperations}. - * - * @author Dave Syer - * - */ -public class ExitStatus implements Serializable { - - /** - * Convenient constant value for when we detect that processing is underway. - * Used mainly by asynchronous launchers. - */ - public static final ExitStatus RUNNING = new ExitStatus(true, "RUNNING"); - - /** - * Convenient constant value representing unknown state - assumed - * continuable. - */ - public static final ExitStatus UNKNOWN = new ExitStatus(true, "UNKNOWN"); - - /** - * Convenient constant value representing unfinished processing. - */ - public static final ExitStatus CONTINUABLE = new ExitStatus(true, "CONTINUABLE"); - - /** - * Convenient constant value representing finished processing. - */ - public static final ExitStatus FINISHED = new ExitStatus(false, "COMPLETED"); - - /** - * Convenient constant value representing interrupted processing. - */ - public static final ExitStatus INTERRUPTED = new ExitStatus(false, "INTERRUPTED"); - - /** - * Convenient constant value representing job that did no processing (e.g. - * because it was already complete). - */ - public static final ExitStatus NOOP = new ExitStatus(false, "NOOP"); - - /** - * Convenient constant value representing finished processing with an error. - */ - public static final ExitStatus FAILED = new ExitStatus(false, "FAILED"); - - private final boolean continuable; - - private final String exitCode; - - private final String exitDescription; - - public ExitStatus(boolean continuable) { - this(continuable, "", ""); - } - - public ExitStatus(boolean continuable, String exitCode) { - this(continuable, exitCode, ""); - } - - public ExitStatus(boolean continuable, String exitCode, String exitDescription) { - super(); - this.continuable = continuable; - this.exitCode = exitCode; - this.exitDescription = exitDescription; - } - - /** - * Flag to signal that processing can continue. This is distinct from any - * flag that might indicate that a batch is complete, or terminated, since a - * batch might be only a small part of a larger whole, which is still not - * finished. - * - * @return true if processing can continue. - */ - public boolean isContinuable() { - return continuable; - } - - /** - * Getter for the exit code (defaults to blank). - * - * @return the exit code. - */ - public String getExitCode() { - return exitCode; - } - - /** - * Getter for the exit description (defaults to blank) - * - * @return - */ - public String getExitDescription() { - return exitDescription; - } - - /** - * Create a new {@link ExitStatus} with a logical combination of the - * continuable flag. - * - * @param continuable true if the caller thinks it is safe to continue. - * @return a new {@link ExitStatus} with {@link #isContinuable()} the - * logical and of the current value and the argument provided. - */ - public ExitStatus and(boolean continuable) { - return new ExitStatus(this.continuable && continuable, this.exitCode, this.exitDescription); - } - - /** - * Create a new {@link ExitStatus} with a logical combination of the - * continuable flag, and a concatenation of the descriptions. The exit code - * is only replaced if the result is continuable or the input is not - * continuable.
- * - * If the input is null just return this. - * - * @param status an {@link ExitStatus} to combine with this one. - * @return a new {@link ExitStatus} with {@link #isContinuable()} the - * logical and of the current value and the argument provided. - */ - public ExitStatus and(ExitStatus status) { - if (status == null) { - return this; - } - ExitStatus result = and(status.continuable).addExitDescription(status.exitDescription); - if (result.continuable || !status.continuable) { - result = result.replaceExitCode(status.exitCode); - } - return result; - } - - /* - * (non-Javadoc) - * - * @see java.lang.Object#toString() - */ - public String toString() { - return "continuable=" + continuable + ";exitCode=" + exitCode + ";exitDescription=" + exitDescription; - } - - /** - * Compare the fields one by one. - * - * @see java.lang.Object#equals(java.lang.Object) - */ - public boolean equals(Object obj) { - if (obj == null) { - return false; - } - return toString().equals(obj.toString()); - } - - /** - * Compatible with the equals implementation. - * - * @see java.lang.Object#hashCode() - */ - public int hashCode() { - return toString().hashCode(); - } - - /** - * Add an exit code to an existing {@link ExitStatus}. If there is already - * a code present tit will be replaced. - * - * @param code the code to add - * @return a new {@link ExitStatus} with the same properties but a new exit - * code. - */ - public ExitStatus replaceExitCode(String code) { - return new ExitStatus(continuable, code, exitDescription); - } - - /** - * Check if this status represents a running process. - * - * @return true if the exit code is "RUNNING" or "UNKNOWN" - */ - public boolean isRunning() { - return "RUNNING".equals(this.exitCode) || "UNKNOWN".equals(this.exitCode); - } - - /** - * Add an exit description to an existing {@link ExitStatus}. If there is - * already a description present the two will be concatenated with a - * semicolon. - * - * @param description the description to add - * @return a new {@link ExitStatus} with the same properties but a new exit - * description - */ - public ExitStatus addExitDescription(String description) { - if (StringUtils.hasText(exitDescription) && StringUtils.hasText(description) - && !exitDescription.equals(description)) { - description = exitDescription + "; " + description; - } - return new ExitStatus(continuable, exitCode, description); - } - -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.repeat; + +import java.io.Serializable; + +import org.springframework.util.StringUtils; + +/** + * Value object used to carry information about the status of a + * {@link RepeatOperations}. + * + * @author Dave Syer + * + */ +public class ExitStatus implements Serializable { + + /** + * Convenient constant value for when we detect that processing is underway. + * Used mainly by asynchronous launchers. + */ + public static final ExitStatus RUNNING = new ExitStatus(true, "RUNNING"); + + /** + * Convenient constant value representing unknown state - assumed + * continuable. + */ + public static final ExitStatus UNKNOWN = new ExitStatus(true, "UNKNOWN"); + + /** + * Convenient constant value representing unfinished processing. + */ + public static final ExitStatus CONTINUABLE = new ExitStatus(true, "CONTINUABLE"); + + /** + * Convenient constant value representing finished processing. + */ + public static final ExitStatus FINISHED = new ExitStatus(false, "COMPLETED"); + + /** + * Convenient constant value representing interrupted processing. + */ + public static final ExitStatus INTERRUPTED = new ExitStatus(false, "INTERRUPTED"); + + /** + * Convenient constant value representing job that did no processing (e.g. + * because it was already complete). + */ + public static final ExitStatus NOOP = new ExitStatus(false, "NOOP"); + + /** + * Convenient constant value representing finished processing with an error. + */ + public static final ExitStatus FAILED = new ExitStatus(false, "FAILED"); + + private final boolean continuable; + + private final String exitCode; + + private final String exitDescription; + + public ExitStatus(boolean continuable) { + this(continuable, "", ""); + } + + public ExitStatus(boolean continuable, String exitCode) { + this(continuable, exitCode, ""); + } + + public ExitStatus(boolean continuable, String exitCode, String exitDescription) { + super(); + this.continuable = continuable; + this.exitCode = exitCode; + this.exitDescription = exitDescription; + } + + /** + * Flag to signal that processing can continue. This is distinct from any + * flag that might indicate that a batch is complete, or terminated, since a + * batch might be only a small part of a larger whole, which is still not + * finished. + * + * @return true if processing can continue. + */ + public boolean isContinuable() { + return continuable; + } + + /** + * Getter for the exit code (defaults to blank). + * + * @return the exit code. + */ + public String getExitCode() { + return exitCode; + } + + /** + * Getter for the exit description (defaults to blank) + * + * @return + */ + public String getExitDescription() { + return exitDescription; + } + + /** + * Create a new {@link ExitStatus} with a logical combination of the + * continuable flag. + * + * @param continuable true if the caller thinks it is safe to continue. + * @return a new {@link ExitStatus} with {@link #isContinuable()} the + * logical and of the current value and the argument provided. + */ + public ExitStatus and(boolean continuable) { + return new ExitStatus(this.continuable && continuable, this.exitCode, this.exitDescription); + } + + /** + * Create a new {@link ExitStatus} with a logical combination of the + * continuable flag, and a concatenation of the descriptions. The exit code + * is only replaced if the result is continuable or the input is not + * continuable.
+ * + * If the input is null just return this. + * + * @param status an {@link ExitStatus} to combine with this one. + * @return a new {@link ExitStatus} with {@link #isContinuable()} the + * logical and of the current value and the argument provided. + */ + public ExitStatus and(ExitStatus status) { + if (status == null) { + return this; + } + ExitStatus result = and(status.continuable).addExitDescription(status.exitDescription); + if (result.continuable || !status.continuable) { + result = result.replaceExitCode(status.exitCode); + } + return result; + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#toString() + */ + public String toString() { + return "continuable=" + continuable + ";exitCode=" + exitCode + ";exitDescription=" + exitDescription; + } + + /** + * Compare the fields one by one. + * + * @see java.lang.Object#equals(java.lang.Object) + */ + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + return toString().equals(obj.toString()); + } + + /** + * Compatible with the equals implementation. + * + * @see java.lang.Object#hashCode() + */ + public int hashCode() { + return toString().hashCode(); + } + + /** + * Add an exit code to an existing {@link ExitStatus}. If there is already + * a code present tit will be replaced. + * + * @param code the code to add + * @return a new {@link ExitStatus} with the same properties but a new exit + * code. + */ + public ExitStatus replaceExitCode(String code) { + return new ExitStatus(continuable, code, exitDescription); + } + + /** + * Check if this status represents a running process. + * + * @return true if the exit code is "RUNNING" or "UNKNOWN" + */ + public boolean isRunning() { + return "RUNNING".equals(this.exitCode) || "UNKNOWN".equals(this.exitCode); + } + + /** + * Add an exit description to an existing {@link ExitStatus}. If there is + * already a description present the two will be concatenated with a + * semicolon. + * + * @param description the description to add + * @return a new {@link ExitStatus} with the same properties but a new exit + * description + */ + public ExitStatus addExitDescription(String description) { + if (StringUtils.hasText(exitDescription) && StringUtils.hasText(description) + && !exitDescription.equals(description)) { + description = exitDescription + "; " + description; + } + return new ExitStatus(continuable, exitCode, description); + } + +} diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/support/AbstractMethodInvokingDelegator.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/support/AbstractMethodInvokingDelegator.java index 61e6bf6e98..7864f2828e 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/support/AbstractMethodInvokingDelegator.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/support/AbstractMethodInvokingDelegator.java @@ -1,175 +1,175 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.batch.support; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; - -import org.springframework.batch.io.exception.DynamicMethodInvocationException; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.util.Assert; -import org.springframework.util.MethodInvoker; - -/** - * Superclass for delegating classes which dynamically call a - * custom method of injected object. - * Provides convenient API for dynamic method invocation shielding - * subclasses from low-level details and exception handling. - * - * @author Robert Kasanicky - */ -public class AbstractMethodInvokingDelegator implements InitializingBean { - - private Object targetObject; - - private String targetMethod; - - private Object[] arguments; - - /** - * Invoker the target method with no arguments. - * @return object returned by invoked method - * @throws DynamicMethodInvocationException if the {@link MethodInvoker} used throws exception - */ - protected Object invokeDelegateMethod() { - MethodInvoker invoker = createMethodInvoker(targetObject, targetMethod); - invoker.setArguments(arguments); - return doInvoke(invoker); - } - - /** - * Invokes the target method with given argument. - * @param object argument for the target method - * @return object returned by target method - * @throws DynamicMethodInvocationException if the {@link MethodInvoker} used throws exception - */ - protected Object invokeDelegateMethodWithArgument(Object object) { - MethodInvoker invoker = createMethodInvoker(targetObject, targetMethod); - invoker.setArguments(new Object[]{object}); - return doInvoke(invoker); - } - - /** - * Invokes the target method with given arguments. - * @param args arguments for the invoked method - * @return object returned by invoked method - * @throws DynamicMethodInvocationException if the {@link MethodInvoker} used throws exception - */ - protected Object invokeDelegateMethodWithArguments(Object[] args) { - MethodInvoker invoker = createMethodInvoker(targetObject, targetMethod); - invoker.setArguments(args); - return doInvoke(invoker); - } - - /** - * Create a new configured instance of {@link MethodInvoker}. - */ - private MethodInvoker createMethodInvoker(Object targetObject, String targetMethod) { - MethodInvoker invoker = new MethodInvoker(); - invoker.setTargetObject(targetObject); - invoker.setTargetMethod(targetMethod); - invoker.setArguments(arguments); - return invoker; - } - - /** - * Prepare and invoke the invoker, rethrow checked exceptions as unchecked. - * @param invoker configured invoker - * @return return value of the invoked method - */ - private Object doInvoke(MethodInvoker invoker) { - try { - invoker.prepare(); - } - catch (ClassNotFoundException e) { - throw new DynamicMethodInvocationException(e); - } - catch (NoSuchMethodException e) { - throw new DynamicMethodInvocationException(e); - } - - try { - return invoker.invoke(); - } - catch (InvocationTargetException e) { - throw new DynamicMethodInvocationException(e); - } - catch (IllegalAccessException e) { - throw new DynamicMethodInvocationException(e); - } - } - - public void afterPropertiesSet() throws Exception { - Assert.notNull(targetObject); - Assert.hasLength(targetMethod); - Assert.state(targetClassDeclaresTargetMethod(), - "target class must declare a method with name matching the target method"); - } - - /** - * @return true if target class declares a method matching target method name - * with given number of arguments of appropriate type. - */ - private boolean targetClassDeclaresTargetMethod() { - MethodInvoker invoker = createMethodInvoker(targetObject, targetMethod); - Method[] methods = invoker.getTargetClass().getDeclaredMethods(); - String targetMethodName = invoker.getTargetMethod(); - - for (int i=0; i < methods.length; i++) { - if (methods[i].getName().equals(targetMethodName)) { - Class[] params = methods[i].getParameterTypes(); - if (arguments == null) { - return true; - } else if (arguments.length == params.length) { - boolean argumentsMatchParameters = true; - for (int j = 0; j < params.length; j++) { - if (!(params[j].isAssignableFrom(arguments[j].getClass()))) { - argumentsMatchParameters = false; - } - } - if (argumentsMatchParameters) return true; - } - } - } - - return false; - } - - /** - * @param targetObject the delegate - bean id can be used to set this value in Spring configuration - */ - public void setTargetObject(Object targetObject) { - this.targetObject = targetObject; - } - - /** - * @param targetMethod name of the method to be invoked on {@link #targetObject}. - */ - public void setTargetMethod(String targetMethod) { - this.targetMethod = targetMethod; - } - - /** - * @param arguments arguments values for the {{@link #targetMethod}. - * These are not expected to change during the lifetime of the delegator - * and will be used only when the subclass tries to invoke the target method - * without providing explicit argument values. - */ - public void setArguments(Object[] arguments) { - this.arguments = arguments; - } -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.batch.support; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +import org.springframework.batch.io.exception.DynamicMethodInvocationException; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.util.Assert; +import org.springframework.util.MethodInvoker; + +/** + * Superclass for delegating classes which dynamically call a + * custom method of injected object. + * Provides convenient API for dynamic method invocation shielding + * subclasses from low-level details and exception handling. + * + * @author Robert Kasanicky + */ +public class AbstractMethodInvokingDelegator implements InitializingBean { + + private Object targetObject; + + private String targetMethod; + + private Object[] arguments; + + /** + * Invoker the target method with no arguments. + * @return object returned by invoked method + * @throws DynamicMethodInvocationException if the {@link MethodInvoker} used throws exception + */ + protected Object invokeDelegateMethod() { + MethodInvoker invoker = createMethodInvoker(targetObject, targetMethod); + invoker.setArguments(arguments); + return doInvoke(invoker); + } + + /** + * Invokes the target method with given argument. + * @param object argument for the target method + * @return object returned by target method + * @throws DynamicMethodInvocationException if the {@link MethodInvoker} used throws exception + */ + protected Object invokeDelegateMethodWithArgument(Object object) { + MethodInvoker invoker = createMethodInvoker(targetObject, targetMethod); + invoker.setArguments(new Object[]{object}); + return doInvoke(invoker); + } + + /** + * Invokes the target method with given arguments. + * @param args arguments for the invoked method + * @return object returned by invoked method + * @throws DynamicMethodInvocationException if the {@link MethodInvoker} used throws exception + */ + protected Object invokeDelegateMethodWithArguments(Object[] args) { + MethodInvoker invoker = createMethodInvoker(targetObject, targetMethod); + invoker.setArguments(args); + return doInvoke(invoker); + } + + /** + * Create a new configured instance of {@link MethodInvoker}. + */ + private MethodInvoker createMethodInvoker(Object targetObject, String targetMethod) { + MethodInvoker invoker = new MethodInvoker(); + invoker.setTargetObject(targetObject); + invoker.setTargetMethod(targetMethod); + invoker.setArguments(arguments); + return invoker; + } + + /** + * Prepare and invoke the invoker, rethrow checked exceptions as unchecked. + * @param invoker configured invoker + * @return return value of the invoked method + */ + private Object doInvoke(MethodInvoker invoker) { + try { + invoker.prepare(); + } + catch (ClassNotFoundException e) { + throw new DynamicMethodInvocationException(e); + } + catch (NoSuchMethodException e) { + throw new DynamicMethodInvocationException(e); + } + + try { + return invoker.invoke(); + } + catch (InvocationTargetException e) { + throw new DynamicMethodInvocationException(e); + } + catch (IllegalAccessException e) { + throw new DynamicMethodInvocationException(e); + } + } + + public void afterPropertiesSet() throws Exception { + Assert.notNull(targetObject); + Assert.hasLength(targetMethod); + Assert.state(targetClassDeclaresTargetMethod(), + "target class must declare a method with name matching the target method"); + } + + /** + * @return true if target class declares a method matching target method name + * with given number of arguments of appropriate type. + */ + private boolean targetClassDeclaresTargetMethod() { + MethodInvoker invoker = createMethodInvoker(targetObject, targetMethod); + Method[] methods = invoker.getTargetClass().getDeclaredMethods(); + String targetMethodName = invoker.getTargetMethod(); + + for (int i=0; i < methods.length; i++) { + if (methods[i].getName().equals(targetMethodName)) { + Class[] params = methods[i].getParameterTypes(); + if (arguments == null) { + return true; + } else if (arguments.length == params.length) { + boolean argumentsMatchParameters = true; + for (int j = 0; j < params.length; j++) { + if (!(params[j].isAssignableFrom(arguments[j].getClass()))) { + argumentsMatchParameters = false; + } + } + if (argumentsMatchParameters) return true; + } + } + } + + return false; + } + + /** + * @param targetObject the delegate - bean id can be used to set this value in Spring configuration + */ + public void setTargetObject(Object targetObject) { + this.targetObject = targetObject; + } + + /** + * @param targetMethod name of the method to be invoked on {@link #targetObject}. + */ + public void setTargetMethod(String targetMethod) { + this.targetMethod = targetMethod; + } + + /** + * @param arguments arguments values for the {{@link #targetMethod}. + * These are not expected to change during the lifetime of the delegator + * and will be used only when the subclass tries to invoke the target method + * without providing explicit argument values. + */ + public void setArguments(Object[] arguments) { + this.arguments = arguments; + } +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/cursor/HibernateCursorItemReaderIntegrationTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/cursor/HibernateCursorItemReaderIntegrationTests.java index c145a75b08..964f883c6c 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/cursor/HibernateCursorItemReaderIntegrationTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/cursor/HibernateCursorItemReaderIntegrationTests.java @@ -1,63 +1,63 @@ -package org.springframework.batch.io.cursor; - -import org.hibernate.SessionFactory; -import org.hibernate.StatelessSession; -import org.springframework.batch.io.support.AbstractDataSourceItemReaderIntegrationTests; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.item.ItemReader; -import org.springframework.core.io.ClassPathResource; -import org.springframework.core.io.Resource; -import org.springframework.orm.hibernate3.LocalSessionFactoryBean; - -/** - * Tests for {@link HibernateCursorItemReader} using {@link StatelessSession}. - * - * @author Robert Kasanicky - */ -public class HibernateCursorItemReaderIntegrationTests extends AbstractDataSourceItemReaderIntegrationTests { - - protected ItemReader createItemReader() throws Exception { - LocalSessionFactoryBean factoryBean = new LocalSessionFactoryBean(); - factoryBean.setDataSource(super.getJdbcTemplate().getDataSource()); - factoryBean.setMappingLocations(new Resource[] { new ClassPathResource("Foo.hbm.xml", getClass()) }); - factoryBean.afterPropertiesSet(); - - SessionFactory sessionFactory = (SessionFactory) factoryBean.getObject(); - - String hsqlQuery = "from Foo"; - - HibernateCursorItemReader inputSource = new HibernateCursorItemReader(); - inputSource.setQueryString(hsqlQuery); - inputSource.setSessionFactory(sessionFactory); - inputSource.setUseStatelessSession(isUseStatelessSession()); - inputSource.afterPropertiesSet(); - inputSource.setSaveState(true); - - return inputSource; - } - - protected boolean isUseStatelessSession() { - return true; - } - - /** - * Exception scenario. - * - * {@link HibernateCursorItemReader#setUseStatelessSession(boolean)} can be - * called only in uninitialized state. - */ - public void testSetUseStatelessSession() { - HibernateCursorItemReader inputSource = ((HibernateCursorItemReader) reader); - - // initialize and call setter => error - inputSource.open(new ExecutionContext()); - try { - inputSource.setUseStatelessSession(false); - fail(); - } - catch (IllegalStateException e) { - // expected - } - } - -} +package org.springframework.batch.io.cursor; + +import org.hibernate.SessionFactory; +import org.hibernate.StatelessSession; +import org.springframework.batch.io.support.AbstractDataSourceItemReaderIntegrationTests; +import org.springframework.batch.item.ExecutionContext; +import org.springframework.batch.item.ItemReader; +import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.Resource; +import org.springframework.orm.hibernate3.LocalSessionFactoryBean; + +/** + * Tests for {@link HibernateCursorItemReader} using {@link StatelessSession}. + * + * @author Robert Kasanicky + */ +public class HibernateCursorItemReaderIntegrationTests extends AbstractDataSourceItemReaderIntegrationTests { + + protected ItemReader createItemReader() throws Exception { + LocalSessionFactoryBean factoryBean = new LocalSessionFactoryBean(); + factoryBean.setDataSource(super.getJdbcTemplate().getDataSource()); + factoryBean.setMappingLocations(new Resource[] { new ClassPathResource("Foo.hbm.xml", getClass()) }); + factoryBean.afterPropertiesSet(); + + SessionFactory sessionFactory = (SessionFactory) factoryBean.getObject(); + + String hsqlQuery = "from Foo"; + + HibernateCursorItemReader inputSource = new HibernateCursorItemReader(); + inputSource.setQueryString(hsqlQuery); + inputSource.setSessionFactory(sessionFactory); + inputSource.setUseStatelessSession(isUseStatelessSession()); + inputSource.afterPropertiesSet(); + inputSource.setSaveState(true); + + return inputSource; + } + + protected boolean isUseStatelessSession() { + return true; + } + + /** + * Exception scenario. + * + * {@link HibernateCursorItemReader#setUseStatelessSession(boolean)} can be + * called only in uninitialized state. + */ + public void testSetUseStatelessSession() { + HibernateCursorItemReader inputSource = ((HibernateCursorItemReader) reader); + + // initialize and call setter => error + inputSource.open(new ExecutionContext()); + try { + inputSource.setUseStatelessSession(false); + fail(); + } + catch (IllegalStateException e) { + // expected + } + } + +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/cursor/HibernateCursorItemReaderStatefulIntegrationTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/cursor/HibernateCursorItemReaderStatefulIntegrationTests.java index 3897f3225a..64f07c19d1 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/cursor/HibernateCursorItemReaderStatefulIntegrationTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/cursor/HibernateCursorItemReaderStatefulIntegrationTests.java @@ -1,16 +1,16 @@ -package org.springframework.batch.io.cursor; - -import org.hibernate.Session; - -/** - * Tests for {@link HibernateCursorItemReader} using standard hibernate {@link Session}. - * - * @author Robert Kasanicky - */ -public class HibernateCursorItemReaderStatefulIntegrationTests extends HibernateCursorItemReaderIntegrationTests { - - protected boolean isUseStatelessSession() { - return false; - } - -} +package org.springframework.batch.io.cursor; + +import org.hibernate.Session; + +/** + * Tests for {@link HibernateCursorItemReader} using standard hibernate {@link Session}. + * + * @author Robert Kasanicky + */ +public class HibernateCursorItemReaderStatefulIntegrationTests extends HibernateCursorItemReaderIntegrationTests { + + protected boolean isUseStatelessSession() { + return false; + } + +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/cursor/JdbcCursorItemReaderIntegrationTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/cursor/JdbcCursorItemReaderIntegrationTests.java index ae12e1120f..70d81c5e9d 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/cursor/JdbcCursorItemReaderIntegrationTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/cursor/JdbcCursorItemReaderIntegrationTests.java @@ -1,30 +1,30 @@ -package org.springframework.batch.io.cursor; - -import org.springframework.batch.io.driving.FooRowMapper; -import org.springframework.batch.io.support.AbstractDataSourceItemReaderIntegrationTests; -import org.springframework.batch.item.ItemReader; - -/** - * Tests for {@link JdbcCursorItemReader} - * - * @author Robert Kasanicky - */ -public class JdbcCursorItemReaderIntegrationTests extends AbstractDataSourceItemReaderIntegrationTests { - - protected ItemReader createItemReader() throws Exception { - JdbcCursorItemReader result = new JdbcCursorItemReader(); - result.setDataSource(super.getJdbcTemplate().getDataSource()); - result.setSql("select ID, NAME, VALUE from T_FOOS"); - result.setIgnoreWarnings(true); - result.setVerifyCursorPosition(true); - - result.setMapper(new FooRowMapper()); - result.setFetchSize(10); - result.setMaxRows(100); - result.setQueryTimeout(1000); - result.setSaveState(true); - - return result; - } - -} +package org.springframework.batch.io.cursor; + +import org.springframework.batch.io.driving.FooRowMapper; +import org.springframework.batch.io.support.AbstractDataSourceItemReaderIntegrationTests; +import org.springframework.batch.item.ItemReader; + +/** + * Tests for {@link JdbcCursorItemReader} + * + * @author Robert Kasanicky + */ +public class JdbcCursorItemReaderIntegrationTests extends AbstractDataSourceItemReaderIntegrationTests { + + protected ItemReader createItemReader() throws Exception { + JdbcCursorItemReader result = new JdbcCursorItemReader(); + result.setDataSource(super.getJdbcTemplate().getDataSource()); + result.setSql("select ID, NAME, VALUE from T_FOOS"); + result.setIgnoreWarnings(true); + result.setVerifyCursorPosition(true); + + result.setMapper(new FooRowMapper()); + result.setFetchSize(10); + result.setMaxRows(100); + result.setQueryTimeout(1000); + result.setSaveState(true); + + return result; + } + +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/driving/CompositeKeyFooDao.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/driving/CompositeKeyFooDao.java index c13ea821ee..ac938f4ea2 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/driving/CompositeKeyFooDao.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/driving/CompositeKeyFooDao.java @@ -1,58 +1,58 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.io.driving; - -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.Map; - -import org.springframework.batch.io.sample.domain.Foo; -import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.jdbc.core.RowMapper; -import org.springframework.jdbc.core.support.JdbcDaoSupport; - -/** - * @author Lucas Ward - * - */ -public class CompositeKeyFooDao extends JdbcDaoSupport implements FooDao { - - public CompositeKeyFooDao(JdbcTemplate jdbcTemplate) { - this.setJdbcTemplate(jdbcTemplate); - } - /* (non-Javadoc) - * @see org.springframework.batch.io.sql.scratch.FooDao#getFoo(java.lang.Object) - */ - public Foo getFoo(Object key) { - - Map keys = (Map)key; - Object[] args = keys.values().toArray(); - - RowMapper fooMapper = new RowMapper(){ - public Object mapRow(ResultSet rs, int rowNum) throws SQLException { - Foo foo = new Foo(); - foo.setId(rs.getInt(1)); - foo.setName(rs.getString(2)); - foo.setValue(rs.getInt(3)); - return foo; - } - }; - - return (Foo)getJdbcTemplate().query("SELECT ID, NAME, VALUE from T_FOOS where ID = ? and VALUE = ?", - args, fooMapper).get(0); - } - -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.io.driving; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.Map; + +import org.springframework.batch.io.sample.domain.Foo; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.RowMapper; +import org.springframework.jdbc.core.support.JdbcDaoSupport; + +/** + * @author Lucas Ward + * + */ +public class CompositeKeyFooDao extends JdbcDaoSupport implements FooDao { + + public CompositeKeyFooDao(JdbcTemplate jdbcTemplate) { + this.setJdbcTemplate(jdbcTemplate); + } + /* (non-Javadoc) + * @see org.springframework.batch.io.sql.scratch.FooDao#getFoo(java.lang.Object) + */ + public Foo getFoo(Object key) { + + Map keys = (Map)key; + Object[] args = keys.values().toArray(); + + RowMapper fooMapper = new RowMapper(){ + public Object mapRow(ResultSet rs, int rowNum) throws SQLException { + Foo foo = new Foo(); + foo.setId(rs.getInt(1)); + foo.setName(rs.getString(2)); + foo.setValue(rs.getInt(3)); + return foo; + } + }; + + return (Foo)getJdbcTemplate().query("SELECT ID, NAME, VALUE from T_FOOS where ID = ? and VALUE = ?", + args, fooMapper).get(0); + } + +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/driving/FooDao.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/driving/FooDao.java index f39b5d6749..8fe633d707 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/driving/FooDao.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/driving/FooDao.java @@ -1,30 +1,30 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.io.driving; - -import org.springframework.batch.io.sample.domain.Foo; -import org.springframework.jdbc.core.JdbcTemplate; - -/** - * @author Lucas Ward - * - */ -public interface FooDao { - - Foo getFoo(Object key); - - void setJdbcTemplate(JdbcTemplate jdbcTemplate); -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.io.driving; + +import org.springframework.batch.io.sample.domain.Foo; +import org.springframework.jdbc.core.JdbcTemplate; + +/** + * @author Lucas Ward + * + */ +public interface FooDao { + + Foo getFoo(Object key); + + void setJdbcTemplate(JdbcTemplate jdbcTemplate); +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/driving/FooInputSource.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/driving/FooInputSource.java index ab9adedd48..7c3b1e1131 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/driving/FooInputSource.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/driving/FooInputSource.java @@ -1,68 +1,68 @@ -package org.springframework.batch.io.driving; - -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.item.ItemReader; -import org.springframework.batch.item.ItemStream; -import org.springframework.beans.factory.DisposableBean; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.jdbc.core.JdbcTemplate; - -class FooItemReader implements ItemStream, ItemReader, DisposableBean, InitializingBean { - - DrivingQueryItemReader inputSource; - - FooDao fooDao = new SingleKeyFooDao(); - - public FooItemReader(DrivingQueryItemReader inputSource, JdbcTemplate jdbcTemplate) { - this.inputSource = inputSource; - fooDao.setJdbcTemplate(jdbcTemplate); - } - - public Object read() { - Object key = inputSource.read(); - if (key != null) { - return fooDao.getFoo(key); - } - else { - return null; - } - } - - public void update(ExecutionContext executionContext) { - inputSource.update(executionContext); - } - - public void destroy() throws Exception { - inputSource.close(null); - } - - public void setFooDao(FooDao fooDao) { - this.fooDao = fooDao; - } - - public void afterPropertiesSet() throws Exception { - } - - public void open(ExecutionContext executionContext) { - inputSource.open(executionContext); - }; - - public void close(ExecutionContext executionContext) { - } - - /* - * (non-Javadoc) - * @see org.springframework.batch.item.ItemStream#mark(org.springframework.batch.item.StreamContext) - */ - public void mark() { - inputSource.mark(); - } - - /* - * (non-Javadoc) - * @see org.springframework.batch.item.ItemStream#reset(org.springframework.batch.item.StreamContext) - */ - public void reset() { - inputSource.reset(); - }; -} +package org.springframework.batch.io.driving; + +import org.springframework.batch.item.ExecutionContext; +import org.springframework.batch.item.ItemReader; +import org.springframework.batch.item.ItemStream; +import org.springframework.beans.factory.DisposableBean; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.jdbc.core.JdbcTemplate; + +class FooItemReader implements ItemStream, ItemReader, DisposableBean, InitializingBean { + + DrivingQueryItemReader inputSource; + + FooDao fooDao = new SingleKeyFooDao(); + + public FooItemReader(DrivingQueryItemReader inputSource, JdbcTemplate jdbcTemplate) { + this.inputSource = inputSource; + fooDao.setJdbcTemplate(jdbcTemplate); + } + + public Object read() { + Object key = inputSource.read(); + if (key != null) { + return fooDao.getFoo(key); + } + else { + return null; + } + } + + public void update(ExecutionContext executionContext) { + inputSource.update(executionContext); + } + + public void destroy() throws Exception { + inputSource.close(null); + } + + public void setFooDao(FooDao fooDao) { + this.fooDao = fooDao; + } + + public void afterPropertiesSet() throws Exception { + } + + public void open(ExecutionContext executionContext) { + inputSource.open(executionContext); + }; + + public void close(ExecutionContext executionContext) { + } + + /* + * (non-Javadoc) + * @see org.springframework.batch.item.ItemStream#mark(org.springframework.batch.item.StreamContext) + */ + public void mark() { + inputSource.mark(); + } + + /* + * (non-Javadoc) + * @see org.springframework.batch.item.ItemStream#reset(org.springframework.batch.item.StreamContext) + */ + public void reset() { + inputSource.reset(); + }; +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/driving/FooRowMapper.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/driving/FooRowMapper.java index 405ec7dbab..34bd3b7672 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/driving/FooRowMapper.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/driving/FooRowMapper.java @@ -1,21 +1,21 @@ -package org.springframework.batch.io.driving; - -import java.sql.ResultSet; -import java.sql.SQLException; - -import org.springframework.batch.io.sample.domain.Foo; -import org.springframework.jdbc.core.RowMapper; - - -public class FooRowMapper implements RowMapper { - - public Object mapRow(ResultSet rs, int rowNum) throws SQLException { - - Foo foo = new Foo(); - foo.setId(rs.getInt(1)); - foo.setName(rs.getString(2)); - foo.setValue(rs.getInt(3)); - - return foo; - } -} +package org.springframework.batch.io.driving; + +import java.sql.ResultSet; +import java.sql.SQLException; + +import org.springframework.batch.io.sample.domain.Foo; +import org.springframework.jdbc.core.RowMapper; + + +public class FooRowMapper implements RowMapper { + + public Object mapRow(ResultSet rs, int rowNum) throws SQLException { + + Foo foo = new Foo(); + foo.setId(rs.getInt(1)); + foo.setName(rs.getString(2)); + foo.setValue(rs.getInt(3)); + + return foo; + } +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/driving/IbatisItemReaderIntegrationTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/driving/IbatisItemReaderIntegrationTests.java index 45a857e0f6..eb5ac8d5a3 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/driving/IbatisItemReaderIntegrationTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/driving/IbatisItemReaderIntegrationTests.java @@ -1,40 +1,40 @@ -package org.springframework.batch.io.driving; - -import org.springframework.batch.io.driving.support.IbatisKeyGenerator; -import org.springframework.batch.io.support.AbstractDataSourceItemReaderIntegrationTests; -import org.springframework.batch.item.ItemReader; -import org.springframework.core.io.ClassPathResource; -import org.springframework.orm.ibatis.SqlMapClientFactoryBean; - -import com.ibatis.sqlmap.client.SqlMapClient; - -/** - * Tests for {@link IbatisDrivingQueryItemReader} - * - * @author Robert Kasanicky - */ -public class IbatisItemReaderIntegrationTests extends AbstractDataSourceItemReaderIntegrationTests { - - protected ItemReader createItemReader() throws Exception { - - SqlMapClientFactoryBean factory = new SqlMapClientFactoryBean(); - factory.setConfigLocation(new ClassPathResource("ibatis-config.xml", getClass())); - factory.setDataSource(super.getJdbcTemplate().getDataSource()); - factory.afterPropertiesSet(); - SqlMapClient sqlMapClient = (SqlMapClient) factory.getObject(); - - IbatisDrivingQueryItemReader inputSource = new IbatisDrivingQueryItemReader(); - IbatisKeyGenerator keyGenerator = new IbatisKeyGenerator(); - keyGenerator.setDrivingQueryId("getAllFooIds"); - inputSource.setDetailsQueryId("getFooById"); - keyGenerator.setRestartQueryId("getAllFooIdsRestart"); - keyGenerator.setSqlMapClient(sqlMapClient); - inputSource.setSqlMapClient(sqlMapClient); - inputSource.setKeyGenerator(keyGenerator); - inputSource.setSaveState(true); - - return inputSource; - } - - -} +package org.springframework.batch.io.driving; + +import org.springframework.batch.io.driving.support.IbatisKeyGenerator; +import org.springframework.batch.io.support.AbstractDataSourceItemReaderIntegrationTests; +import org.springframework.batch.item.ItemReader; +import org.springframework.core.io.ClassPathResource; +import org.springframework.orm.ibatis.SqlMapClientFactoryBean; + +import com.ibatis.sqlmap.client.SqlMapClient; + +/** + * Tests for {@link IbatisDrivingQueryItemReader} + * + * @author Robert Kasanicky + */ +public class IbatisItemReaderIntegrationTests extends AbstractDataSourceItemReaderIntegrationTests { + + protected ItemReader createItemReader() throws Exception { + + SqlMapClientFactoryBean factory = new SqlMapClientFactoryBean(); + factory.setConfigLocation(new ClassPathResource("ibatis-config.xml", getClass())); + factory.setDataSource(super.getJdbcTemplate().getDataSource()); + factory.afterPropertiesSet(); + SqlMapClient sqlMapClient = (SqlMapClient) factory.getObject(); + + IbatisDrivingQueryItemReader inputSource = new IbatisDrivingQueryItemReader(); + IbatisKeyGenerator keyGenerator = new IbatisKeyGenerator(); + keyGenerator.setDrivingQueryId("getAllFooIds"); + inputSource.setDetailsQueryId("getFooById"); + keyGenerator.setRestartQueryId("getAllFooIdsRestart"); + keyGenerator.setSqlMapClient(sqlMapClient); + inputSource.setSqlMapClient(sqlMapClient); + inputSource.setKeyGenerator(keyGenerator); + inputSource.setSaveState(true); + + return inputSource; + } + + +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/driving/MultipleColumnJdbcDrivingQueryItemReaderIntegrationTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/driving/MultipleColumnJdbcDrivingQueryItemReaderIntegrationTests.java index 5074529f31..feae7bd22f 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/driving/MultipleColumnJdbcDrivingQueryItemReaderIntegrationTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/driving/MultipleColumnJdbcDrivingQueryItemReaderIntegrationTests.java @@ -1,44 +1,44 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.io.driving; - -import org.springframework.batch.io.driving.support.MultipleColumnJdbcKeyGenerator; -import org.springframework.batch.io.sql.AbstractJdbcItemReaderIntegrationTests; -import org.springframework.batch.item.ItemReader; - -/** - * @author Lucas Ward - * - */ -public class MultipleColumnJdbcDrivingQueryItemReaderIntegrationTests extends - AbstractJdbcItemReaderIntegrationTests { - - protected ItemReader createItemReader() throws Exception { - - MultipleColumnJdbcKeyGenerator keyGenerator = - new MultipleColumnJdbcKeyGenerator(getJdbcTemplate(), - "SELECT ID, VALUE from T_FOOS order by ID, VALUE"); - - keyGenerator.setRestartSql("SELECT ID, VALUE from T_FOOS where ID > ? and VALUE > ? order by ID"); - DrivingQueryItemReader inputSource = new DrivingQueryItemReader(); - inputSource.setSaveState(true); - inputSource.setKeyGenerator(keyGenerator); - FooItemReader fooItemReader = new FooItemReader(inputSource, getJdbcTemplate()); - fooItemReader.setFooDao(new CompositeKeyFooDao(getJdbcTemplate())); - return fooItemReader; - } - -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.io.driving; + +import org.springframework.batch.io.driving.support.MultipleColumnJdbcKeyGenerator; +import org.springframework.batch.io.sql.AbstractJdbcItemReaderIntegrationTests; +import org.springframework.batch.item.ItemReader; + +/** + * @author Lucas Ward + * + */ +public class MultipleColumnJdbcDrivingQueryItemReaderIntegrationTests extends + AbstractJdbcItemReaderIntegrationTests { + + protected ItemReader createItemReader() throws Exception { + + MultipleColumnJdbcKeyGenerator keyGenerator = + new MultipleColumnJdbcKeyGenerator(getJdbcTemplate(), + "SELECT ID, VALUE from T_FOOS order by ID, VALUE"); + + keyGenerator.setRestartSql("SELECT ID, VALUE from T_FOOS where ID > ? and VALUE > ? order by ID"); + DrivingQueryItemReader inputSource = new DrivingQueryItemReader(); + inputSource.setSaveState(true); + inputSource.setKeyGenerator(keyGenerator); + FooItemReader fooItemReader = new FooItemReader(inputSource, getJdbcTemplate()); + fooItemReader.setFooDao(new CompositeKeyFooDao(getJdbcTemplate())); + return fooItemReader; + } + +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/driving/SingleColumnJdbcDrivingQueryItemReaderIntegrationTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/driving/SingleColumnJdbcDrivingQueryItemReaderIntegrationTests.java index de47c1dcff..7559da69fe 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/driving/SingleColumnJdbcDrivingQueryItemReaderIntegrationTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/driving/SingleColumnJdbcDrivingQueryItemReaderIntegrationTests.java @@ -1,26 +1,26 @@ -package org.springframework.batch.io.driving; - -import org.springframework.batch.io.driving.support.SingleColumnJdbcKeyGenerator; -import org.springframework.batch.io.sql.AbstractJdbcItemReaderIntegrationTests; -import org.springframework.batch.item.ItemReader; - -public class SingleColumnJdbcDrivingQueryItemReaderIntegrationTests extends AbstractJdbcItemReaderIntegrationTests { - - protected ItemReader source; - - - /** - * @return input source with all necessary dependencies set - */ - protected ItemReader createItemReader() throws Exception { - - SingleColumnJdbcKeyGenerator keyStrategy = new SingleColumnJdbcKeyGenerator(getJdbcTemplate(), - "SELECT ID from T_FOOS order by ID"); - keyStrategy.setRestartSql("SELECT ID from T_FOOS where ID > ? order by ID"); - DrivingQueryItemReader inputSource = new DrivingQueryItemReader(); - inputSource.setKeyGenerator(keyStrategy); - inputSource.setSaveState(true); - return new FooItemReader(inputSource, getJdbcTemplate()); - - } -} +package org.springframework.batch.io.driving; + +import org.springframework.batch.io.driving.support.SingleColumnJdbcKeyGenerator; +import org.springframework.batch.io.sql.AbstractJdbcItemReaderIntegrationTests; +import org.springframework.batch.item.ItemReader; + +public class SingleColumnJdbcDrivingQueryItemReaderIntegrationTests extends AbstractJdbcItemReaderIntegrationTests { + + protected ItemReader source; + + + /** + * @return input source with all necessary dependencies set + */ + protected ItemReader createItemReader() throws Exception { + + SingleColumnJdbcKeyGenerator keyStrategy = new SingleColumnJdbcKeyGenerator(getJdbcTemplate(), + "SELECT ID from T_FOOS order by ID"); + keyStrategy.setRestartSql("SELECT ID from T_FOOS where ID > ? order by ID"); + DrivingQueryItemReader inputSource = new DrivingQueryItemReader(); + inputSource.setKeyGenerator(keyStrategy); + inputSource.setSaveState(true); + return new FooItemReader(inputSource, getJdbcTemplate()); + + } +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/driving/SingleKeyFooDao.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/driving/SingleKeyFooDao.java index 19f4a40f9a..a9d85c360d 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/driving/SingleKeyFooDao.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/driving/SingleKeyFooDao.java @@ -1,28 +1,28 @@ -package org.springframework.batch.io.driving; - -import java.sql.ResultSet; -import java.sql.SQLException; - -import org.springframework.batch.io.sample.domain.Foo; -import org.springframework.jdbc.core.RowMapper; -import org.springframework.jdbc.core.support.JdbcDaoSupport; - -public class SingleKeyFooDao extends JdbcDaoSupport implements FooDao { - - public Foo getFoo(Object key){ - - RowMapper fooMapper = new RowMapper(){ - public Object mapRow(ResultSet rs, int rowNum) throws SQLException { - Foo foo = new Foo(); - foo.setId(rs.getInt(1)); - foo.setName(rs.getString(2)); - foo.setValue(rs.getInt(3)); - return foo; - } - }; - - return (Foo)getJdbcTemplate().query("SELECT ID, NAME, VALUE from T_FOOS where ID = ?", - new Object[] {key}, fooMapper).get(0); - - } -} +package org.springframework.batch.io.driving; + +import java.sql.ResultSet; +import java.sql.SQLException; + +import org.springframework.batch.io.sample.domain.Foo; +import org.springframework.jdbc.core.RowMapper; +import org.springframework.jdbc.core.support.JdbcDaoSupport; + +public class SingleKeyFooDao extends JdbcDaoSupport implements FooDao { + + public Foo getFoo(Object key){ + + RowMapper fooMapper = new RowMapper(){ + public Object mapRow(ResultSet rs, int rowNum) throws SQLException { + Foo foo = new Foo(); + foo.setId(rs.getInt(1)); + foo.setName(rs.getString(2)); + foo.setValue(rs.getInt(3)); + return foo; + } + }; + + return (Foo)getJdbcTemplate().query("SELECT ID, NAME, VALUE from T_FOOS where ID = ?", + new Object[] {key}, fooMapper).get(0); + + } +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/file/FieldSetTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/file/FieldSetTests.java index 4fceaf14b7..4236d475bc 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/file/FieldSetTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/file/FieldSetTests.java @@ -1,453 +1,453 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.batch.io.file; - -import java.math.BigDecimal; -import java.text.ParseException; - -import junit.framework.TestCase; - -import org.springframework.batch.io.file.mapping.DefaultFieldSet; -import org.springframework.batch.io.file.mapping.FieldSet; - -public class FieldSetTests extends TestCase { - FieldSet fieldSet; - - String[] tokens; - - String[] names; - - protected void setUp() throws Exception { - super.setUp(); - - tokens = new String[] { "TestString", "true", "C", "10", "-472", "354224", "543", "124.3", "424.3", "324", - null, "2007-10-12", "12-10-2007", "" }; - names = new String[] { "String", "Boolean", "Char", "Byte", "Short", "Integer", "Long", "Float", "Double", - "BigDecimal", "Null", "Date", "DatePattern", "BlankInput" }; - - fieldSet = new DefaultFieldSet(tokens, names); - assertEquals(14, fieldSet.getFieldCount()); - - } - - public void testNames() throws Exception { - assertEquals(fieldSet.getFieldCount(), fieldSet.getNames().length); - } - - public void testNamesNotKnown() throws Exception { - fieldSet = new DefaultFieldSet(new String[]{"foo"}); - try { - fieldSet.getNames(); - fail("Expected IllegalStateException"); - } catch (IllegalStateException e) { - // expected - } - } - - public void testReadString() throws ParseException { - - assertEquals(fieldSet.readString(0), "TestString"); - assertEquals(fieldSet.readString("String"), "TestString"); - - } - - public void testReadChar() throws Exception { - - assertTrue(fieldSet.readChar(2) == 'C'); - assertTrue(fieldSet.readChar("Char") == 'C'); - - } - - public void testReadBooleanTrue() throws Exception { - - assertTrue(fieldSet.readBoolean(1)); - assertTrue(fieldSet.readBoolean("Boolean")); - - } - - public void testReadByte() throws Exception { - - assertTrue(fieldSet.readByte(3) == 10); - assertTrue(fieldSet.readByte("Byte") == 10); - - } - - public void testReadShort() throws Exception { - - assertTrue(fieldSet.readShort(4) == -472); - assertTrue(fieldSet.readShort("Short") == -472); - - } - - public void testReadFloat() throws Exception { - - assertTrue(fieldSet.readFloat(7) == 124.3F); - assertTrue(fieldSet.readFloat("Float") == 124.3F); - - } - - public void testReadDouble() throws Exception { - - assertTrue(fieldSet.readDouble(8) == 424.3); - assertTrue(fieldSet.readDouble("Double") == 424.3); - - } - - public void testReadBigDecimal() throws Exception { - - BigDecimal bd = new BigDecimal(324); - assertEquals(fieldSet.readBigDecimal(9), bd); - assertEquals(fieldSet.readBigDecimal("BigDecimal"), bd); - - } - - public void testReadBigDecimalWithDefaultvalue() throws Exception { - - BigDecimal bd = new BigDecimal(324); - assertEquals(bd, fieldSet.readBigDecimal(10, bd)); - assertEquals(bd, fieldSet.readBigDecimal("Null", bd)); - - } - - public void testReadNonExistentField() throws Exception { - - try { - fieldSet.readString("something"); - fail("field set returns value even value was never put in!"); - } - catch (IllegalArgumentException e) { - assertTrue(e.getMessage().indexOf("something") > 0); - } - - } - - public void testReadIndexOutOfRange() throws Exception { - - try { - fieldSet.readShort(-1); - fail("field set returns value even index is out of range!"); - } - catch (IndexOutOfBoundsException e) { - assertTrue(true); - } - - try { - fieldSet.readShort(99); - fail("field set returns value even index is out of range!"); - } - catch (Exception e) { - assertTrue(true); - } - } - - public void testReadBooleanWithTrueValue() { - assertTrue(fieldSet.readBoolean(1, "true")); - assertFalse(fieldSet.readBoolean(1, "incorrect trueValue")); - - assertTrue(fieldSet.readBoolean("Boolean", "true")); - assertFalse(fieldSet.readBoolean("Boolean", "incorrect trueValue")); - } - - public void testReadBooleanFalse() { - fieldSet = new DefaultFieldSet(new String[] { "false" }); - assertFalse(fieldSet.readBoolean(0)); - } - - public void testReadCharException() { - try { - fieldSet.readChar(1); - fail("the value read was not a character, exception expected"); - } - catch (IllegalArgumentException expected) { - assertTrue(true); - } - - try { - fieldSet.readChar("Boolean"); - fail("the value read was not a character, exception expected"); - } - catch (IllegalArgumentException expected) { - assertTrue(true); - } - } - - public void testReadInt() throws Exception { - assertEquals(354224, fieldSet.readInt(5)); - assertEquals(354224, fieldSet.readInt("Integer")); - } - - public void testReadBlankInt(){ - - //Trying to parse a blank field as an integer, but without a default - //value should throw a NumberFormatException - try{ - fieldSet.readInt(13); - fail(); - } - catch(NumberFormatException ex){ - //expected - } - - try{ - fieldSet.readInt("BlankInput"); - fail(); - } - catch(NumberFormatException ex){ - //expected - } - - } - - public void testReadLong() throws Exception { - assertEquals(543, fieldSet.readLong(6)); - assertEquals(543, fieldSet.readLong("Long")); - } - - public void testReadLongWithPadding() throws Exception { - fieldSet = new DefaultFieldSet(new String[] {"000009"}); - assertEquals(9, fieldSet.readLong(0)); - } - - public void testReadIntWithNullValue() { - assertEquals(5, fieldSet.readInt(10, 5)); - assertEquals(5, fieldSet.readInt("Null", 5)); - } - - public void testReadIntWithDefaultAndNotNull() throws Exception { - assertEquals(354224, fieldSet.readInt(5, 5)); - assertEquals(354224, fieldSet.readInt("Integer", 5)); - } - - public void testReadLongWithNullValue() { - int defaultValue = 5; - int indexOfNull = 10; - int indexNotNull = 6; - String nameNull = "Null"; - String nameNotNull = "Long"; - long longValueAtIndex = 543; - - assertEquals(fieldSet.readLong(indexOfNull, defaultValue), defaultValue); - assertEquals(fieldSet.readLong(indexNotNull, defaultValue), longValueAtIndex); - - assertEquals(fieldSet.readLong(nameNull, defaultValue), defaultValue); - assertEquals(fieldSet.readLong(nameNotNull, defaultValue), longValueAtIndex); - } - - public void testReadBigDecimalInvalid() { - int index = 0; - - try { - fieldSet.readBigDecimal(index); - fail("field value is not a number, exception expected"); - } - catch (IllegalArgumentException e) { - assertTrue(e.getMessage().indexOf("TestString") > 0); - } - - } - - public void testReadBigDecimalByNameInvalid() throws Exception { - try { - fieldSet.readBigDecimal("String"); - fail("field value is not a number, exception expected"); - } - catch (IllegalArgumentException e) { - assertTrue(e.getMessage().indexOf("TestString") > 0); - assertTrue(e.getMessage().indexOf("name: [String]") > 0); - } - } - - public void testReadDate() throws Exception { - assertNotNull(fieldSet.readDate(11)); - assertNotNull(fieldSet.readDate("Date")); - } - - public void testReadDateInvalid() throws Exception { - - try { - fieldSet.readDate(0); - fail("field value is not a date, exception expected"); - } - catch (IllegalArgumentException e) { - assertTrue(e.getMessage().indexOf("TestString") > 0); - } - - } - - public void testReadDateInvalidByName() throws Exception { - - try { - fieldSet.readDate("String"); - fail("field value is not a date, exception expected"); - } - catch (IllegalArgumentException e) { - assertTrue(e.getMessage().indexOf("name: [String]") > 0); - } - - } - - public void testReadDateInvalidWithPattern() throws Exception { - - try { - fieldSet.readDate(0, "dd-MM-yyyy"); - fail("field value is not a date, exception expected"); - } - catch (IllegalArgumentException e) { - assertTrue(e.getMessage().indexOf("dd-MM-yyyy") > 0); - } - } - - public void testReadDateByNameInvalidWithPattern() throws Exception { - - try { - fieldSet.readDate("String", "dd-MM-yyyy"); - fail("field value is not a date, exception expected"); - } - catch (IllegalArgumentException e) { - assertTrue(e.getMessage().indexOf("dd-MM-yyyy") > 0); - assertTrue(e.getMessage().indexOf("String") > 0); - } - } - - public void testEquals() { - - assertEquals(fieldSet, fieldSet); - assertEquals(fieldSet, new DefaultFieldSet(tokens)); - - String[] tokens1 = new String[] { "token1" }; - String[] tokens2 = new String[] { "token1" }; - FieldSet fs1 = new DefaultFieldSet(tokens1); - FieldSet fs2 = new DefaultFieldSet(tokens2); - assertEquals(fs1, fs2); - } - - public void testNullField() { - assertEquals(null, fieldSet.readString(10)); - } - - public void testEqualsNull() { - assertFalse(fieldSet.equals(null)); - } - - public void testEqualsNullTokens() { - assertFalse(new DefaultFieldSet(null).equals(fieldSet)); - } - - public void testEqualsNotEqual() throws Exception { - - String[] tokens1 = new String[] { "token1" }; - String[] tokens2 = new String[] { "token1", "token2" }; - FieldSet fs1 = new DefaultFieldSet(tokens1); - FieldSet fs2 = new DefaultFieldSet(tokens2); - assertFalse(fs1.equals(fs2)); - - } - - public void testHashCode() throws Exception { - assertEquals(fieldSet.hashCode(), new DefaultFieldSet(tokens).hashCode()); - } - - public void testHashCodeWithNullTokens() throws Exception { - assertEquals(0, new DefaultFieldSet(null).hashCode()); - } - - public void testConstructor() throws Exception { - try { - new DefaultFieldSet(new String[] { "1", "2" }, new String[] { "a" }); - fail("Expected IllegalArgumentException"); - } - catch (IllegalArgumentException e) { - // expected - } - } - - public void testToStringWithNames() throws Exception { - fieldSet = new DefaultFieldSet(new String[] { "foo", "bar" }, new String[] { "Foo", "Bar" }); - assertTrue(fieldSet.toString().indexOf("Foo=foo") >= 0); - } - - public void testToStringWithoutNames() throws Exception { - fieldSet = new DefaultFieldSet(new String[] { "foo", "bar" }); - assertTrue(fieldSet.toString().indexOf("foo") >= 0); - } - - public void testToStringNullTokens() throws Exception { - fieldSet = new DefaultFieldSet(null); - assertEquals("", fieldSet.toString()); - } - - public void testProperties() throws Exception { - assertEquals("foo", new DefaultFieldSet(new String[] { "foo", "bar" }, new String[] { "Foo", "Bar" }).getProperties() - .getProperty("Foo")); - } - - public void testPropertiesWithNoNames() throws Exception { - try { - new DefaultFieldSet(new String[] { "foo", "bar" }).getProperties(); - fail("Expected IllegalStateException"); - } - catch (IllegalStateException e) { - // expected - } - } - - public void testPropertiesWithWhiteSpace() throws Exception{ - - assertEquals("bar", new DefaultFieldSet(new String[] { "foo", "bar " }, new String[] { "Foo", "Bar"}).getProperties().getProperty("Bar")); - } - - public void testPropertiesWithNullValues() throws Exception{ - - fieldSet = new DefaultFieldSet(new String[] { null, "bar" }, new String[] { "Foo", "Bar"}); - assertEquals("bar", fieldSet.getProperties().getProperty("Bar")); - assertEquals(null, fieldSet.getProperties().getProperty("Foo")); - } - - public void testAccessByNameWhenNamesMissing() throws Exception { - try { - new DefaultFieldSet(new String[] { "1", "2" }).readInt("a"); - fail("Expected IllegalArgumentException"); - } - catch (IllegalArgumentException e) { - // expected - } - } - - public void testGetValues() { - String[] values = fieldSet.getValues(); - assertEquals(tokens.length, values.length); - for (int i = 0; i < tokens.length; i++) { - assertEquals(tokens[i], values[i]); - } - } - - public void testPaddedLong(){ - FieldSet fs = new DefaultFieldSet(new String[]{"00000009"}); - - long value = fs.readLong(0); - assertEquals(value, 9); - } - - public void testReadRawString() { - String name = "fieldName"; - String value = " string with trailing whitespace "; - FieldSet fs = new DefaultFieldSet(new String[] { value }, new String[]{ name }); - - assertEquals(value, fs.readRawString(0)); - assertEquals(value, fs.readRawString(name)); - } -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.batch.io.file; + +import java.math.BigDecimal; +import java.text.ParseException; + +import junit.framework.TestCase; + +import org.springframework.batch.io.file.mapping.DefaultFieldSet; +import org.springframework.batch.io.file.mapping.FieldSet; + +public class FieldSetTests extends TestCase { + FieldSet fieldSet; + + String[] tokens; + + String[] names; + + protected void setUp() throws Exception { + super.setUp(); + + tokens = new String[] { "TestString", "true", "C", "10", "-472", "354224", "543", "124.3", "424.3", "324", + null, "2007-10-12", "12-10-2007", "" }; + names = new String[] { "String", "Boolean", "Char", "Byte", "Short", "Integer", "Long", "Float", "Double", + "BigDecimal", "Null", "Date", "DatePattern", "BlankInput" }; + + fieldSet = new DefaultFieldSet(tokens, names); + assertEquals(14, fieldSet.getFieldCount()); + + } + + public void testNames() throws Exception { + assertEquals(fieldSet.getFieldCount(), fieldSet.getNames().length); + } + + public void testNamesNotKnown() throws Exception { + fieldSet = new DefaultFieldSet(new String[]{"foo"}); + try { + fieldSet.getNames(); + fail("Expected IllegalStateException"); + } catch (IllegalStateException e) { + // expected + } + } + + public void testReadString() throws ParseException { + + assertEquals(fieldSet.readString(0), "TestString"); + assertEquals(fieldSet.readString("String"), "TestString"); + + } + + public void testReadChar() throws Exception { + + assertTrue(fieldSet.readChar(2) == 'C'); + assertTrue(fieldSet.readChar("Char") == 'C'); + + } + + public void testReadBooleanTrue() throws Exception { + + assertTrue(fieldSet.readBoolean(1)); + assertTrue(fieldSet.readBoolean("Boolean")); + + } + + public void testReadByte() throws Exception { + + assertTrue(fieldSet.readByte(3) == 10); + assertTrue(fieldSet.readByte("Byte") == 10); + + } + + public void testReadShort() throws Exception { + + assertTrue(fieldSet.readShort(4) == -472); + assertTrue(fieldSet.readShort("Short") == -472); + + } + + public void testReadFloat() throws Exception { + + assertTrue(fieldSet.readFloat(7) == 124.3F); + assertTrue(fieldSet.readFloat("Float") == 124.3F); + + } + + public void testReadDouble() throws Exception { + + assertTrue(fieldSet.readDouble(8) == 424.3); + assertTrue(fieldSet.readDouble("Double") == 424.3); + + } + + public void testReadBigDecimal() throws Exception { + + BigDecimal bd = new BigDecimal(324); + assertEquals(fieldSet.readBigDecimal(9), bd); + assertEquals(fieldSet.readBigDecimal("BigDecimal"), bd); + + } + + public void testReadBigDecimalWithDefaultvalue() throws Exception { + + BigDecimal bd = new BigDecimal(324); + assertEquals(bd, fieldSet.readBigDecimal(10, bd)); + assertEquals(bd, fieldSet.readBigDecimal("Null", bd)); + + } + + public void testReadNonExistentField() throws Exception { + + try { + fieldSet.readString("something"); + fail("field set returns value even value was never put in!"); + } + catch (IllegalArgumentException e) { + assertTrue(e.getMessage().indexOf("something") > 0); + } + + } + + public void testReadIndexOutOfRange() throws Exception { + + try { + fieldSet.readShort(-1); + fail("field set returns value even index is out of range!"); + } + catch (IndexOutOfBoundsException e) { + assertTrue(true); + } + + try { + fieldSet.readShort(99); + fail("field set returns value even index is out of range!"); + } + catch (Exception e) { + assertTrue(true); + } + } + + public void testReadBooleanWithTrueValue() { + assertTrue(fieldSet.readBoolean(1, "true")); + assertFalse(fieldSet.readBoolean(1, "incorrect trueValue")); + + assertTrue(fieldSet.readBoolean("Boolean", "true")); + assertFalse(fieldSet.readBoolean("Boolean", "incorrect trueValue")); + } + + public void testReadBooleanFalse() { + fieldSet = new DefaultFieldSet(new String[] { "false" }); + assertFalse(fieldSet.readBoolean(0)); + } + + public void testReadCharException() { + try { + fieldSet.readChar(1); + fail("the value read was not a character, exception expected"); + } + catch (IllegalArgumentException expected) { + assertTrue(true); + } + + try { + fieldSet.readChar("Boolean"); + fail("the value read was not a character, exception expected"); + } + catch (IllegalArgumentException expected) { + assertTrue(true); + } + } + + public void testReadInt() throws Exception { + assertEquals(354224, fieldSet.readInt(5)); + assertEquals(354224, fieldSet.readInt("Integer")); + } + + public void testReadBlankInt(){ + + //Trying to parse a blank field as an integer, but without a default + //value should throw a NumberFormatException + try{ + fieldSet.readInt(13); + fail(); + } + catch(NumberFormatException ex){ + //expected + } + + try{ + fieldSet.readInt("BlankInput"); + fail(); + } + catch(NumberFormatException ex){ + //expected + } + + } + + public void testReadLong() throws Exception { + assertEquals(543, fieldSet.readLong(6)); + assertEquals(543, fieldSet.readLong("Long")); + } + + public void testReadLongWithPadding() throws Exception { + fieldSet = new DefaultFieldSet(new String[] {"000009"}); + assertEquals(9, fieldSet.readLong(0)); + } + + public void testReadIntWithNullValue() { + assertEquals(5, fieldSet.readInt(10, 5)); + assertEquals(5, fieldSet.readInt("Null", 5)); + } + + public void testReadIntWithDefaultAndNotNull() throws Exception { + assertEquals(354224, fieldSet.readInt(5, 5)); + assertEquals(354224, fieldSet.readInt("Integer", 5)); + } + + public void testReadLongWithNullValue() { + int defaultValue = 5; + int indexOfNull = 10; + int indexNotNull = 6; + String nameNull = "Null"; + String nameNotNull = "Long"; + long longValueAtIndex = 543; + + assertEquals(fieldSet.readLong(indexOfNull, defaultValue), defaultValue); + assertEquals(fieldSet.readLong(indexNotNull, defaultValue), longValueAtIndex); + + assertEquals(fieldSet.readLong(nameNull, defaultValue), defaultValue); + assertEquals(fieldSet.readLong(nameNotNull, defaultValue), longValueAtIndex); + } + + public void testReadBigDecimalInvalid() { + int index = 0; + + try { + fieldSet.readBigDecimal(index); + fail("field value is not a number, exception expected"); + } + catch (IllegalArgumentException e) { + assertTrue(e.getMessage().indexOf("TestString") > 0); + } + + } + + public void testReadBigDecimalByNameInvalid() throws Exception { + try { + fieldSet.readBigDecimal("String"); + fail("field value is not a number, exception expected"); + } + catch (IllegalArgumentException e) { + assertTrue(e.getMessage().indexOf("TestString") > 0); + assertTrue(e.getMessage().indexOf("name: [String]") > 0); + } + } + + public void testReadDate() throws Exception { + assertNotNull(fieldSet.readDate(11)); + assertNotNull(fieldSet.readDate("Date")); + } + + public void testReadDateInvalid() throws Exception { + + try { + fieldSet.readDate(0); + fail("field value is not a date, exception expected"); + } + catch (IllegalArgumentException e) { + assertTrue(e.getMessage().indexOf("TestString") > 0); + } + + } + + public void testReadDateInvalidByName() throws Exception { + + try { + fieldSet.readDate("String"); + fail("field value is not a date, exception expected"); + } + catch (IllegalArgumentException e) { + assertTrue(e.getMessage().indexOf("name: [String]") > 0); + } + + } + + public void testReadDateInvalidWithPattern() throws Exception { + + try { + fieldSet.readDate(0, "dd-MM-yyyy"); + fail("field value is not a date, exception expected"); + } + catch (IllegalArgumentException e) { + assertTrue(e.getMessage().indexOf("dd-MM-yyyy") > 0); + } + } + + public void testReadDateByNameInvalidWithPattern() throws Exception { + + try { + fieldSet.readDate("String", "dd-MM-yyyy"); + fail("field value is not a date, exception expected"); + } + catch (IllegalArgumentException e) { + assertTrue(e.getMessage().indexOf("dd-MM-yyyy") > 0); + assertTrue(e.getMessage().indexOf("String") > 0); + } + } + + public void testEquals() { + + assertEquals(fieldSet, fieldSet); + assertEquals(fieldSet, new DefaultFieldSet(tokens)); + + String[] tokens1 = new String[] { "token1" }; + String[] tokens2 = new String[] { "token1" }; + FieldSet fs1 = new DefaultFieldSet(tokens1); + FieldSet fs2 = new DefaultFieldSet(tokens2); + assertEquals(fs1, fs2); + } + + public void testNullField() { + assertEquals(null, fieldSet.readString(10)); + } + + public void testEqualsNull() { + assertFalse(fieldSet.equals(null)); + } + + public void testEqualsNullTokens() { + assertFalse(new DefaultFieldSet(null).equals(fieldSet)); + } + + public void testEqualsNotEqual() throws Exception { + + String[] tokens1 = new String[] { "token1" }; + String[] tokens2 = new String[] { "token1", "token2" }; + FieldSet fs1 = new DefaultFieldSet(tokens1); + FieldSet fs2 = new DefaultFieldSet(tokens2); + assertFalse(fs1.equals(fs2)); + + } + + public void testHashCode() throws Exception { + assertEquals(fieldSet.hashCode(), new DefaultFieldSet(tokens).hashCode()); + } + + public void testHashCodeWithNullTokens() throws Exception { + assertEquals(0, new DefaultFieldSet(null).hashCode()); + } + + public void testConstructor() throws Exception { + try { + new DefaultFieldSet(new String[] { "1", "2" }, new String[] { "a" }); + fail("Expected IllegalArgumentException"); + } + catch (IllegalArgumentException e) { + // expected + } + } + + public void testToStringWithNames() throws Exception { + fieldSet = new DefaultFieldSet(new String[] { "foo", "bar" }, new String[] { "Foo", "Bar" }); + assertTrue(fieldSet.toString().indexOf("Foo=foo") >= 0); + } + + public void testToStringWithoutNames() throws Exception { + fieldSet = new DefaultFieldSet(new String[] { "foo", "bar" }); + assertTrue(fieldSet.toString().indexOf("foo") >= 0); + } + + public void testToStringNullTokens() throws Exception { + fieldSet = new DefaultFieldSet(null); + assertEquals("", fieldSet.toString()); + } + + public void testProperties() throws Exception { + assertEquals("foo", new DefaultFieldSet(new String[] { "foo", "bar" }, new String[] { "Foo", "Bar" }).getProperties() + .getProperty("Foo")); + } + + public void testPropertiesWithNoNames() throws Exception { + try { + new DefaultFieldSet(new String[] { "foo", "bar" }).getProperties(); + fail("Expected IllegalStateException"); + } + catch (IllegalStateException e) { + // expected + } + } + + public void testPropertiesWithWhiteSpace() throws Exception{ + + assertEquals("bar", new DefaultFieldSet(new String[] { "foo", "bar " }, new String[] { "Foo", "Bar"}).getProperties().getProperty("Bar")); + } + + public void testPropertiesWithNullValues() throws Exception{ + + fieldSet = new DefaultFieldSet(new String[] { null, "bar" }, new String[] { "Foo", "Bar"}); + assertEquals("bar", fieldSet.getProperties().getProperty("Bar")); + assertEquals(null, fieldSet.getProperties().getProperty("Foo")); + } + + public void testAccessByNameWhenNamesMissing() throws Exception { + try { + new DefaultFieldSet(new String[] { "1", "2" }).readInt("a"); + fail("Expected IllegalArgumentException"); + } + catch (IllegalArgumentException e) { + // expected + } + } + + public void testGetValues() { + String[] values = fieldSet.getValues(); + assertEquals(tokens.length, values.length); + for (int i = 0; i < tokens.length; i++) { + assertEquals(tokens[i], values[i]); + } + } + + public void testPaddedLong(){ + FieldSet fs = new DefaultFieldSet(new String[]{"00000009"}); + + long value = fs.readLong(0); + assertEquals(value, 9); + } + + public void testReadRawString() { + String name = "fieldName"; + String value = " string with trailing whitespace "; + FieldSet fs = new DefaultFieldSet(new String[] { value }, new String[]{ name }); + + assertEquals(value, fs.readRawString(0)); + assertEquals(value, fs.readRawString(name)); + } +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/file/FlatFileItemReaderBasicTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/file/FlatFileItemReaderBasicTests.java index 99eb6b7c32..3c0839f903 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/file/FlatFileItemReaderBasicTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/file/FlatFileItemReaderBasicTests.java @@ -1,339 +1,339 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.batch.io.file; - -import java.io.IOException; -import java.io.InputStream; - -import junit.framework.TestCase; - -import org.springframework.batch.io.exception.FlatFileParsingException; -import org.springframework.batch.io.file.mapping.DefaultFieldSet; -import org.springframework.batch.io.file.mapping.FieldSet; -import org.springframework.batch.io.file.mapping.FieldSetMapper; -import org.springframework.batch.io.file.separator.DefaultRecordSeparatorPolicy; -import org.springframework.batch.io.file.transform.DelimitedLineTokenizer; -import org.springframework.batch.io.file.transform.LineTokenizer; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.item.exception.StreamException; -import org.springframework.core.io.AbstractResource; -import org.springframework.core.io.ByteArrayResource; -import org.springframework.core.io.Resource; - -/** - * Tests for {@link FlatFileItemReader} - the fundamental item reading functionality. - * - * @see FlatFileItemReaderAdvancedTests - * @author Dave Syer - */ -public class FlatFileItemReaderBasicTests extends TestCase { - - // object under test - private FlatFileItemReader itemReader = new FlatFileItemReader(); - - // common value used for writing to a file - private String TEST_STRING = "FlatFileInputTemplate-TestData"; - private String TEST_OUTPUT = "[FlatFileInputTemplate-TestData]"; - - private ExecutionContext executionContext; - - // simple stub instead of a realistic tokenizer - private LineTokenizer tokenizer = new LineTokenizer() { - public FieldSet tokenize(String line) { - return new DefaultFieldSet(new String[] { line }); - } - }; - - private FieldSetMapper fieldSetMapper = new FieldSetMapper(){ - public Object mapLine(FieldSet fs) { - return fs; - } - }; - - /** - * Create inputFile, inject mock/stub dependencies for tested object, - * initialize the tested object - */ - protected void setUp() throws Exception { - - itemReader.setResource(getInputResource(TEST_STRING)); - itemReader.setLineTokenizer(tokenizer); - itemReader.setFieldSetMapper(fieldSetMapper); - itemReader.afterPropertiesSet(); - - executionContext = new ExecutionContext(); - } - - /** - * Release resources. - */ - protected void tearDown() throws Exception { - itemReader.close(null); - } - - private Resource getInputResource(String input) { - return new ByteArrayResource(input.getBytes()); - } - - /** - * Regular usage of read method - */ - public void testRead() throws Exception { - itemReader.open(executionContext); - assertEquals("[FlatFileInputTemplate-TestData]", itemReader.read().toString()); - } - - /** - * Regular usage of read method - */ - public void testReadExhausted() throws Exception { - itemReader.open(executionContext); - assertEquals("[FlatFileInputTemplate-TestData]", itemReader.read().toString()); - assertEquals(null, itemReader.read()); - } - - /** - * Regular usage of read method - */ - public void testReadWithTokenizerError() throws Exception { - itemReader.setLineTokenizer(new LineTokenizer() { - public FieldSet tokenize(String line) { - throw new RuntimeException("foo"); - } - }); - try { - itemReader.open(executionContext); - itemReader.read(); - fail("Expected ParsingException"); - } catch (FlatFileParsingException e) { - assertEquals(e.getInput(), TEST_STRING); - assertEquals(e.getLineNumber(), 1); - } - } - - public void testReadWithMapperError() throws Exception { - itemReader.setFieldSetMapper(new FieldSetMapper(){ - public Object mapLine(FieldSet fs) { - throw new RuntimeException("foo"); - } - }); - - try { - itemReader.open(executionContext); - itemReader.read(); - fail("Expected ParsingException"); - } catch (FlatFileParsingException e) { - assertEquals(e.getInput(), TEST_STRING); - assertEquals(e.getLineNumber(), 1); - } - } - - public void testReadBeforeOpen() throws Exception { - itemReader = new FlatFileItemReader(); - itemReader.setResource(getInputResource(TEST_STRING)); - itemReader.setFieldSetMapper(fieldSetMapper); - try { - itemReader.read(); - fail("Expected StreamException"); - } catch (StreamException e) { - assertTrue(e.getMessage().contains("open")); - } - } - - public void testCloseBeforeOpen() throws Exception { - itemReader = new FlatFileItemReader(); - itemReader.setResource(getInputResource(TEST_STRING)); - itemReader.setFieldSetMapper(fieldSetMapper); - itemReader.close(null); - // The open does not happen automatically on a read... - itemReader.open(executionContext); - assertEquals("[FlatFileInputTemplate-TestData]", itemReader.read().toString()); - } - - public void testInitializationWithNullResource() throws Exception { - itemReader = new FlatFileItemReader(); - try { - itemReader.afterPropertiesSet(); - fail("Expected IllegalArgumentException"); - } - catch (IllegalArgumentException e) { - // expected - } - } - - public void testOpenTwiceHasNoEffect() throws Exception { - itemReader.open(executionContext); - testRead(); - } - - public void testSetValidEncoding() throws Exception { - itemReader = new FlatFileItemReader(); - itemReader.setEncoding("UTF-8"); - itemReader.setResource(getInputResource(TEST_STRING)); - itemReader.setFieldSetMapper(fieldSetMapper); - itemReader.open(executionContext); - testRead(); - } - - public void testSetNullEncoding() throws Exception { - itemReader = new FlatFileItemReader(); - itemReader.setEncoding(null); - itemReader.setResource(getInputResource(TEST_STRING)); - try { - itemReader.open(executionContext); - fail("Expected IllegalArgumentException"); - } - catch (IllegalArgumentException e) { - // expected - } - } - - public void testSetInvalidEncoding() throws Exception { - itemReader = new FlatFileItemReader(); - itemReader.setEncoding("foo"); - itemReader.setResource(getInputResource(TEST_STRING)); - try { - itemReader.open(executionContext); - fail("Expected BatchEnvironmentException"); - } - catch (StreamException e) { - // expected - assertEquals("foo", e.getCause().getMessage()); - } - } - - public void testEncoding() throws Exception { - itemReader.setEncoding("UTF-8"); - testRead(); - } - - public void testRecordSeparator() throws Exception { - itemReader.setRecordSeparatorPolicy(new DefaultRecordSeparatorPolicy()); - testRead(); - } - - public void testComments() throws Exception { - itemReader.setResource(getInputResource("% Comment\n"+TEST_STRING)); - itemReader.setComments(new String[] {"%"}); - testRead(); - } - - /** - * Header line is skipped and used to setup fieldSet column names. - */ - public void testColumnNamesInHeader() throws Exception { - final String INPUT = "name1|name2\nvalue1|value2\nvalue3|value4"; - - itemReader = new FlatFileItemReader(); - itemReader.setResource(getInputResource(INPUT)); - itemReader.setLineTokenizer(new DelimitedLineTokenizer('|')); - itemReader.setFieldSetMapper(fieldSetMapper); - itemReader.setFirstLineIsHeader(true); - itemReader.afterPropertiesSet(); - itemReader.open(executionContext); - - FieldSet fs = (FieldSet) itemReader.read(); - assertEquals("value1", fs.readString("name1")); - assertEquals("value2", fs.readString("name2")); - - fs = (FieldSet) itemReader.read(); - assertEquals("value3", fs.readString("name1")); - assertEquals("value4", fs.readString("name2")); - } - - /** - * Header line is skipped and used to setup fieldSet column names. - */ - public void testLinesToSkip() throws Exception { - final String INPUT = "foo bar spam\none two\nthree four"; - - itemReader = new FlatFileItemReader(); - itemReader.setResource(getInputResource(INPUT)); - itemReader.setLineTokenizer(new DelimitedLineTokenizer(' ')); - itemReader.setFieldSetMapper(fieldSetMapper); - itemReader.setLinesToSkip(1); - itemReader.afterPropertiesSet(); - itemReader.open(executionContext); - - FieldSet fs = (FieldSet) itemReader.read(); - assertEquals("one", fs.readString(0)); - assertEquals("two", fs.readString(1)); - - fs = (FieldSet) itemReader.read(); - assertEquals("three", fs.readString(0)); - assertEquals("four", fs.readString(1)); - } - - public void testNonExistantResource() throws Exception{ - - Resource resource = new NonExistentResource(); - - FlatFileItemReader testReader = new FlatFileItemReader(); - testReader.setResource(resource); - testReader.setLineTokenizer(tokenizer); - testReader.setFieldSetMapper(fieldSetMapper); - testReader.setResource(resource); - - //afterPropertiesSet should only throw an exception if the Resource is null - testReader.afterPropertiesSet(); - - try{ - testReader.open(executionContext); - fail(); - }catch(IllegalStateException ex){ - //expected - } - - } - - public void testRuntimeFileCreation() throws Exception{ - - Resource resource = new NonExistentResource(); - - FlatFileItemReader testReader = new FlatFileItemReader(); - testReader.setResource(resource); - testReader.setLineTokenizer(tokenizer); - testReader.setFieldSetMapper(fieldSetMapper); - testReader.setResource(resource); - - //afterPropertiesSet should only throw an exception if the Resource is null - testReader.afterPropertiesSet(); - - //replace the resource to simulate runtime resource creation - testReader.setResource(getInputResource(TEST_STRING)); - testReader.open(executionContext); - assertEquals(TEST_OUTPUT, testReader.read().toString()); - } - - private class NonExistentResource extends AbstractResource{ - - public NonExistentResource() { - } - - public boolean exists() { - return false; - } - - public String getDescription() { - return "NonExistantResource"; - } - - public InputStream getInputStream() throws IOException { - return null; - } - } -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.batch.io.file; + +import java.io.IOException; +import java.io.InputStream; + +import junit.framework.TestCase; + +import org.springframework.batch.io.exception.FlatFileParsingException; +import org.springframework.batch.io.file.mapping.DefaultFieldSet; +import org.springframework.batch.io.file.mapping.FieldSet; +import org.springframework.batch.io.file.mapping.FieldSetMapper; +import org.springframework.batch.io.file.separator.DefaultRecordSeparatorPolicy; +import org.springframework.batch.io.file.transform.DelimitedLineTokenizer; +import org.springframework.batch.io.file.transform.LineTokenizer; +import org.springframework.batch.item.ExecutionContext; +import org.springframework.batch.item.exception.StreamException; +import org.springframework.core.io.AbstractResource; +import org.springframework.core.io.ByteArrayResource; +import org.springframework.core.io.Resource; + +/** + * Tests for {@link FlatFileItemReader} - the fundamental item reading functionality. + * + * @see FlatFileItemReaderAdvancedTests + * @author Dave Syer + */ +public class FlatFileItemReaderBasicTests extends TestCase { + + // object under test + private FlatFileItemReader itemReader = new FlatFileItemReader(); + + // common value used for writing to a file + private String TEST_STRING = "FlatFileInputTemplate-TestData"; + private String TEST_OUTPUT = "[FlatFileInputTemplate-TestData]"; + + private ExecutionContext executionContext; + + // simple stub instead of a realistic tokenizer + private LineTokenizer tokenizer = new LineTokenizer() { + public FieldSet tokenize(String line) { + return new DefaultFieldSet(new String[] { line }); + } + }; + + private FieldSetMapper fieldSetMapper = new FieldSetMapper(){ + public Object mapLine(FieldSet fs) { + return fs; + } + }; + + /** + * Create inputFile, inject mock/stub dependencies for tested object, + * initialize the tested object + */ + protected void setUp() throws Exception { + + itemReader.setResource(getInputResource(TEST_STRING)); + itemReader.setLineTokenizer(tokenizer); + itemReader.setFieldSetMapper(fieldSetMapper); + itemReader.afterPropertiesSet(); + + executionContext = new ExecutionContext(); + } + + /** + * Release resources. + */ + protected void tearDown() throws Exception { + itemReader.close(null); + } + + private Resource getInputResource(String input) { + return new ByteArrayResource(input.getBytes()); + } + + /** + * Regular usage of read method + */ + public void testRead() throws Exception { + itemReader.open(executionContext); + assertEquals("[FlatFileInputTemplate-TestData]", itemReader.read().toString()); + } + + /** + * Regular usage of read method + */ + public void testReadExhausted() throws Exception { + itemReader.open(executionContext); + assertEquals("[FlatFileInputTemplate-TestData]", itemReader.read().toString()); + assertEquals(null, itemReader.read()); + } + + /** + * Regular usage of read method + */ + public void testReadWithTokenizerError() throws Exception { + itemReader.setLineTokenizer(new LineTokenizer() { + public FieldSet tokenize(String line) { + throw new RuntimeException("foo"); + } + }); + try { + itemReader.open(executionContext); + itemReader.read(); + fail("Expected ParsingException"); + } catch (FlatFileParsingException e) { + assertEquals(e.getInput(), TEST_STRING); + assertEquals(e.getLineNumber(), 1); + } + } + + public void testReadWithMapperError() throws Exception { + itemReader.setFieldSetMapper(new FieldSetMapper(){ + public Object mapLine(FieldSet fs) { + throw new RuntimeException("foo"); + } + }); + + try { + itemReader.open(executionContext); + itemReader.read(); + fail("Expected ParsingException"); + } catch (FlatFileParsingException e) { + assertEquals(e.getInput(), TEST_STRING); + assertEquals(e.getLineNumber(), 1); + } + } + + public void testReadBeforeOpen() throws Exception { + itemReader = new FlatFileItemReader(); + itemReader.setResource(getInputResource(TEST_STRING)); + itemReader.setFieldSetMapper(fieldSetMapper); + try { + itemReader.read(); + fail("Expected StreamException"); + } catch (StreamException e) { + assertTrue(e.getMessage().contains("open")); + } + } + + public void testCloseBeforeOpen() throws Exception { + itemReader = new FlatFileItemReader(); + itemReader.setResource(getInputResource(TEST_STRING)); + itemReader.setFieldSetMapper(fieldSetMapper); + itemReader.close(null); + // The open does not happen automatically on a read... + itemReader.open(executionContext); + assertEquals("[FlatFileInputTemplate-TestData]", itemReader.read().toString()); + } + + public void testInitializationWithNullResource() throws Exception { + itemReader = new FlatFileItemReader(); + try { + itemReader.afterPropertiesSet(); + fail("Expected IllegalArgumentException"); + } + catch (IllegalArgumentException e) { + // expected + } + } + + public void testOpenTwiceHasNoEffect() throws Exception { + itemReader.open(executionContext); + testRead(); + } + + public void testSetValidEncoding() throws Exception { + itemReader = new FlatFileItemReader(); + itemReader.setEncoding("UTF-8"); + itemReader.setResource(getInputResource(TEST_STRING)); + itemReader.setFieldSetMapper(fieldSetMapper); + itemReader.open(executionContext); + testRead(); + } + + public void testSetNullEncoding() throws Exception { + itemReader = new FlatFileItemReader(); + itemReader.setEncoding(null); + itemReader.setResource(getInputResource(TEST_STRING)); + try { + itemReader.open(executionContext); + fail("Expected IllegalArgumentException"); + } + catch (IllegalArgumentException e) { + // expected + } + } + + public void testSetInvalidEncoding() throws Exception { + itemReader = new FlatFileItemReader(); + itemReader.setEncoding("foo"); + itemReader.setResource(getInputResource(TEST_STRING)); + try { + itemReader.open(executionContext); + fail("Expected BatchEnvironmentException"); + } + catch (StreamException e) { + // expected + assertEquals("foo", e.getCause().getMessage()); + } + } + + public void testEncoding() throws Exception { + itemReader.setEncoding("UTF-8"); + testRead(); + } + + public void testRecordSeparator() throws Exception { + itemReader.setRecordSeparatorPolicy(new DefaultRecordSeparatorPolicy()); + testRead(); + } + + public void testComments() throws Exception { + itemReader.setResource(getInputResource("% Comment\n"+TEST_STRING)); + itemReader.setComments(new String[] {"%"}); + testRead(); + } + + /** + * Header line is skipped and used to setup fieldSet column names. + */ + public void testColumnNamesInHeader() throws Exception { + final String INPUT = "name1|name2\nvalue1|value2\nvalue3|value4"; + + itemReader = new FlatFileItemReader(); + itemReader.setResource(getInputResource(INPUT)); + itemReader.setLineTokenizer(new DelimitedLineTokenizer('|')); + itemReader.setFieldSetMapper(fieldSetMapper); + itemReader.setFirstLineIsHeader(true); + itemReader.afterPropertiesSet(); + itemReader.open(executionContext); + + FieldSet fs = (FieldSet) itemReader.read(); + assertEquals("value1", fs.readString("name1")); + assertEquals("value2", fs.readString("name2")); + + fs = (FieldSet) itemReader.read(); + assertEquals("value3", fs.readString("name1")); + assertEquals("value4", fs.readString("name2")); + } + + /** + * Header line is skipped and used to setup fieldSet column names. + */ + public void testLinesToSkip() throws Exception { + final String INPUT = "foo bar spam\none two\nthree four"; + + itemReader = new FlatFileItemReader(); + itemReader.setResource(getInputResource(INPUT)); + itemReader.setLineTokenizer(new DelimitedLineTokenizer(' ')); + itemReader.setFieldSetMapper(fieldSetMapper); + itemReader.setLinesToSkip(1); + itemReader.afterPropertiesSet(); + itemReader.open(executionContext); + + FieldSet fs = (FieldSet) itemReader.read(); + assertEquals("one", fs.readString(0)); + assertEquals("two", fs.readString(1)); + + fs = (FieldSet) itemReader.read(); + assertEquals("three", fs.readString(0)); + assertEquals("four", fs.readString(1)); + } + + public void testNonExistantResource() throws Exception{ + + Resource resource = new NonExistentResource(); + + FlatFileItemReader testReader = new FlatFileItemReader(); + testReader.setResource(resource); + testReader.setLineTokenizer(tokenizer); + testReader.setFieldSetMapper(fieldSetMapper); + testReader.setResource(resource); + + //afterPropertiesSet should only throw an exception if the Resource is null + testReader.afterPropertiesSet(); + + try{ + testReader.open(executionContext); + fail(); + }catch(IllegalStateException ex){ + //expected + } + + } + + public void testRuntimeFileCreation() throws Exception{ + + Resource resource = new NonExistentResource(); + + FlatFileItemReader testReader = new FlatFileItemReader(); + testReader.setResource(resource); + testReader.setLineTokenizer(tokenizer); + testReader.setFieldSetMapper(fieldSetMapper); + testReader.setResource(resource); + + //afterPropertiesSet should only throw an exception if the Resource is null + testReader.afterPropertiesSet(); + + //replace the resource to simulate runtime resource creation + testReader.setResource(getInputResource(TEST_STRING)); + testReader.open(executionContext); + assertEquals(TEST_OUTPUT, testReader.read().toString()); + } + + private class NonExistentResource extends AbstractResource{ + + public NonExistentResource() { + } + + public boolean exists() { + return false; + } + + public String getDescription() { + return "NonExistantResource"; + } + + public InputStream getInputStream() throws IOException { + return null; + } + } +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/file/ResourceLineReaderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/file/ResourceLineReaderTests.java index 8d31b2f51e..6c93950506 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/file/ResourceLineReaderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/file/ResourceLineReaderTests.java @@ -1,196 +1,196 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.batch.io.file; - -import java.io.IOException; -import java.io.InputStream; - -import junit.framework.TestCase; - -import org.springframework.batch.io.file.separator.ResourceLineReader; -import org.springframework.batch.io.file.separator.SuffixRecordSeparatorPolicy; -import org.springframework.batch.item.exception.StreamException; -import org.springframework.core.io.ByteArrayResource; -import org.springframework.core.io.InputStreamResource; -import org.springframework.core.io.Resource; - -/** - * @author Rob Harrop - */ -public class ResourceLineReaderTests extends TestCase { - - public void testBadResource() throws Exception { - ResourceLineReader reader = new ResourceLineReader(new InputStreamResource(new InputStream() { - public int read() throws IOException { - throw new IOException("Foo"); - } - })); - try { - reader.read(); - fail("Expected InputException"); - } - catch (StreamException e) { - // expected - assertTrue(e.getMessage().startsWith("Unable to read")); - } - } - - public void testRead() throws Exception { - Resource resource = new ByteArrayResource("a,b,c\n1,2,3".getBytes()); - ResourceLineReader reader = new ResourceLineReader(resource); - int count = 0; - String line; - while ((line = (String) reader.read()) != null) { - count++; - assertNotNull(line); - } - - assertEquals(2, count); - } - - public void testCloseTwice() throws Exception { - Resource resource = new ByteArrayResource("a,b,c\n1,2,3".getBytes()); - ResourceLineReader reader = new ResourceLineReader(resource); - reader.open(); - reader.close(null); - try { - reader.close(null); // just closing a BufferedReader twice should be fine - } catch (Exception e) { - fail("Unexpected Exception "+e); - } - assertEquals("a,b,c", reader.read()); - } - - public void testEncoding() throws Exception { - Resource resource = new ByteArrayResource("a,b,c\n1,2,3".getBytes()); - ResourceLineReader reader = new ResourceLineReader(resource, "UTF-8"); - int count = 0; - String line; - while ((line = (String) reader.read()) != null) { - count++; - assertNotNull(line); - } - - assertEquals(2, count); - } - - public void testLineCount() throws Exception { - Resource resource = new ByteArrayResource("1,2,\"3\n4\"\n5,6,7".getBytes()); - ResourceLineReader reader = new ResourceLineReader(resource); - reader.read(); - assertEquals(2, reader.getPosition()); - } - - public void testLineContent() throws Exception { - Resource resource = new ByteArrayResource("1,2,3\n4\n5,6,7".getBytes()); - ResourceLineReader reader = new ResourceLineReader(resource); - assertEquals("1,2,3", reader.read()); - assertEquals("4", reader.read()); - assertEquals("5,6,7", reader.read()); - } - - public void testLineContentWhenLineContainsQuotedNewline() throws Exception { - Resource resource = new ByteArrayResource("1,2,\"3\n4\"\n5,6,7".getBytes()); - ResourceLineReader reader = new ResourceLineReader(resource); - assertEquals("1,2,\"3\n4\"", reader.read()); - assertEquals("5,6,7", reader.read()); - } - - public void testLineEndings() throws Exception { - Resource resource = new ByteArrayResource("1\n2\r\n3".getBytes()); - ResourceLineReader reader = new ResourceLineReader(resource); - reader.read(); - String line = (String) reader.read(); - assertEquals("2", line); - assertEquals(2, reader.getPosition()); - line = (String) reader.read(); - assertEquals("3", line); - assertEquals(3, reader.getPosition()); - } - - public void testDefaultComments() throws Exception { - Resource resource = new ByteArrayResource("1\n# 2\n3".getBytes()); - ResourceLineReader reader = new ResourceLineReader(resource); - reader.read(); - String line = (String) reader.read(); - assertEquals("3", line); - } - - public void testComments() throws Exception { - Resource resource = new ByteArrayResource("1\n-- 2\n3".getBytes()); - ResourceLineReader reader = new ResourceLineReader(resource); - reader.setComments(new String[] {"//", "--"}); - reader.read(); - String line = (String) reader.read(); - assertEquals("3", line); - } - - public void testCommentOnTheLastLine() throws Exception { - Resource resource = new ByteArrayResource("1\n#last line".getBytes()); - ResourceLineReader reader = new ResourceLineReader(resource); - reader.read(); - String line = (String) reader.read(); - assertNull(line); - } - - public void testResetNewReader() throws Exception { - Resource resource = new ByteArrayResource("1\n4\n5".getBytes()); - ResourceLineReader reader = new ResourceLineReader(resource); - reader.reset(); - assertEquals(0, reader.getPosition()); - } - - public void testMarkReset() throws Exception { - Resource resource = new ByteArrayResource("1\n4\n5".getBytes()); - ResourceLineReader reader = new ResourceLineReader(resource); - reader.read(); - assertEquals(1, reader.getPosition()); - reader.mark(); - reader.read(); - assertEquals(2, reader.getPosition()); - reader.reset(); - reader.read(); - assertEquals(2, reader.getPosition()); - } - - public void testMarkOnFirstRead() throws Exception { - Resource resource = new ByteArrayResource("1\n# 2\n3".getBytes()); - ResourceLineReader reader = new ResourceLineReader(resource); - reader.read(); - // The first read should do a mark() so the reset goes back to the beginning. - reader.reset(); - String line = (String) reader.read(); - assertEquals("1", line); - } - - public void testMarkAfterClose() throws Exception { - Resource resource = new ByteArrayResource("1\n# 2\n3".getBytes()); - ResourceLineReader reader = new ResourceLineReader(resource); - reader.read(); - reader.close(null); - reader.mark(); - } - - public void testNonDefaultRecordSeparatorPolicy() throws Exception { - Resource resource = new ByteArrayResource("1\n\"4\n5\"; \n6".getBytes()); - ResourceLineReader reader = new ResourceLineReader(resource); - reader.setRecordSeparatorPolicy(new SuffixRecordSeparatorPolicy()); - assertEquals(0, reader.getPosition()); - String line = (String) reader.read(); - assertEquals("1\"4\n5\"", line); - } -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.batch.io.file; + +import java.io.IOException; +import java.io.InputStream; + +import junit.framework.TestCase; + +import org.springframework.batch.io.file.separator.ResourceLineReader; +import org.springframework.batch.io.file.separator.SuffixRecordSeparatorPolicy; +import org.springframework.batch.item.exception.StreamException; +import org.springframework.core.io.ByteArrayResource; +import org.springframework.core.io.InputStreamResource; +import org.springframework.core.io.Resource; + +/** + * @author Rob Harrop + */ +public class ResourceLineReaderTests extends TestCase { + + public void testBadResource() throws Exception { + ResourceLineReader reader = new ResourceLineReader(new InputStreamResource(new InputStream() { + public int read() throws IOException { + throw new IOException("Foo"); + } + })); + try { + reader.read(); + fail("Expected InputException"); + } + catch (StreamException e) { + // expected + assertTrue(e.getMessage().startsWith("Unable to read")); + } + } + + public void testRead() throws Exception { + Resource resource = new ByteArrayResource("a,b,c\n1,2,3".getBytes()); + ResourceLineReader reader = new ResourceLineReader(resource); + int count = 0; + String line; + while ((line = (String) reader.read()) != null) { + count++; + assertNotNull(line); + } + + assertEquals(2, count); + } + + public void testCloseTwice() throws Exception { + Resource resource = new ByteArrayResource("a,b,c\n1,2,3".getBytes()); + ResourceLineReader reader = new ResourceLineReader(resource); + reader.open(); + reader.close(null); + try { + reader.close(null); // just closing a BufferedReader twice should be fine + } catch (Exception e) { + fail("Unexpected Exception "+e); + } + assertEquals("a,b,c", reader.read()); + } + + public void testEncoding() throws Exception { + Resource resource = new ByteArrayResource("a,b,c\n1,2,3".getBytes()); + ResourceLineReader reader = new ResourceLineReader(resource, "UTF-8"); + int count = 0; + String line; + while ((line = (String) reader.read()) != null) { + count++; + assertNotNull(line); + } + + assertEquals(2, count); + } + + public void testLineCount() throws Exception { + Resource resource = new ByteArrayResource("1,2,\"3\n4\"\n5,6,7".getBytes()); + ResourceLineReader reader = new ResourceLineReader(resource); + reader.read(); + assertEquals(2, reader.getPosition()); + } + + public void testLineContent() throws Exception { + Resource resource = new ByteArrayResource("1,2,3\n4\n5,6,7".getBytes()); + ResourceLineReader reader = new ResourceLineReader(resource); + assertEquals("1,2,3", reader.read()); + assertEquals("4", reader.read()); + assertEquals("5,6,7", reader.read()); + } + + public void testLineContentWhenLineContainsQuotedNewline() throws Exception { + Resource resource = new ByteArrayResource("1,2,\"3\n4\"\n5,6,7".getBytes()); + ResourceLineReader reader = new ResourceLineReader(resource); + assertEquals("1,2,\"3\n4\"", reader.read()); + assertEquals("5,6,7", reader.read()); + } + + public void testLineEndings() throws Exception { + Resource resource = new ByteArrayResource("1\n2\r\n3".getBytes()); + ResourceLineReader reader = new ResourceLineReader(resource); + reader.read(); + String line = (String) reader.read(); + assertEquals("2", line); + assertEquals(2, reader.getPosition()); + line = (String) reader.read(); + assertEquals("3", line); + assertEquals(3, reader.getPosition()); + } + + public void testDefaultComments() throws Exception { + Resource resource = new ByteArrayResource("1\n# 2\n3".getBytes()); + ResourceLineReader reader = new ResourceLineReader(resource); + reader.read(); + String line = (String) reader.read(); + assertEquals("3", line); + } + + public void testComments() throws Exception { + Resource resource = new ByteArrayResource("1\n-- 2\n3".getBytes()); + ResourceLineReader reader = new ResourceLineReader(resource); + reader.setComments(new String[] {"//", "--"}); + reader.read(); + String line = (String) reader.read(); + assertEquals("3", line); + } + + public void testCommentOnTheLastLine() throws Exception { + Resource resource = new ByteArrayResource("1\n#last line".getBytes()); + ResourceLineReader reader = new ResourceLineReader(resource); + reader.read(); + String line = (String) reader.read(); + assertNull(line); + } + + public void testResetNewReader() throws Exception { + Resource resource = new ByteArrayResource("1\n4\n5".getBytes()); + ResourceLineReader reader = new ResourceLineReader(resource); + reader.reset(); + assertEquals(0, reader.getPosition()); + } + + public void testMarkReset() throws Exception { + Resource resource = new ByteArrayResource("1\n4\n5".getBytes()); + ResourceLineReader reader = new ResourceLineReader(resource); + reader.read(); + assertEquals(1, reader.getPosition()); + reader.mark(); + reader.read(); + assertEquals(2, reader.getPosition()); + reader.reset(); + reader.read(); + assertEquals(2, reader.getPosition()); + } + + public void testMarkOnFirstRead() throws Exception { + Resource resource = new ByteArrayResource("1\n# 2\n3".getBytes()); + ResourceLineReader reader = new ResourceLineReader(resource); + reader.read(); + // The first read should do a mark() so the reset goes back to the beginning. + reader.reset(); + String line = (String) reader.read(); + assertEquals("1", line); + } + + public void testMarkAfterClose() throws Exception { + Resource resource = new ByteArrayResource("1\n# 2\n3".getBytes()); + ResourceLineReader reader = new ResourceLineReader(resource); + reader.read(); + reader.close(null); + reader.mark(); + } + + public void testNonDefaultRecordSeparatorPolicy() throws Exception { + Resource resource = new ByteArrayResource("1\n\"4\n5\"; \n6".getBytes()); + ResourceLineReader reader = new ResourceLineReader(resource); + reader.setRecordSeparatorPolicy(new SuffixRecordSeparatorPolicy()); + assertEquals(0, reader.getPosition()); + String line = (String) reader.read(); + assertEquals("1\"4\n5\"", line); + } +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/file/mapping/TestObject.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/file/mapping/TestObject.java index 4f3d87b725..c3e0965214 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/file/mapping/TestObject.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/file/mapping/TestObject.java @@ -1,135 +1,135 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.batch.io.file.mapping; - -import java.math.BigDecimal; -import java.util.Date; - -public class TestObject { - String varString; - - boolean varBoolean; - - char varChar; - - byte varByte; - - short varShort; - - int varInt; - - long varLong; - - float varFloat; - - double varDouble; - - BigDecimal varBigDecimal; - - Date varDate; - - public Date getVarDate() { - return (Date)varDate.clone(); - } - - public void setVarDate(Date varDate) { - this.varDate = varDate == null ? null : (Date)varDate.clone(); - } - - public TestObject() { - } - - public BigDecimal getVarBigDecimal() { - return varBigDecimal; - } - - public void setVarBigDecimal(BigDecimal varBigDecimal) { - this.varBigDecimal = varBigDecimal; - } - - public boolean isVarBoolean() { - return varBoolean; - } - - public void setVarBoolean(boolean varBoolean) { - this.varBoolean = varBoolean; - } - - public byte getVarByte() { - return varByte; - } - - public void setVarByte(byte varByte) { - this.varByte = varByte; - } - - public char getVarChar() { - return varChar; - } - - public void setVarChar(char varChar) { - this.varChar = varChar; - } - - public double getVarDouble() { - return varDouble; - } - - public void setVarDouble(double varDouble) { - this.varDouble = varDouble; - } - - public float getVarFloat() { - return varFloat; - } - - public void setVarFloat(float varFloat) { - this.varFloat = varFloat; - } - - public long getVarLong() { - return varLong; - } - - public void setVarLong(long varLong) { - this.varLong = varLong; - } - - public short getVarShort() { - return varShort; - } - - public void setVarShort(short varShort) { - this.varShort = varShort; - } - - public String getVarString() { - return varString; - } - - public void setVarString(String varString) { - this.varString = varString; - } - - public int getVarInt() { - return varInt; - } - - public void setVarInt(int varInt) { - this.varInt = varInt; - } -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.batch.io.file.mapping; + +import java.math.BigDecimal; +import java.util.Date; + +public class TestObject { + String varString; + + boolean varBoolean; + + char varChar; + + byte varByte; + + short varShort; + + int varInt; + + long varLong; + + float varFloat; + + double varDouble; + + BigDecimal varBigDecimal; + + Date varDate; + + public Date getVarDate() { + return (Date)varDate.clone(); + } + + public void setVarDate(Date varDate) { + this.varDate = varDate == null ? null : (Date)varDate.clone(); + } + + public TestObject() { + } + + public BigDecimal getVarBigDecimal() { + return varBigDecimal; + } + + public void setVarBigDecimal(BigDecimal varBigDecimal) { + this.varBigDecimal = varBigDecimal; + } + + public boolean isVarBoolean() { + return varBoolean; + } + + public void setVarBoolean(boolean varBoolean) { + this.varBoolean = varBoolean; + } + + public byte getVarByte() { + return varByte; + } + + public void setVarByte(byte varByte) { + this.varByte = varByte; + } + + public char getVarChar() { + return varChar; + } + + public void setVarChar(char varChar) { + this.varChar = varChar; + } + + public double getVarDouble() { + return varDouble; + } + + public void setVarDouble(double varDouble) { + this.varDouble = varDouble; + } + + public float getVarFloat() { + return varFloat; + } + + public void setVarFloat(float varFloat) { + this.varFloat = varFloat; + } + + public long getVarLong() { + return varLong; + } + + public void setVarLong(long varLong) { + this.varLong = varLong; + } + + public short getVarShort() { + return varShort; + } + + public void setVarShort(short varShort) { + this.varShort = varShort; + } + + public String getVarString() { + return varString; + } + + public void setVarString(String varString) { + this.varString = varString; + } + + public int getVarInt() { + return varInt; + } + + public void setVarInt(int varInt) { + this.varInt = varInt; + } +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/file/transform/CommonLineTokenizerTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/file/transform/CommonLineTokenizerTests.java index 0804bb156c..fc01e61bdd 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/file/transform/CommonLineTokenizerTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/file/transform/CommonLineTokenizerTests.java @@ -1,39 +1,39 @@ -package org.springframework.batch.io.file.transform; - -import java.util.List; - -import org.springframework.batch.io.file.transform.AbstractLineTokenizer; - -import junit.framework.TestCase; - -/** - * Tests for {@link AbstractLineTokenizer}. - * - * @author Robert Kasanicky - * @author Dave Syer - */ -public class CommonLineTokenizerTests extends TestCase { - - /** - * Columns names are considered to be specified if they are not null or empty. - */ - public void testHasNames() { - AbstractLineTokenizer tokenizer = new AbstractLineTokenizer() { - protected List doTokenize(String line) { - return null; - } - }; - - assertFalse(tokenizer.hasNames()); - - tokenizer.setNames(null); - assertFalse(tokenizer.hasNames()); - - tokenizer.setNames(new String[0]); - assertFalse(tokenizer.hasNames()); - - tokenizer.setNames(new String[]{"name1", "name2"}); - assertTrue(tokenizer.hasNames()); - } - -} +package org.springframework.batch.io.file.transform; + +import java.util.List; + +import org.springframework.batch.io.file.transform.AbstractLineTokenizer; + +import junit.framework.TestCase; + +/** + * Tests for {@link AbstractLineTokenizer}. + * + * @author Robert Kasanicky + * @author Dave Syer + */ +public class CommonLineTokenizerTests extends TestCase { + + /** + * Columns names are considered to be specified if they are not null or empty. + */ + public void testHasNames() { + AbstractLineTokenizer tokenizer = new AbstractLineTokenizer() { + protected List doTokenize(String line) { + return null; + } + }; + + assertFalse(tokenizer.hasNames()); + + tokenizer.setNames(null); + assertFalse(tokenizer.hasNames()); + + tokenizer.setNames(new String[0]); + assertFalse(tokenizer.hasNames()); + + tokenizer.setNames(new String[]{"name1", "name2"}); + assertTrue(tokenizer.hasNames()); + } + +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/file/transform/DelimitedLineTokenizerTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/file/transform/DelimitedLineTokenizerTests.java index 35ea686786..e8d3b43809 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/file/transform/DelimitedLineTokenizerTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/file/transform/DelimitedLineTokenizerTests.java @@ -1,185 +1,185 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.batch.io.file.transform; - -import junit.framework.TestCase; - -import org.springframework.batch.io.file.mapping.FieldSet; -import org.springframework.batch.io.file.transform.AbstractLineTokenizer; -import org.springframework.batch.io.file.transform.DelimitedLineTokenizer; - -public class DelimitedLineTokenizerTests extends TestCase { - - private static final String TOKEN_MATCHES = "token equals the expected string"; - - private DelimitedLineTokenizer tokenizer = new DelimitedLineTokenizer(); - - public void testTokenizeRegularUse() { - FieldSet tokens = tokenizer.tokenize("sfd,\"Well,I have no idea what to do in the afternoon\",sFj, asdf,,as\n"); - assertEquals(6, tokens.getFieldCount()); - assertTrue(TOKEN_MATCHES, tokens.readString(0).equals("sfd")); - assertTrue(TOKEN_MATCHES, tokens.readString(1).equals("Well,I have no idea what to do in the afternoon")); - assertTrue(TOKEN_MATCHES, tokens.readString(2).equals("sFj")); - assertTrue(TOKEN_MATCHES, tokens.readString(3).equals("asdf")); - assertTrue(TOKEN_MATCHES, tokens.readString(4).equals("")); - assertTrue(TOKEN_MATCHES, tokens.readString(5).equals("as")); - - tokens = tokenizer.tokenize("First string,"); - assertEquals(2, tokens.getFieldCount()); - assertTrue(TOKEN_MATCHES, tokens.readString(0).equals("First string")); - assertTrue(TOKEN_MATCHES, tokens.readString(1).equals("")); - } - - public void testInvalidConstructorArgument() { - try { - new DelimitedLineTokenizer(DelimitedLineTokenizer.DEFAULT_QUOTE_CHARACTER); - fail("Quote character can't be used as delimiter for delimited line tokenizer!"); - } - catch (Exception e) { - assertTrue(true); - } - } - - public void testDelimitedLineTokenizer() { - FieldSet line = tokenizer.tokenize("a,b,c"); - assertEquals(3, line.getFieldCount()); - } - - public void testNames() { - tokenizer.setNames(new String[] {"A", "B", "C"}); - FieldSet line = tokenizer.tokenize("a,b,c"); - assertEquals(3, line.getFieldCount()); - assertEquals("a", line.readString("A")); - } - - public void testTooFewNames() { - tokenizer.setNames(new String[] {"A", "B"}); - try { - tokenizer.tokenize("a,b,c"); - fail("Expected IllegalArgumentException"); - } - catch (IllegalArgumentException e) { - // expected - } - } - - public void testTooManyNames() { - tokenizer.setNames(new String[] {"A", "B", "C", "D"}); - FieldSet line = tokenizer.tokenize("a,b,c"); - assertEquals(4, line.getFieldCount()); - assertEquals("c", line.readString("C")); - assertEquals(null, line.readString("D")); - } - - public void testDelimitedLineTokenizerChar() { - AbstractLineTokenizer tokenizer = new DelimitedLineTokenizer(' '); - FieldSet line = tokenizer.tokenize("a b c"); - assertEquals(3, line.getFieldCount()); - } - - public void testTokenizeWithQuotes() { - FieldSet line = tokenizer.tokenize("a,b,\"c\""); - assertEquals(3, line.getFieldCount()); - assertEquals("c", line.readString(2)); - } - - public void testTokenizeWithNotDefaultQuotes() { - tokenizer.setQuoteCharacter('\''); - FieldSet line = tokenizer.tokenize("a,b,'c'"); - assertEquals(3, line.getFieldCount()); - assertEquals("c", line.readString(2)); - } - - public void testTokenizeWithEscapedQuotes() { - FieldSet line = tokenizer.tokenize("a,\"\"b,\"\"\"c\""); - assertEquals(3, line.getFieldCount()); - assertEquals("\"\"b", line.readString(1)); - assertEquals("\"c", line.readString(2)); - } - - public void testTokenizeWithUnclosedQuotes() { - tokenizer.setQuoteCharacter('\''); - FieldSet line = tokenizer.tokenize("a,\"b,c"); - assertEquals(3, line.getFieldCount()); - assertEquals("\"b", line.readString(1)); - assertEquals("c", line.readString(2)); - } - - public void testTokenizeWithSpaceAtEnd() { - FieldSet line = tokenizer.tokenize("a,b,c "); - assertEquals(3, line.getFieldCount()); - assertEquals("c", line.readString(2)); - } - - public void testTokenizeWithQuoteAndSpaceAtEnd() { - FieldSet line = tokenizer.tokenize("a,b,\"c\" "); - assertEquals(3, line.getFieldCount()); - assertEquals("c", line.readString(2)); - } - - public void testTokenizeWithQuoteAndSpaceBeforeDelimiter() { - FieldSet line = tokenizer.tokenize("a,\"b\" ,c"); - assertEquals(3, line.getFieldCount()); - assertEquals("b", line.readString(1)); - } - - public void testTokenizeWithDelimiterAtEnd() { - FieldSet line = tokenizer.tokenize("a,b,c,"); - assertEquals(4, line.getFieldCount()); - assertEquals("c", line.readString(2)); - assertEquals("", line.readString(3)); - } - - public void testEmptyLine() throws Exception { - FieldSet line = tokenizer.tokenize(""); - assertEquals(0, line.getFieldCount()); - } - - public void testWhitespaceLine() throws Exception { - FieldSet line = tokenizer.tokenize(" "); - // whitespace counts as text - assertEquals(1, line.getFieldCount()); - } - - public void testNullLine() throws Exception { - FieldSet line = tokenizer.tokenize(null); - // null doesn't... - assertEquals(0, line.getFieldCount()); - } - - public void testMultiLineField() throws Exception { - FieldSet line = tokenizer.tokenize("a,b,c\nrap"); - assertEquals(3, line.getFieldCount()); - assertEquals("c\nrap", line.readString(2)); - - } - - public void testMultiLineFieldWithQuotes() throws Exception { - FieldSet line = tokenizer.tokenize("a,b,\"c\nrap\""); - assertEquals(3, line.getFieldCount()); - assertEquals("c\nrap", line.readString(2)); - - } - - public void testTokenizeWithQuotesEmptyValue() { - FieldSet line = tokenizer.tokenize("\"a\",\"b\",\"\",\"d\""); - assertEquals(4, line.getFieldCount()); - assertEquals("", line.readString(2)); - } - - -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.batch.io.file.transform; + +import junit.framework.TestCase; + +import org.springframework.batch.io.file.mapping.FieldSet; +import org.springframework.batch.io.file.transform.AbstractLineTokenizer; +import org.springframework.batch.io.file.transform.DelimitedLineTokenizer; + +public class DelimitedLineTokenizerTests extends TestCase { + + private static final String TOKEN_MATCHES = "token equals the expected string"; + + private DelimitedLineTokenizer tokenizer = new DelimitedLineTokenizer(); + + public void testTokenizeRegularUse() { + FieldSet tokens = tokenizer.tokenize("sfd,\"Well,I have no idea what to do in the afternoon\",sFj, asdf,,as\n"); + assertEquals(6, tokens.getFieldCount()); + assertTrue(TOKEN_MATCHES, tokens.readString(0).equals("sfd")); + assertTrue(TOKEN_MATCHES, tokens.readString(1).equals("Well,I have no idea what to do in the afternoon")); + assertTrue(TOKEN_MATCHES, tokens.readString(2).equals("sFj")); + assertTrue(TOKEN_MATCHES, tokens.readString(3).equals("asdf")); + assertTrue(TOKEN_MATCHES, tokens.readString(4).equals("")); + assertTrue(TOKEN_MATCHES, tokens.readString(5).equals("as")); + + tokens = tokenizer.tokenize("First string,"); + assertEquals(2, tokens.getFieldCount()); + assertTrue(TOKEN_MATCHES, tokens.readString(0).equals("First string")); + assertTrue(TOKEN_MATCHES, tokens.readString(1).equals("")); + } + + public void testInvalidConstructorArgument() { + try { + new DelimitedLineTokenizer(DelimitedLineTokenizer.DEFAULT_QUOTE_CHARACTER); + fail("Quote character can't be used as delimiter for delimited line tokenizer!"); + } + catch (Exception e) { + assertTrue(true); + } + } + + public void testDelimitedLineTokenizer() { + FieldSet line = tokenizer.tokenize("a,b,c"); + assertEquals(3, line.getFieldCount()); + } + + public void testNames() { + tokenizer.setNames(new String[] {"A", "B", "C"}); + FieldSet line = tokenizer.tokenize("a,b,c"); + assertEquals(3, line.getFieldCount()); + assertEquals("a", line.readString("A")); + } + + public void testTooFewNames() { + tokenizer.setNames(new String[] {"A", "B"}); + try { + tokenizer.tokenize("a,b,c"); + fail("Expected IllegalArgumentException"); + } + catch (IllegalArgumentException e) { + // expected + } + } + + public void testTooManyNames() { + tokenizer.setNames(new String[] {"A", "B", "C", "D"}); + FieldSet line = tokenizer.tokenize("a,b,c"); + assertEquals(4, line.getFieldCount()); + assertEquals("c", line.readString("C")); + assertEquals(null, line.readString("D")); + } + + public void testDelimitedLineTokenizerChar() { + AbstractLineTokenizer tokenizer = new DelimitedLineTokenizer(' '); + FieldSet line = tokenizer.tokenize("a b c"); + assertEquals(3, line.getFieldCount()); + } + + public void testTokenizeWithQuotes() { + FieldSet line = tokenizer.tokenize("a,b,\"c\""); + assertEquals(3, line.getFieldCount()); + assertEquals("c", line.readString(2)); + } + + public void testTokenizeWithNotDefaultQuotes() { + tokenizer.setQuoteCharacter('\''); + FieldSet line = tokenizer.tokenize("a,b,'c'"); + assertEquals(3, line.getFieldCount()); + assertEquals("c", line.readString(2)); + } + + public void testTokenizeWithEscapedQuotes() { + FieldSet line = tokenizer.tokenize("a,\"\"b,\"\"\"c\""); + assertEquals(3, line.getFieldCount()); + assertEquals("\"\"b", line.readString(1)); + assertEquals("\"c", line.readString(2)); + } + + public void testTokenizeWithUnclosedQuotes() { + tokenizer.setQuoteCharacter('\''); + FieldSet line = tokenizer.tokenize("a,\"b,c"); + assertEquals(3, line.getFieldCount()); + assertEquals("\"b", line.readString(1)); + assertEquals("c", line.readString(2)); + } + + public void testTokenizeWithSpaceAtEnd() { + FieldSet line = tokenizer.tokenize("a,b,c "); + assertEquals(3, line.getFieldCount()); + assertEquals("c", line.readString(2)); + } + + public void testTokenizeWithQuoteAndSpaceAtEnd() { + FieldSet line = tokenizer.tokenize("a,b,\"c\" "); + assertEquals(3, line.getFieldCount()); + assertEquals("c", line.readString(2)); + } + + public void testTokenizeWithQuoteAndSpaceBeforeDelimiter() { + FieldSet line = tokenizer.tokenize("a,\"b\" ,c"); + assertEquals(3, line.getFieldCount()); + assertEquals("b", line.readString(1)); + } + + public void testTokenizeWithDelimiterAtEnd() { + FieldSet line = tokenizer.tokenize("a,b,c,"); + assertEquals(4, line.getFieldCount()); + assertEquals("c", line.readString(2)); + assertEquals("", line.readString(3)); + } + + public void testEmptyLine() throws Exception { + FieldSet line = tokenizer.tokenize(""); + assertEquals(0, line.getFieldCount()); + } + + public void testWhitespaceLine() throws Exception { + FieldSet line = tokenizer.tokenize(" "); + // whitespace counts as text + assertEquals(1, line.getFieldCount()); + } + + public void testNullLine() throws Exception { + FieldSet line = tokenizer.tokenize(null); + // null doesn't... + assertEquals(0, line.getFieldCount()); + } + + public void testMultiLineField() throws Exception { + FieldSet line = tokenizer.tokenize("a,b,c\nrap"); + assertEquals(3, line.getFieldCount()); + assertEquals("c\nrap", line.readString(2)); + + } + + public void testMultiLineFieldWithQuotes() throws Exception { + FieldSet line = tokenizer.tokenize("a,b,\"c\nrap\""); + assertEquals(3, line.getFieldCount()); + assertEquals("c\nrap", line.readString(2)); + + } + + public void testTokenizeWithQuotesEmptyValue() { + FieldSet line = tokenizer.tokenize("\"a\",\"b\",\"\",\"d\""); + assertEquals(4, line.getFieldCount()); + assertEquals("", line.readString(2)); + } + + +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/file/transform/FixedLengthLineAggregatorTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/file/transform/FixedLengthLineAggregatorTests.java index 3a95a2c34f..b3f2347412 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/file/transform/FixedLengthLineAggregatorTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/file/transform/FixedLengthLineAggregatorTests.java @@ -1,172 +1,172 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.batch.io.file.transform; - -import org.springframework.batch.io.file.mapping.DefaultFieldSet; -import org.springframework.batch.io.file.transform.FixedLengthLineAggregator; -import org.springframework.batch.io.file.transform.Range; - -import junit.framework.TestCase; - -/** - * Unit tests for {@link FixedLengthLineAggregator} - * - * @author robert.kasanicky - * @author peter.zozom - */ -public class FixedLengthLineAggregatorTests extends TestCase { - - // object under test - private FixedLengthLineAggregator aggregator = new FixedLengthLineAggregator(); - - /** - * If no ranges are specified, IllegalArgumentException is thrown - */ - public void testAggregateNullRecordDescriptor() { - String[] args = { "does not matter what is here" }; - - try { - aggregator.aggregate(new DefaultFieldSet(args)); - fail("should not work with no ranges specified"); - } - catch (IllegalArgumentException expected) { - // expected - } - } - - /** - * Count of aggregated strings does not match the number of columns - */ - public void testAggregateWrongArgumentCount() { - String[] string = { "only one test string" }; - aggregator.setColumns(new Range[0]); - - try { - aggregator.aggregate(new DefaultFieldSet(string)); - fail("Exception expected: count of aggregated strings" - + " does not match the number of columns"); - } - catch (IllegalArgumentException expected) { - // expected - } - } - - /** - * Text length exceeds the length of the column. - */ - public void testAggregateInvalidInputLength() { - String[] args = { "Oversize" }; - aggregator.setColumns(new Range[] {new Range(1,args[0].length()-1)}); - try { - aggregator.aggregate(new DefaultFieldSet(args)); - fail("Invalid text length, exception should have been thrown"); - } - catch (IllegalArgumentException expected) { - // expected - } - } - - /** - * Test aggregation - */ - public void testAggregate() { - String[] args = { "Matchsize", "Smallsize" }; - aggregator.setColumns(new Range[] {new Range(1,9), new Range(10,18)}); - String result = aggregator.aggregate(new DefaultFieldSet(args)); - assertEquals("MatchsizeSmallsize", result); - } - - /** - * Test aggregation with last range unbound - */ - public void testAggregateWithLastRangeUnbound() { - String[] args = { "Matchsize", "Smallsize" }; - aggregator.setColumns(new Range[] {new Range(1,12), new Range(13)}); - String result = aggregator.aggregate(new DefaultFieldSet(args)); - assertEquals("Matchsize Smallsize", result); - } - - - /** - * Test aggregation with right alignment - */ - public void testAggregateFormattedRight() { - String[] args = { "Matchsize", "Smallsize" }; - aggregator.setAlignment("right"); - aggregator.setColumns(new Range[] {new Range(1,13), new Range(14,23)}); - String result = aggregator.aggregate(new DefaultFieldSet(args)); - assertEquals(23,result.length()); - assertEquals(result, " Matchsize Smallsize"); - } - - /** - * Test aggregation with center alignment - */ - public void testAggregateFormattedCenter() { - String[] args = { "Matchsize", "Smallsize" }; - aggregator.setAlignment("center"); - aggregator.setColumns(new Range[] {new Range(1,13), new Range(14,25)}); - String result = aggregator.aggregate(new DefaultFieldSet(args)); - assertEquals(result, " Matchsize Smallsize "); - } - - /** - * Test aggregation with left alignment - */ - public void testAggregateWithCustomPadding() { - String[] args = { "Matchsize", "Smallsize" }; - aggregator.setPadding('.'); - aggregator.setAlignment("left"); - aggregator.setColumns(new Range[] {new Range(1,13), new Range(14,24)}); - String result = aggregator.aggregate(new DefaultFieldSet(args)); - assertEquals(result, "Matchsize....Smallsize.."); - } - - /** - * Test aggregation with left alignment - */ - public void testAggregateFormattedLeft() { - String[] args = { "Matchsize", "Smallsize" }; - aggregator.setAlignment("left"); - aggregator.setColumns(new Range[] {new Range(1,13), new Range(14,24)}); - String result = aggregator.aggregate(new DefaultFieldSet(args)); - assertEquals(result, "Matchsize Smallsize "); - } - - - /** - * Try set ivalid alignment - */ - public void testInvalidAlignment() { - try { - aggregator.setAlignment("foo"); - fail("Exception was expected: invalid alignment value"); - } catch (IllegalArgumentException iae) { - // expected - } - } - - /** - * If one of the passed arguments is null, string filled with spaces should - * be returned - */ - public void testAggregateNullArgument() { - String[] args = { null }; - aggregator.setColumns(new Range[] {new Range(1,3)}); - assertEquals(" ", aggregator.aggregate(new DefaultFieldSet(args))); - } -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.batch.io.file.transform; + +import org.springframework.batch.io.file.mapping.DefaultFieldSet; +import org.springframework.batch.io.file.transform.FixedLengthLineAggregator; +import org.springframework.batch.io.file.transform.Range; + +import junit.framework.TestCase; + +/** + * Unit tests for {@link FixedLengthLineAggregator} + * + * @author robert.kasanicky + * @author peter.zozom + */ +public class FixedLengthLineAggregatorTests extends TestCase { + + // object under test + private FixedLengthLineAggregator aggregator = new FixedLengthLineAggregator(); + + /** + * If no ranges are specified, IllegalArgumentException is thrown + */ + public void testAggregateNullRecordDescriptor() { + String[] args = { "does not matter what is here" }; + + try { + aggregator.aggregate(new DefaultFieldSet(args)); + fail("should not work with no ranges specified"); + } + catch (IllegalArgumentException expected) { + // expected + } + } + + /** + * Count of aggregated strings does not match the number of columns + */ + public void testAggregateWrongArgumentCount() { + String[] string = { "only one test string" }; + aggregator.setColumns(new Range[0]); + + try { + aggregator.aggregate(new DefaultFieldSet(string)); + fail("Exception expected: count of aggregated strings" + + " does not match the number of columns"); + } + catch (IllegalArgumentException expected) { + // expected + } + } + + /** + * Text length exceeds the length of the column. + */ + public void testAggregateInvalidInputLength() { + String[] args = { "Oversize" }; + aggregator.setColumns(new Range[] {new Range(1,args[0].length()-1)}); + try { + aggregator.aggregate(new DefaultFieldSet(args)); + fail("Invalid text length, exception should have been thrown"); + } + catch (IllegalArgumentException expected) { + // expected + } + } + + /** + * Test aggregation + */ + public void testAggregate() { + String[] args = { "Matchsize", "Smallsize" }; + aggregator.setColumns(new Range[] {new Range(1,9), new Range(10,18)}); + String result = aggregator.aggregate(new DefaultFieldSet(args)); + assertEquals("MatchsizeSmallsize", result); + } + + /** + * Test aggregation with last range unbound + */ + public void testAggregateWithLastRangeUnbound() { + String[] args = { "Matchsize", "Smallsize" }; + aggregator.setColumns(new Range[] {new Range(1,12), new Range(13)}); + String result = aggregator.aggregate(new DefaultFieldSet(args)); + assertEquals("Matchsize Smallsize", result); + } + + + /** + * Test aggregation with right alignment + */ + public void testAggregateFormattedRight() { + String[] args = { "Matchsize", "Smallsize" }; + aggregator.setAlignment("right"); + aggregator.setColumns(new Range[] {new Range(1,13), new Range(14,23)}); + String result = aggregator.aggregate(new DefaultFieldSet(args)); + assertEquals(23,result.length()); + assertEquals(result, " Matchsize Smallsize"); + } + + /** + * Test aggregation with center alignment + */ + public void testAggregateFormattedCenter() { + String[] args = { "Matchsize", "Smallsize" }; + aggregator.setAlignment("center"); + aggregator.setColumns(new Range[] {new Range(1,13), new Range(14,25)}); + String result = aggregator.aggregate(new DefaultFieldSet(args)); + assertEquals(result, " Matchsize Smallsize "); + } + + /** + * Test aggregation with left alignment + */ + public void testAggregateWithCustomPadding() { + String[] args = { "Matchsize", "Smallsize" }; + aggregator.setPadding('.'); + aggregator.setAlignment("left"); + aggregator.setColumns(new Range[] {new Range(1,13), new Range(14,24)}); + String result = aggregator.aggregate(new DefaultFieldSet(args)); + assertEquals(result, "Matchsize....Smallsize.."); + } + + /** + * Test aggregation with left alignment + */ + public void testAggregateFormattedLeft() { + String[] args = { "Matchsize", "Smallsize" }; + aggregator.setAlignment("left"); + aggregator.setColumns(new Range[] {new Range(1,13), new Range(14,24)}); + String result = aggregator.aggregate(new DefaultFieldSet(args)); + assertEquals(result, "Matchsize Smallsize "); + } + + + /** + * Try set ivalid alignment + */ + public void testInvalidAlignment() { + try { + aggregator.setAlignment("foo"); + fail("Exception was expected: invalid alignment value"); + } catch (IllegalArgumentException iae) { + // expected + } + } + + /** + * If one of the passed arguments is null, string filled with spaces should + * be returned + */ + public void testAggregateNullArgument() { + String[] args = { null }; + aggregator.setColumns(new Range[] {new Range(1,3)}); + assertEquals(" ", aggregator.aggregate(new DefaultFieldSet(args))); + } +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/file/transform/FixedLengthTokenizerTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/file/transform/FixedLengthTokenizerTests.java index 6fc194c6ad..8c55756730 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/file/transform/FixedLengthTokenizerTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/file/transform/FixedLengthTokenizerTests.java @@ -1,128 +1,128 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.batch.io.file.transform; - -import junit.framework.TestCase; - -import org.springframework.batch.io.file.mapping.FieldSet; -import org.springframework.batch.io.file.transform.FixedLengthTokenizer; -import org.springframework.batch.io.file.transform.Range; - -public class FixedLengthTokenizerTests extends TestCase { - - private FixedLengthTokenizer tokenizer = new FixedLengthTokenizer(); - - private String line = null; - - /** - * if null or empty string is tokenized, tokenizer returns empty fieldset - * (with no tokens). - */ - public void testTokenizeEmptyString() { - tokenizer.setColumns(new Range[] {new Range(1,5),new Range(6,10),new Range(11,15)}); - FieldSet tokens = tokenizer.tokenize(""); - assertEquals(0, tokens.getFieldCount()); - } - - public void testTokenizeNullString() { - tokenizer.setColumns(new Range[] {new Range(1,5),new Range(6,10),new Range(11,15)}); - FieldSet tokens = tokenizer.tokenize(null); - assertEquals(0, tokens.getFieldCount()); - } - - public void testTokenizeRegularUse() { - tokenizer.setColumns(new Range[] {new Range(1,2),new Range(3,7),new Range(8,12)}); - // test shorter line as defined by record descriptor - line = "H1"; - FieldSet tokens = tokenizer.tokenize(line); - assertEquals(3, tokens.getFieldCount()); - assertEquals("H1", tokens.readString(0)); - assertEquals("", tokens.readString(1)); - assertEquals("", tokens.readString(2)); - } - - public void testNormalLength() throws Exception { - tokenizer.setColumns(new Range[] {new Range(1,10),new Range(11,25),new Range(26,30)}); - // test shorter line as defined by record descriptor - line = "H1"; - FieldSet tokens = tokenizer.tokenize(line); - // test normal length - line = "H1 12345678 12345"; - tokens = tokenizer.tokenize(line); - assertEquals(3, tokens.getFieldCount()); - assertEquals(line.substring(0, 10).trim(), tokens.readString(0)); - assertEquals(line.substring(10, 25).trim(), tokens.readString(1)); - assertEquals(line.substring(25).trim(), tokens.readString(2)); - } - - public void testLongerLinesRestIgnored() throws Exception { - tokenizer.setColumns(new Range[] {new Range(1,10),new Range(11,25),new Range(26,30)}); - // test shorter line as defined by record descriptor - line = "H1"; - FieldSet tokens = tokenizer.tokenize(line); - // test longer lines => rest will be ignored - line = "H1 12345678 1234567890"; - tokens = tokenizer.tokenize(line); - assertEquals(3, tokens.getFieldCount()); - assertEquals(line.substring(0, 10).trim(), tokens.readString(0)); - assertEquals(line.substring(10, 25).trim(), tokens.readString(1)); - assertEquals(line.substring(25, 30).trim(), tokens.readString(2)); - } - - public void testNonAdjacentRangesUnsorted() throws Exception { - tokenizer.setColumns(new Range[] {new Range(14,28), new Range(34,38), new Range(1,10)}); - // test shorter line as defined by record descriptor - line = "H1"; - FieldSet tokens = tokenizer.tokenize(line); - // test normal length - line = "H1 +++12345678 +++++12345+++"; - tokens = tokenizer.tokenize(line); - assertEquals(3, tokens.getFieldCount()); - assertEquals(line.substring(0, 10).trim(), tokens.readString(2)); - assertEquals(line.substring(13, 28).trim(), tokens.readString(0)); - assertEquals(line.substring(33, 38).trim(), tokens.readString(1)); - } - - public void testAnotherTypeOfRecord() throws Exception { - tokenizer.setColumns(new Range[] {new Range(1,5),new Range(6,15),new Range(16,25),new Range(26,27)}); - // test shorter line as defined by record descriptor - line = "H1"; - FieldSet tokens = tokenizer.tokenize(line); - // test another type of record - line = "H2 123456 12345 12"; - tokens = tokenizer.tokenize(line); - assertEquals(4, tokens.getFieldCount()); - assertEquals(line.substring(0, 5).trim(), tokens.readString(0)); - assertEquals(line.substring(5, 15).trim(), tokens.readString(1)); - assertEquals(line.substring(15, 25).trim(), tokens.readString(2)); - assertEquals(line.substring(25).trim(), tokens.readString(3)); - } - - public void testTokenizerInvalidSetup() { - tokenizer.setNames(new String[] {"a", "b"}); - tokenizer.setColumns(new Range[] {new Range(1,5),new Range(6,15),new Range(16,25),new Range(26,27)}); - - try { - tokenizer.tokenize("Test tokenize"); - fail("Exception was expected: too few names provided"); - } - catch (Exception e) { - assertTrue(true); - } - } - -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.batch.io.file.transform; + +import junit.framework.TestCase; + +import org.springframework.batch.io.file.mapping.FieldSet; +import org.springframework.batch.io.file.transform.FixedLengthTokenizer; +import org.springframework.batch.io.file.transform.Range; + +public class FixedLengthTokenizerTests extends TestCase { + + private FixedLengthTokenizer tokenizer = new FixedLengthTokenizer(); + + private String line = null; + + /** + * if null or empty string is tokenized, tokenizer returns empty fieldset + * (with no tokens). + */ + public void testTokenizeEmptyString() { + tokenizer.setColumns(new Range[] {new Range(1,5),new Range(6,10),new Range(11,15)}); + FieldSet tokens = tokenizer.tokenize(""); + assertEquals(0, tokens.getFieldCount()); + } + + public void testTokenizeNullString() { + tokenizer.setColumns(new Range[] {new Range(1,5),new Range(6,10),new Range(11,15)}); + FieldSet tokens = tokenizer.tokenize(null); + assertEquals(0, tokens.getFieldCount()); + } + + public void testTokenizeRegularUse() { + tokenizer.setColumns(new Range[] {new Range(1,2),new Range(3,7),new Range(8,12)}); + // test shorter line as defined by record descriptor + line = "H1"; + FieldSet tokens = tokenizer.tokenize(line); + assertEquals(3, tokens.getFieldCount()); + assertEquals("H1", tokens.readString(0)); + assertEquals("", tokens.readString(1)); + assertEquals("", tokens.readString(2)); + } + + public void testNormalLength() throws Exception { + tokenizer.setColumns(new Range[] {new Range(1,10),new Range(11,25),new Range(26,30)}); + // test shorter line as defined by record descriptor + line = "H1"; + FieldSet tokens = tokenizer.tokenize(line); + // test normal length + line = "H1 12345678 12345"; + tokens = tokenizer.tokenize(line); + assertEquals(3, tokens.getFieldCount()); + assertEquals(line.substring(0, 10).trim(), tokens.readString(0)); + assertEquals(line.substring(10, 25).trim(), tokens.readString(1)); + assertEquals(line.substring(25).trim(), tokens.readString(2)); + } + + public void testLongerLinesRestIgnored() throws Exception { + tokenizer.setColumns(new Range[] {new Range(1,10),new Range(11,25),new Range(26,30)}); + // test shorter line as defined by record descriptor + line = "H1"; + FieldSet tokens = tokenizer.tokenize(line); + // test longer lines => rest will be ignored + line = "H1 12345678 1234567890"; + tokens = tokenizer.tokenize(line); + assertEquals(3, tokens.getFieldCount()); + assertEquals(line.substring(0, 10).trim(), tokens.readString(0)); + assertEquals(line.substring(10, 25).trim(), tokens.readString(1)); + assertEquals(line.substring(25, 30).trim(), tokens.readString(2)); + } + + public void testNonAdjacentRangesUnsorted() throws Exception { + tokenizer.setColumns(new Range[] {new Range(14,28), new Range(34,38), new Range(1,10)}); + // test shorter line as defined by record descriptor + line = "H1"; + FieldSet tokens = tokenizer.tokenize(line); + // test normal length + line = "H1 +++12345678 +++++12345+++"; + tokens = tokenizer.tokenize(line); + assertEquals(3, tokens.getFieldCount()); + assertEquals(line.substring(0, 10).trim(), tokens.readString(2)); + assertEquals(line.substring(13, 28).trim(), tokens.readString(0)); + assertEquals(line.substring(33, 38).trim(), tokens.readString(1)); + } + + public void testAnotherTypeOfRecord() throws Exception { + tokenizer.setColumns(new Range[] {new Range(1,5),new Range(6,15),new Range(16,25),new Range(26,27)}); + // test shorter line as defined by record descriptor + line = "H1"; + FieldSet tokens = tokenizer.tokenize(line); + // test another type of record + line = "H2 123456 12345 12"; + tokens = tokenizer.tokenize(line); + assertEquals(4, tokens.getFieldCount()); + assertEquals(line.substring(0, 5).trim(), tokens.readString(0)); + assertEquals(line.substring(5, 15).trim(), tokens.readString(1)); + assertEquals(line.substring(15, 25).trim(), tokens.readString(2)); + assertEquals(line.substring(25).trim(), tokens.readString(3)); + } + + public void testTokenizerInvalidSetup() { + tokenizer.setNames(new String[] {"a", "b"}); + tokenizer.setColumns(new Range[] {new Range(1,5),new Range(6,15),new Range(16,25),new Range(26,27)}); + + try { + tokenizer.tokenize("Test tokenize"); + fail("Exception was expected: too few names provided"); + } + catch (Exception e) { + assertTrue(true); + } + } + +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/file/transform/RangeArrayPropertyEditorTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/file/transform/RangeArrayPropertyEditorTests.java index 02863ad4d4..27e1a7ecad 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/file/transform/RangeArrayPropertyEditorTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/file/transform/RangeArrayPropertyEditorTests.java @@ -1,109 +1,109 @@ -package org.springframework.batch.io.file.transform; - -import org.springframework.batch.io.file.transform.Range; -import org.springframework.batch.io.file.transform.RangeArrayPropertyEditor; - -import junit.framework.TestCase; - -public class RangeArrayPropertyEditorTests extends TestCase { - - private Range[] ranges; - private RangeArrayPropertyEditor pe; - - public void setUp() { - - ranges = null; - - pe = new RangeArrayPropertyEditor() { - public void setValue(Object value) { - ranges = (Range[]) value; - } - - public Object getValue() { - return ranges; - } - }; - } - - public void testSetAsText() { - pe.setAsText("15, 32, 1-10, 33"); - - // result should be 15-31, 32-32, 1-10, 33-unbound - assertEquals(4, ranges.length); - assertEquals(15, ranges[0].getMin()); - assertEquals(31, ranges[0].getMax()); - assertEquals(32, ranges[1].getMin()); - assertEquals(32, ranges[1].getMax()); - assertEquals(1, ranges[2].getMin()); - assertEquals(10, ranges[2].getMax()); - assertEquals(33, ranges[3].getMin()); - assertFalse(ranges[3].hasMaxValue()); - } - - public void testSetAsTextWithNoSpaces() { - pe.setAsText("15,32"); - - // result should be 15-31, 32-unbound - assertEquals(2, ranges.length); - assertEquals(15, ranges[0].getMin()); - assertEquals(31, ranges[0].getMax()); - assertEquals(32, ranges[1].getMin()); - assertFalse(ranges[1].hasMaxValue()); - } - - public void testGetAsText() { - - ranges = new Range[] { new Range(20), new Range(6, 15), new Range(2), - new Range(26, 95) }; - assertEquals("20, 6-15, 2, 26-95", pe.getAsText()); - } - - public void testValidDisjointRanges() { - pe.setForceDisjointRanges(true); - - // test disjoint ranges - pe.setAsText("1-5,11-15"); - - assertEquals(2, ranges.length); - assertEquals(1, ranges[0].getMin()); - assertEquals(5, ranges[0].getMax()); - assertEquals(11, ranges[1].getMin()); - assertEquals(15, ranges[1].getMax()); - - } - - public void testInvalidOverlappingRanges() { - - pe.setForceDisjointRanges(true); - - // test joint ranges - try { - pe.setAsText("1-10, 5-15"); - fail("Exception expected: ranges are not disjoint"); - } catch (IllegalArgumentException iae) { - // expected - } - } - - public void testValidOverlappingRanges() { - - // test joint ranges - pe.setAsText("1-10, 5-15"); - assertEquals(2, ranges.length); - assertEquals(1, ranges[0].getMin()); - assertEquals(10, ranges[0].getMax()); - assertEquals(5, ranges[1].getMin()); - assertEquals(15, ranges[1].getMax()); - - } - - public void testInvalidInput() { - - try { - pe.setAsText("1-5, b"); - fail("Exception expected: 2nd range is invalid"); - } catch (IllegalArgumentException iae) { - // expected - } - } -} +package org.springframework.batch.io.file.transform; + +import org.springframework.batch.io.file.transform.Range; +import org.springframework.batch.io.file.transform.RangeArrayPropertyEditor; + +import junit.framework.TestCase; + +public class RangeArrayPropertyEditorTests extends TestCase { + + private Range[] ranges; + private RangeArrayPropertyEditor pe; + + public void setUp() { + + ranges = null; + + pe = new RangeArrayPropertyEditor() { + public void setValue(Object value) { + ranges = (Range[]) value; + } + + public Object getValue() { + return ranges; + } + }; + } + + public void testSetAsText() { + pe.setAsText("15, 32, 1-10, 33"); + + // result should be 15-31, 32-32, 1-10, 33-unbound + assertEquals(4, ranges.length); + assertEquals(15, ranges[0].getMin()); + assertEquals(31, ranges[0].getMax()); + assertEquals(32, ranges[1].getMin()); + assertEquals(32, ranges[1].getMax()); + assertEquals(1, ranges[2].getMin()); + assertEquals(10, ranges[2].getMax()); + assertEquals(33, ranges[3].getMin()); + assertFalse(ranges[3].hasMaxValue()); + } + + public void testSetAsTextWithNoSpaces() { + pe.setAsText("15,32"); + + // result should be 15-31, 32-unbound + assertEquals(2, ranges.length); + assertEquals(15, ranges[0].getMin()); + assertEquals(31, ranges[0].getMax()); + assertEquals(32, ranges[1].getMin()); + assertFalse(ranges[1].hasMaxValue()); + } + + public void testGetAsText() { + + ranges = new Range[] { new Range(20), new Range(6, 15), new Range(2), + new Range(26, 95) }; + assertEquals("20, 6-15, 2, 26-95", pe.getAsText()); + } + + public void testValidDisjointRanges() { + pe.setForceDisjointRanges(true); + + // test disjoint ranges + pe.setAsText("1-5,11-15"); + + assertEquals(2, ranges.length); + assertEquals(1, ranges[0].getMin()); + assertEquals(5, ranges[0].getMax()); + assertEquals(11, ranges[1].getMin()); + assertEquals(15, ranges[1].getMax()); + + } + + public void testInvalidOverlappingRanges() { + + pe.setForceDisjointRanges(true); + + // test joint ranges + try { + pe.setAsText("1-10, 5-15"); + fail("Exception expected: ranges are not disjoint"); + } catch (IllegalArgumentException iae) { + // expected + } + } + + public void testValidOverlappingRanges() { + + // test joint ranges + pe.setAsText("1-10, 5-15"); + assertEquals(2, ranges.length); + assertEquals(1, ranges[0].getMin()); + assertEquals(10, ranges[0].getMax()); + assertEquals(5, ranges[1].getMin()); + assertEquals(15, ranges[1].getMax()); + + } + + public void testInvalidInput() { + + try { + pe.setAsText("1-5, b"); + fail("Exception expected: 2nd range is invalid"); + } catch (IllegalArgumentException iae) { + // expected + } + } +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/sample/domain/Foo.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/sample/domain/Foo.java index 8c64986db3..bfce33945c 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/sample/domain/Foo.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/sample/domain/Foo.java @@ -1,54 +1,54 @@ -package org.springframework.batch.io.sample.domain; - -import org.apache.commons.lang.builder.EqualsBuilder; -import org.apache.commons.lang.builder.HashCodeBuilder; - -/** - * Simple domain object for testing purposes. - */ -public class Foo { - - private int id; - private String name; - private int value; - - public Foo(){} - - public Foo(int id, String name, int value) { - this.id = id; - this.name = name; - this.value = value; - } - - public String getName() { - return name; - } - public void setName(String name) { - this.name = name; - } - public int getValue() { - return value; - } - public void setValue(int value) { - this.value = value; - } - public int getId() { - return id; - } - public void setId(int id) { - this.id = id; - } - - public String toString() { - return "Foo[id=" +id +",name=" + name + ",value=" + value + "]"; - } - - public boolean equals(Object obj) { - return EqualsBuilder.reflectionEquals(this, obj); - } - - public int hashCode() { - return HashCodeBuilder.reflectionHashCode(this); - } - -} +package org.springframework.batch.io.sample.domain; + +import org.apache.commons.lang.builder.EqualsBuilder; +import org.apache.commons.lang.builder.HashCodeBuilder; + +/** + * Simple domain object for testing purposes. + */ +public class Foo { + + private int id; + private String name; + private int value; + + public Foo(){} + + public Foo(int id, String name, int value) { + this.id = id; + this.name = name; + this.value = value; + } + + public String getName() { + return name; + } + public void setName(String name) { + this.name = name; + } + public int getValue() { + return value; + } + public void setValue(int value) { + this.value = value; + } + public int getId() { + return id; + } + public void setId(int id) { + this.id = id; + } + + public String toString() { + return "Foo[id=" +id +",name=" + name + ",value=" + value + "]"; + } + + public boolean equals(Object obj) { + return EqualsBuilder.reflectionEquals(this, obj); + } + + public int hashCode() { + return HashCodeBuilder.reflectionHashCode(this); + } + +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/sample/domain/FooService.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/sample/domain/FooService.java index 9c9e44bf9e..0e655374f1 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/sample/domain/FooService.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/sample/domain/FooService.java @@ -1,53 +1,53 @@ -package org.springframework.batch.io.sample.domain; - -import java.util.ArrayList; -import java.util.List; - - -/** - * Custom class that contains the logic of providing and processing {@link Foo} - * objects. It serves the purpose to show how providing/processing logic contained in a - * custom class can be reused by the framework. - * - * @author Robert Kasanicky - */ -public class FooService { - - public static final int GENERATION_LIMIT = 10; - - private int counter = 0; - private List generatedFoos = new ArrayList(GENERATION_LIMIT); - private List processedFoos = new ArrayList(GENERATION_LIMIT); - private List processedFooNameValuePairs = new ArrayList(GENERATION_LIMIT); - - public Foo generateFoo() { - if (counter++ >= GENERATION_LIMIT) return null; - - Foo foo = new Foo(counter, "foo" + counter, counter); - generatedFoos.add(foo); - return foo; - - } - - public void processFoo(Foo foo) { - processedFoos.add(foo); - } - - public void processNameValuePair(String name, int value) { - processedFooNameValuePairs.add(new Foo(0, name, value)); - } - - public List getGeneratedFoos() { - return generatedFoos; - } - - public List getProcessedFoos() { - return processedFoos; - } - - public List getProcessedFooNameValuePairs() { - return processedFooNameValuePairs; - } - - -} +package org.springframework.batch.io.sample.domain; + +import java.util.ArrayList; +import java.util.List; + + +/** + * Custom class that contains the logic of providing and processing {@link Foo} + * objects. It serves the purpose to show how providing/processing logic contained in a + * custom class can be reused by the framework. + * + * @author Robert Kasanicky + */ +public class FooService { + + public static final int GENERATION_LIMIT = 10; + + private int counter = 0; + private List generatedFoos = new ArrayList(GENERATION_LIMIT); + private List processedFoos = new ArrayList(GENERATION_LIMIT); + private List processedFooNameValuePairs = new ArrayList(GENERATION_LIMIT); + + public Foo generateFoo() { + if (counter++ >= GENERATION_LIMIT) return null; + + Foo foo = new Foo(counter, "foo" + counter, counter); + generatedFoos.add(foo); + return foo; + + } + + public void processFoo(Foo foo) { + processedFoos.add(foo); + } + + public void processNameValuePair(String name, int value) { + processedFooNameValuePairs.add(new Foo(0, name, value)); + } + + public List getGeneratedFoos() { + return generatedFoos; + } + + public List getProcessedFoos() { + return processedFoos; + } + + public List getProcessedFooNameValuePairs() { + return processedFooNameValuePairs; + } + + +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/sample/domain/Order.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/sample/domain/Order.java index 755a8c20cd..a780233d53 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/sample/domain/Order.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/sample/domain/Order.java @@ -1,83 +1,83 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.batch.io.sample.domain; - -import java.util.Date; -import java.util.List; - -import org.apache.commons.lang.builder.EqualsBuilder; -import org.apache.commons.lang.builder.HashCodeBuilder; -import org.apache.commons.lang.builder.ToStringBuilder; - -/** - * An XML order. - * - * This is a complex type. - */ -public class Order { - private Customer customer; - - private Date date; - - private List lineItems; - - private Shipper shipper; - - public Customer getCustomer() { - return customer; - } - - public void setCustomer(Customer customer) { - this.customer = customer; - } - - public Date getDate() { - return (Date)date.clone(); - } - - public void setDate(Date date) { - this.date = date == null ? null : (Date)date.clone(); - } - - public List getLineItems() { - return lineItems; - } - - public void setLineItems(List lineItems) { - this.lineItems = lineItems; - } - - public Shipper getShipper() { - return shipper; - } - - public void setShipper(Shipper shipper) { - this.shipper = shipper; - } - - public boolean equals(Object obj) { - return EqualsBuilder.reflectionEquals(obj, this); - } - - public int hashCode() { - return HashCodeBuilder.reflectionHashCode(this); - } - - public String toString() { - return ToStringBuilder.reflectionToString(this); - } -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.batch.io.sample.domain; + +import java.util.Date; +import java.util.List; + +import org.apache.commons.lang.builder.EqualsBuilder; +import org.apache.commons.lang.builder.HashCodeBuilder; +import org.apache.commons.lang.builder.ToStringBuilder; + +/** + * An XML order. + * + * This is a complex type. + */ +public class Order { + private Customer customer; + + private Date date; + + private List lineItems; + + private Shipper shipper; + + public Customer getCustomer() { + return customer; + } + + public void setCustomer(Customer customer) { + this.customer = customer; + } + + public Date getDate() { + return (Date)date.clone(); + } + + public void setDate(Date date) { + this.date = date == null ? null : (Date)date.clone(); + } + + public List getLineItems() { + return lineItems; + } + + public void setLineItems(List lineItems) { + this.lineItems = lineItems; + } + + public Shipper getShipper() { + return shipper; + } + + public void setShipper(Shipper shipper) { + this.shipper = shipper; + } + + public boolean equals(Object obj) { + return EqualsBuilder.reflectionEquals(obj, this); + } + + public int hashCode() { + return HashCodeBuilder.reflectionHashCode(this); + } + + public String toString() { + return ToStringBuilder.reflectionToString(this); + } +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/sql/AbstractJdbcItemReaderIntegrationTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/sql/AbstractJdbcItemReaderIntegrationTests.java index b08078d036..44fa561125 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/sql/AbstractJdbcItemReaderIntegrationTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/sql/AbstractJdbcItemReaderIntegrationTests.java @@ -1,173 +1,173 @@ -package org.springframework.batch.io.sql; - -import org.springframework.batch.io.sample.domain.Foo; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.item.ItemReader; -import org.springframework.batch.item.ItemStream; -import org.springframework.beans.factory.DisposableBean; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.test.AbstractTransactionalDataSourceSpringContextTests; -import org.springframework.util.Assert; - -/** - * Common scenarios for testing {@link ItemReader} implementations which read data from database. - * - * @author Lucas Ward - * @author Robert Kasanicky - */ -public abstract class AbstractJdbcItemReaderIntegrationTests extends AbstractTransactionalDataSourceSpringContextTests { - - protected ItemReader itemReader; - - protected ExecutionContext executionContext; - - /** - * @return input source with all necessary dependencies set - */ - protected abstract ItemReader createItemReader() throws Exception; - - protected String[] getConfigLocations(){ - return new String[] { "org/springframework/batch/io/sql/data-source-context.xml"}; - } - - protected void onSetUp()throws Exception{ - super.onSetUp(); - itemReader = createItemReader(); - getAsInitializingBean(itemReader).afterPropertiesSet(); - executionContext = new ExecutionContext(); - } - - protected void onTearDown()throws Exception { - getAsDisposableBean(itemReader).destroy(); - super.onTearDown(); - } - - /** - * Regular scenario - read all rows and eventually return null. - */ - public void testNormalProcessing() throws Exception { - getAsInitializingBean(itemReader).afterPropertiesSet(); - getAsItemStream(itemReader).open(executionContext); - - Foo foo1 = (Foo) itemReader.read(); - assertEquals(1, foo1.getValue()); - - Foo foo2 = (Foo) itemReader.read(); - assertEquals(2, foo2.getValue()); - - Foo foo3 = (Foo) itemReader.read(); - assertEquals(3, foo3.getValue()); - - Foo foo4 = (Foo) itemReader.read(); - assertEquals(4, foo4.getValue()); - - Foo foo5 = (Foo) itemReader.read(); - assertEquals(5, foo5.getValue()); - - assertNull(itemReader.read()); - } - - /** - * Restart scenario. - * @throws Exception - */ - public void testRestart() throws Exception { - getAsItemStream(itemReader).open(executionContext); - Foo foo1 = (Foo) itemReader.read(); - assertEquals(1, foo1.getValue()); - - Foo foo2 = (Foo) itemReader.read(); - assertEquals(2, foo2.getValue()); - - getAsItemStream(itemReader).update(executionContext); - - // create new input source - itemReader = createItemReader(); - getAsItemStream(itemReader).open(executionContext); - - Foo fooAfterRestart = (Foo) itemReader.read(); - assertEquals(3, fooAfterRestart.getValue()); - } - - /** - * Reading from an input source and then trying to restore causes an error. - */ - public void testInvalidRestore() throws Exception { - - getAsItemStream(itemReader).open(executionContext); - Foo foo1 = (Foo) itemReader.read(); - assertEquals(1, foo1.getValue()); - - Foo foo2 = (Foo) itemReader.read(); - assertEquals(2, foo2.getValue()); - - getAsItemStream(itemReader).update(executionContext); - - // create new input source - itemReader = createItemReader(); - - Foo foo = (Foo) itemReader.read(); - assertEquals(1, foo.getValue()); - - try { - getAsItemStream(itemReader).open(executionContext); - fail(); - } - catch (IllegalStateException ex) { - // expected - } - } - - /** - * Empty restart data should be handled gracefully. - * @throws Exception - */ - public void testRestoreFromEmptyData() throws Exception { - ExecutionContext streamContext = new ExecutionContext(); - getAsItemStream(itemReader).open(streamContext); - Foo foo = (Foo) itemReader.read(); - assertEquals(1, foo.getValue()); - } - - /** - * Rollback scenario. - * @throws Exception - */ - public void testRollback() throws Exception { - Foo foo1 = (Foo) itemReader.read(); - - commit(); - - Foo foo2 = (Foo) itemReader.read(); - Assert.state(!foo2.equals(foo1)); - - Foo foo3 = (Foo) itemReader.read(); - Assert.state(!foo2.equals(foo3)); - - rollback(); - - assertEquals(foo2, itemReader.read()); - } - - - private void commit() { - itemReader.mark(); - } - - private void rollback() { - itemReader.reset(); - } - - private ItemStream getAsItemStream(ItemReader source) { - return (ItemStream) source; - } - - private InitializingBean getAsInitializingBean(ItemReader source) { - return (InitializingBean) source; - } - - private DisposableBean getAsDisposableBean(ItemReader source) { - return (DisposableBean) source; - } - -} +package org.springframework.batch.io.sql; + +import org.springframework.batch.io.sample.domain.Foo; +import org.springframework.batch.item.ExecutionContext; +import org.springframework.batch.item.ItemReader; +import org.springframework.batch.item.ItemStream; +import org.springframework.beans.factory.DisposableBean; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.test.AbstractTransactionalDataSourceSpringContextTests; +import org.springframework.util.Assert; + +/** + * Common scenarios for testing {@link ItemReader} implementations which read data from database. + * + * @author Lucas Ward + * @author Robert Kasanicky + */ +public abstract class AbstractJdbcItemReaderIntegrationTests extends AbstractTransactionalDataSourceSpringContextTests { + + protected ItemReader itemReader; + + protected ExecutionContext executionContext; + + /** + * @return input source with all necessary dependencies set + */ + protected abstract ItemReader createItemReader() throws Exception; + + protected String[] getConfigLocations(){ + return new String[] { "org/springframework/batch/io/sql/data-source-context.xml"}; + } + + protected void onSetUp()throws Exception{ + super.onSetUp(); + itemReader = createItemReader(); + getAsInitializingBean(itemReader).afterPropertiesSet(); + executionContext = new ExecutionContext(); + } + + protected void onTearDown()throws Exception { + getAsDisposableBean(itemReader).destroy(); + super.onTearDown(); + } + + /** + * Regular scenario - read all rows and eventually return null. + */ + public void testNormalProcessing() throws Exception { + getAsInitializingBean(itemReader).afterPropertiesSet(); + getAsItemStream(itemReader).open(executionContext); + + Foo foo1 = (Foo) itemReader.read(); + assertEquals(1, foo1.getValue()); + + Foo foo2 = (Foo) itemReader.read(); + assertEquals(2, foo2.getValue()); + + Foo foo3 = (Foo) itemReader.read(); + assertEquals(3, foo3.getValue()); + + Foo foo4 = (Foo) itemReader.read(); + assertEquals(4, foo4.getValue()); + + Foo foo5 = (Foo) itemReader.read(); + assertEquals(5, foo5.getValue()); + + assertNull(itemReader.read()); + } + + /** + * Restart scenario. + * @throws Exception + */ + public void testRestart() throws Exception { + getAsItemStream(itemReader).open(executionContext); + Foo foo1 = (Foo) itemReader.read(); + assertEquals(1, foo1.getValue()); + + Foo foo2 = (Foo) itemReader.read(); + assertEquals(2, foo2.getValue()); + + getAsItemStream(itemReader).update(executionContext); + + // create new input source + itemReader = createItemReader(); + getAsItemStream(itemReader).open(executionContext); + + Foo fooAfterRestart = (Foo) itemReader.read(); + assertEquals(3, fooAfterRestart.getValue()); + } + + /** + * Reading from an input source and then trying to restore causes an error. + */ + public void testInvalidRestore() throws Exception { + + getAsItemStream(itemReader).open(executionContext); + Foo foo1 = (Foo) itemReader.read(); + assertEquals(1, foo1.getValue()); + + Foo foo2 = (Foo) itemReader.read(); + assertEquals(2, foo2.getValue()); + + getAsItemStream(itemReader).update(executionContext); + + // create new input source + itemReader = createItemReader(); + + Foo foo = (Foo) itemReader.read(); + assertEquals(1, foo.getValue()); + + try { + getAsItemStream(itemReader).open(executionContext); + fail(); + } + catch (IllegalStateException ex) { + // expected + } + } + + /** + * Empty restart data should be handled gracefully. + * @throws Exception + */ + public void testRestoreFromEmptyData() throws Exception { + ExecutionContext streamContext = new ExecutionContext(); + getAsItemStream(itemReader).open(streamContext); + Foo foo = (Foo) itemReader.read(); + assertEquals(1, foo.getValue()); + } + + /** + * Rollback scenario. + * @throws Exception + */ + public void testRollback() throws Exception { + Foo foo1 = (Foo) itemReader.read(); + + commit(); + + Foo foo2 = (Foo) itemReader.read(); + Assert.state(!foo2.equals(foo1)); + + Foo foo3 = (Foo) itemReader.read(); + Assert.state(!foo2.equals(foo3)); + + rollback(); + + assertEquals(foo2, itemReader.read()); + } + + + private void commit() { + itemReader.mark(); + } + + private void rollback() { + itemReader.reset(); + } + + private ItemStream getAsItemStream(ItemReader source) { + return (ItemStream) source; + } + + private InitializingBean getAsInitializingBean(ItemReader source) { + return (InitializingBean) source; + } + + private DisposableBean getAsDisposableBean(ItemReader source) { + return (DisposableBean) source; + } + +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/support/AbstractDataSourceItemReaderIntegrationTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/support/AbstractDataSourceItemReaderIntegrationTests.java index 5f5646332f..72d4469f5e 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/support/AbstractDataSourceItemReaderIntegrationTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/support/AbstractDataSourceItemReaderIntegrationTests.java @@ -1,253 +1,253 @@ -package org.springframework.batch.io.support; - -import org.springframework.batch.io.Skippable; -import org.springframework.batch.io.sample.domain.Foo; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.item.ItemReader; -import org.springframework.batch.item.ItemStream; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.test.AbstractTransactionalDataSourceSpringContextTests; -import org.springframework.util.Assert; - -/** - * Common scenarios for testing {@link ItemReader} implementations which read - * data from database. - * - * @author Lucas Ward - * @author Robert Kasanicky - */ -public abstract class AbstractDataSourceItemReaderIntegrationTests extends - AbstractTransactionalDataSourceSpringContextTests { - - protected ItemReader reader; - protected ExecutionContext executionContext; - - /** - * @return configured input source ready for use - */ - protected abstract ItemReader createItemReader() throws Exception; - - protected String[] getConfigLocations() { - return new String[] { "org/springframework/batch/io/sql/data-source-context.xml" }; - } - - /* - * (non-Javadoc) - * @see org.springframework.test.AbstractTransactionalSpringContextTests#onSetUpInTransaction() - */ - protected void onSetUpInTransaction() throws Exception { - super.onSetUpInTransaction(); - reader = createItemReader(); - executionContext = new ExecutionContext(); - } - - /* - * (non-Javadoc) - * @see org.springframework.test.AbstractTransactionalSpringContextTests#onTearDownAfterTransaction() - */ - protected void onTearDownAfterTransaction() throws Exception { - getAsItemStream(reader).close(null); - super.onTearDownAfterTransaction(); - } - - /** - * Regular scenario - read all rows and eventually return null. - */ - public void testNormalProcessing() throws Exception { - getAsInitializingBean(reader).afterPropertiesSet(); - - Foo foo1 = (Foo) reader.read(); - assertEquals(1, foo1.getValue()); - - Foo foo2 = (Foo) reader.read(); - assertEquals(2, foo2.getValue()); - - Foo foo3 = (Foo) reader.read(); - assertEquals(3, foo3.getValue()); - - Foo foo4 = (Foo) reader.read(); - assertEquals(4, foo4.getValue()); - - Foo foo5 = (Foo) reader.read(); - assertEquals(5, foo5.getValue()); - - assertNull(reader.read()); - } - - /** - * Restart scenario - read records, save restart data, create new input - * source and restore from restart data - the new input source should - * continue where the old one finished. - */ - public void testRestart() throws Exception { - - getAsItemStream(reader).open(executionContext); - - Foo foo1 = (Foo) reader.read(); - assertEquals(1, foo1.getValue()); - - Foo foo2 = (Foo) reader.read(); - assertEquals(2, foo2.getValue()); - - getAsItemStream(reader).update(executionContext); - - // create new input source - reader = createItemReader(); - - getAsItemStream(reader).open(executionContext); - - Foo fooAfterRestart = (Foo) reader.read(); - assertEquals(3, fooAfterRestart.getValue()); - } - - /** - * Reading from an input source and then trying to restore causes an error. - */ - public void testInvalidRestore() throws Exception { - - getAsItemStream(reader).open(executionContext); - - Foo foo1 = (Foo) reader.read(); - assertEquals(1, foo1.getValue()); - - Foo foo2 = (Foo) reader.read(); - assertEquals(2, foo2.getValue()); - - getAsItemStream(reader).update(executionContext); - - // create new input source - reader = createItemReader(); - - Foo foo = (Foo) reader.read(); - assertEquals(1, foo.getValue()); - - try { - getAsItemStream(reader).open(executionContext); - fail(); - } - catch (IllegalStateException ex) { - // expected - } - } - - /** - * Empty restart data should be handled gracefully. - * @throws Exception - */ - public void testRestoreFromEmptyData() throws Exception { - getAsItemStream(reader).update(executionContext); - - Foo foo = (Foo) reader.read(); - assertEquals(1, foo.getValue()); - } - - /** - * Rollback scenario - input source rollbacks to last commit point. - * @throws Exception - */ - public void testRollback() throws Exception { - Foo foo1 = (Foo) reader.read(); - - commit(); - - Foo foo2 = (Foo) reader.read(); - Assert.state(!foo2.equals(foo1)); - - Foo foo3 = (Foo) reader.read(); - Assert.state(!foo2.equals(foo3)); - - rollback(); - - assertEquals(foo2, reader.read()); - } - - /** - * Rollback scenario with skip - input source rollbacks to last commit - * point. - * @throws Exception - */ - public void testRollbackAndSkip() throws Exception { - - if (!(reader instanceof Skippable)) { - return; - } - - Foo foo1 = (Foo) reader.read(); - - commit(); - - Foo foo2 = (Foo) reader.read(); - Assert.state(!foo2.equals(foo1)); - - Foo foo3 = (Foo) reader.read(); - Assert.state(!foo2.equals(foo3)); - - getAsSkippable(reader).skip(); - - rollback(); - - assertEquals(foo2, reader.read()); - Foo foo4 = (Foo) reader.read(); - assertEquals(4, foo4.getValue()); - } - - /** - * Rollback scenario with skip and restart - input source rollbacks to last - * commit point. - * @throws Exception - */ - public void testRollbackSkipAndRestart() throws Exception { - - if (!(reader instanceof Skippable)) { - return; - } - - getAsItemStream(reader).open(executionContext); - - Foo foo1 = (Foo) reader.read(); - - commit(); - - Foo foo2 = (Foo) reader.read(); - Assert.state(!foo2.equals(foo1)); - - Foo foo3 = (Foo) reader.read(); - Assert.state(!foo2.equals(foo3)); - - getAsSkippable(reader).skip(); - - rollback(); - - getAsItemStream(reader).update(executionContext); - - // create new input source - reader = createItemReader(); - - getAsItemStream(reader).open(executionContext); - - assertEquals(foo2, reader.read()); - Foo foo4 = (Foo) reader.read(); - assertEquals(4, foo4.getValue()); - } - - private void commit() { - reader.mark(); - } - - private void rollback() { - reader.reset(); - } - - private Skippable getAsSkippable(ItemReader source) { - return (Skippable) source; - } - - private ItemStream getAsItemStream(ItemReader source) { - return (ItemStream) source; - } - - private InitializingBean getAsInitializingBean(ItemReader source) { - return (InitializingBean) source; - } - -} +package org.springframework.batch.io.support; + +import org.springframework.batch.io.Skippable; +import org.springframework.batch.io.sample.domain.Foo; +import org.springframework.batch.item.ExecutionContext; +import org.springframework.batch.item.ItemReader; +import org.springframework.batch.item.ItemStream; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.test.AbstractTransactionalDataSourceSpringContextTests; +import org.springframework.util.Assert; + +/** + * Common scenarios for testing {@link ItemReader} implementations which read + * data from database. + * + * @author Lucas Ward + * @author Robert Kasanicky + */ +public abstract class AbstractDataSourceItemReaderIntegrationTests extends + AbstractTransactionalDataSourceSpringContextTests { + + protected ItemReader reader; + protected ExecutionContext executionContext; + + /** + * @return configured input source ready for use + */ + protected abstract ItemReader createItemReader() throws Exception; + + protected String[] getConfigLocations() { + return new String[] { "org/springframework/batch/io/sql/data-source-context.xml" }; + } + + /* + * (non-Javadoc) + * @see org.springframework.test.AbstractTransactionalSpringContextTests#onSetUpInTransaction() + */ + protected void onSetUpInTransaction() throws Exception { + super.onSetUpInTransaction(); + reader = createItemReader(); + executionContext = new ExecutionContext(); + } + + /* + * (non-Javadoc) + * @see org.springframework.test.AbstractTransactionalSpringContextTests#onTearDownAfterTransaction() + */ + protected void onTearDownAfterTransaction() throws Exception { + getAsItemStream(reader).close(null); + super.onTearDownAfterTransaction(); + } + + /** + * Regular scenario - read all rows and eventually return null. + */ + public void testNormalProcessing() throws Exception { + getAsInitializingBean(reader).afterPropertiesSet(); + + Foo foo1 = (Foo) reader.read(); + assertEquals(1, foo1.getValue()); + + Foo foo2 = (Foo) reader.read(); + assertEquals(2, foo2.getValue()); + + Foo foo3 = (Foo) reader.read(); + assertEquals(3, foo3.getValue()); + + Foo foo4 = (Foo) reader.read(); + assertEquals(4, foo4.getValue()); + + Foo foo5 = (Foo) reader.read(); + assertEquals(5, foo5.getValue()); + + assertNull(reader.read()); + } + + /** + * Restart scenario - read records, save restart data, create new input + * source and restore from restart data - the new input source should + * continue where the old one finished. + */ + public void testRestart() throws Exception { + + getAsItemStream(reader).open(executionContext); + + Foo foo1 = (Foo) reader.read(); + assertEquals(1, foo1.getValue()); + + Foo foo2 = (Foo) reader.read(); + assertEquals(2, foo2.getValue()); + + getAsItemStream(reader).update(executionContext); + + // create new input source + reader = createItemReader(); + + getAsItemStream(reader).open(executionContext); + + Foo fooAfterRestart = (Foo) reader.read(); + assertEquals(3, fooAfterRestart.getValue()); + } + + /** + * Reading from an input source and then trying to restore causes an error. + */ + public void testInvalidRestore() throws Exception { + + getAsItemStream(reader).open(executionContext); + + Foo foo1 = (Foo) reader.read(); + assertEquals(1, foo1.getValue()); + + Foo foo2 = (Foo) reader.read(); + assertEquals(2, foo2.getValue()); + + getAsItemStream(reader).update(executionContext); + + // create new input source + reader = createItemReader(); + + Foo foo = (Foo) reader.read(); + assertEquals(1, foo.getValue()); + + try { + getAsItemStream(reader).open(executionContext); + fail(); + } + catch (IllegalStateException ex) { + // expected + } + } + + /** + * Empty restart data should be handled gracefully. + * @throws Exception + */ + public void testRestoreFromEmptyData() throws Exception { + getAsItemStream(reader).update(executionContext); + + Foo foo = (Foo) reader.read(); + assertEquals(1, foo.getValue()); + } + + /** + * Rollback scenario - input source rollbacks to last commit point. + * @throws Exception + */ + public void testRollback() throws Exception { + Foo foo1 = (Foo) reader.read(); + + commit(); + + Foo foo2 = (Foo) reader.read(); + Assert.state(!foo2.equals(foo1)); + + Foo foo3 = (Foo) reader.read(); + Assert.state(!foo2.equals(foo3)); + + rollback(); + + assertEquals(foo2, reader.read()); + } + + /** + * Rollback scenario with skip - input source rollbacks to last commit + * point. + * @throws Exception + */ + public void testRollbackAndSkip() throws Exception { + + if (!(reader instanceof Skippable)) { + return; + } + + Foo foo1 = (Foo) reader.read(); + + commit(); + + Foo foo2 = (Foo) reader.read(); + Assert.state(!foo2.equals(foo1)); + + Foo foo3 = (Foo) reader.read(); + Assert.state(!foo2.equals(foo3)); + + getAsSkippable(reader).skip(); + + rollback(); + + assertEquals(foo2, reader.read()); + Foo foo4 = (Foo) reader.read(); + assertEquals(4, foo4.getValue()); + } + + /** + * Rollback scenario with skip and restart - input source rollbacks to last + * commit point. + * @throws Exception + */ + public void testRollbackSkipAndRestart() throws Exception { + + if (!(reader instanceof Skippable)) { + return; + } + + getAsItemStream(reader).open(executionContext); + + Foo foo1 = (Foo) reader.read(); + + commit(); + + Foo foo2 = (Foo) reader.read(); + Assert.state(!foo2.equals(foo1)); + + Foo foo3 = (Foo) reader.read(); + Assert.state(!foo2.equals(foo3)); + + getAsSkippable(reader).skip(); + + rollback(); + + getAsItemStream(reader).update(executionContext); + + // create new input source + reader = createItemReader(); + + getAsItemStream(reader).open(executionContext); + + assertEquals(foo2, reader.read()); + Foo foo4 = (Foo) reader.read(); + assertEquals(4, foo4.getValue()); + } + + private void commit() { + reader.mark(); + } + + private void rollback() { + reader.reset(); + } + + private Skippable getAsSkippable(ItemReader source) { + return (Skippable) source; + } + + private ItemStream getAsItemStream(ItemReader source) { + return (ItemStream) source; + } + + private InitializingBean getAsInitializingBean(ItemReader source) { + return (InitializingBean) source; + } + +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/support/FileUtilsTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/support/FileUtilsTests.java index 7421b63639..b97299de42 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/support/FileUtilsTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/support/FileUtilsTests.java @@ -1,132 +1,132 @@ -package org.springframework.batch.io.support; - -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; - -import org.springframework.dao.DataAccessResourceFailureException; -import org.springframework.util.Assert; - -import junit.framework.TestCase; - -/** - * Tests for {@link FileUtils} - * - * @author Robert Kasanicky - */ -public class FileUtilsTests extends TestCase { - - private File file = new File("FileUtilsTests.tmp"); - - /** - * No restart + file should not be overwritten => file is created if it does - * not exist, exception is thrown if it already exists - */ - public void testNoRestart() throws Exception { - FileUtils.setUpOutputFile(file, false, false); - assertTrue(file.exists()); - - try { - FileUtils.setUpOutputFile(file, false, false); - fail(); - } - catch (Exception e) { - // expected - } - - file.delete(); - Assert.state(!file.exists()); - - FileUtils.setUpOutputFile(file, false, true); - assertTrue(file.exists()); - - BufferedWriter writer = new BufferedWriter(new FileWriter(file)); - writer.write("testString"); - writer.close(); - long size = file.length(); - Assert.state(size > 0); - - FileUtils.setUpOutputFile(file, false, true); - long newSize = file.length(); - - assertTrue(size != newSize); - assertEquals(0, newSize); - } - - /** - * In case of restart, the file is supposed to exist and exception is thrown - * if it does not. - */ - public void testRestart() throws Exception { - try { - FileUtils.setUpOutputFile(file, true, false); - fail(); - } - catch (DataAccessResourceFailureException e) { - // expected - } - - try { - FileUtils.setUpOutputFile(file, true, true); - fail(); - } - catch (DataAccessResourceFailureException e) { - // expected - } - - file.createNewFile(); - assertTrue(file.exists()); - - // with existing file there should be no trouble - FileUtils.setUpOutputFile(file, true, false); - FileUtils.setUpOutputFile(file, true, true); - } - - /** - * If the directories on the file path do not exist, they should be created - */ - public void testCreateDirectoryStructure() { - File file = new File("testDirectory/testDirectory2/testFile.tmp"); - File dir1 = new File("testDirectory"); - File dir2 = new File("testDirectory/testDirectory2"); - - try { - FileUtils.setUpOutputFile(file, false, false); - assertTrue(file.exists()); - assertTrue(dir1.exists()); - assertTrue(dir2.exists()); - } - finally { - file.delete(); - dir2.delete(); - dir1.delete(); - } - } - - public void testBadFile(){ - - File file = new File("new file"){ - public boolean createNewFile() throws IOException { - throw new IOException(); - } - }; - try{ - FileUtils.setUpOutputFile(file, false, false); - fail(); - }catch(DataAccessResourceFailureException ex){ - assertTrue(ex.getCause() instanceof IOException); - }finally{ - file.delete(); - } - } - - protected void setUp() throws Exception { - Assert.state(!file.exists()); - } - - protected void tearDown() throws Exception { - file.delete(); - } - -} +package org.springframework.batch.io.support; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; + +import org.springframework.dao.DataAccessResourceFailureException; +import org.springframework.util.Assert; + +import junit.framework.TestCase; + +/** + * Tests for {@link FileUtils} + * + * @author Robert Kasanicky + */ +public class FileUtilsTests extends TestCase { + + private File file = new File("FileUtilsTests.tmp"); + + /** + * No restart + file should not be overwritten => file is created if it does + * not exist, exception is thrown if it already exists + */ + public void testNoRestart() throws Exception { + FileUtils.setUpOutputFile(file, false, false); + assertTrue(file.exists()); + + try { + FileUtils.setUpOutputFile(file, false, false); + fail(); + } + catch (Exception e) { + // expected + } + + file.delete(); + Assert.state(!file.exists()); + + FileUtils.setUpOutputFile(file, false, true); + assertTrue(file.exists()); + + BufferedWriter writer = new BufferedWriter(new FileWriter(file)); + writer.write("testString"); + writer.close(); + long size = file.length(); + Assert.state(size > 0); + + FileUtils.setUpOutputFile(file, false, true); + long newSize = file.length(); + + assertTrue(size != newSize); + assertEquals(0, newSize); + } + + /** + * In case of restart, the file is supposed to exist and exception is thrown + * if it does not. + */ + public void testRestart() throws Exception { + try { + FileUtils.setUpOutputFile(file, true, false); + fail(); + } + catch (DataAccessResourceFailureException e) { + // expected + } + + try { + FileUtils.setUpOutputFile(file, true, true); + fail(); + } + catch (DataAccessResourceFailureException e) { + // expected + } + + file.createNewFile(); + assertTrue(file.exists()); + + // with existing file there should be no trouble + FileUtils.setUpOutputFile(file, true, false); + FileUtils.setUpOutputFile(file, true, true); + } + + /** + * If the directories on the file path do not exist, they should be created + */ + public void testCreateDirectoryStructure() { + File file = new File("testDirectory/testDirectory2/testFile.tmp"); + File dir1 = new File("testDirectory"); + File dir2 = new File("testDirectory/testDirectory2"); + + try { + FileUtils.setUpOutputFile(file, false, false); + assertTrue(file.exists()); + assertTrue(dir1.exists()); + assertTrue(dir2.exists()); + } + finally { + file.delete(); + dir2.delete(); + dir1.delete(); + } + } + + public void testBadFile(){ + + File file = new File("new file"){ + public boolean createNewFile() throws IOException { + throw new IOException(); + } + }; + try{ + FileUtils.setUpOutputFile(file, false, false); + fail(); + }catch(DataAccessResourceFailureException ex){ + assertTrue(ex.getCause() instanceof IOException); + }finally{ + file.delete(); + } + } + + protected void setUp() throws Exception { + Assert.state(!file.exists()); + } + + protected void tearDown() throws Exception { + file.delete(); + } + +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/support/HibernateAwareItemWriterTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/support/HibernateAwareItemWriterTests.java index 73c3a1d919..95cff533ba 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/support/HibernateAwareItemWriterTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/support/HibernateAwareItemWriterTests.java @@ -1,206 +1,206 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.io.support; - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -import junit.framework.TestCase; - -import org.springframework.batch.item.ItemWriter; -import org.springframework.batch.item.exception.ClearFailedException; -import org.springframework.batch.item.exception.FlushFailedException; -import org.springframework.batch.repeat.context.RepeatContextSupport; -import org.springframework.batch.repeat.synch.RepeatSynchronizationManager; -import org.springframework.dao.DataAccessException; -import org.springframework.orm.hibernate3.HibernateTemplate; -import org.springframework.transaction.support.TransactionSynchronizationManager; - -/** - * @author Dave Syer - * - */ -public class HibernateAwareItemWriterTests extends TestCase { - - private class HibernateTemplateWrapper extends HibernateTemplate { - public void flush() throws DataAccessException { - list.add("flush"); - } - public void clear() { - list.add("clear"); - }; - } - - private class StubItemWriter implements ItemWriter { - public void write(Object item) { - list.add(item); - } - - public void clear() throws ClearFailedException { - list.add("delegateClear"); - } - - public void flush() throws FlushFailedException { - list.add("delegateFlush"); - } - } - - HibernateAwareItemWriter writer = new HibernateAwareItemWriter(); - - final List list = new ArrayList(); - - private RepeatContextSupport context; - - /* - * (non-Javadoc) - * - * @see junit.framework.TestCase#setUp() - */ - protected void setUp() throws Exception { - writer.setDelegate(new StubItemWriter()); - context = new RepeatContextSupport(null); - RepeatSynchronizationManager.register(context); - writer.setHibernateTemplate(new HibernateTemplateWrapper()); - list.clear(); - } - - /* (non-Javadoc) - * @see junit.framework.TestCase#tearDown() - */ - protected void tearDown() throws Exception { - Map map = TransactionSynchronizationManager.getResourceMap(); - for (Iterator iterator = map.keySet().iterator(); iterator.hasNext();) { - String key = (String) iterator.next(); - TransactionSynchronizationManager.unbindResource(key); - } - RepeatSynchronizationManager.clear(); - } - - /** - * Test method for - * {@link org.springframework.batch.io.support.HibernateAwareItemWriter#initDao()}. - * - * @throws Exception - */ - public void testAfterPropertiesSet() throws Exception { - writer = new HibernateAwareItemWriter(); - try { - writer.afterPropertiesSet(); - fail("Expected IllegalArgumentException"); - } catch (IllegalArgumentException e) { - // expected - assertTrue("Wrong message for exception: " + e.getMessage(), e - .getMessage().indexOf("delegate") >= 0); - } - } - - /** - * Test method for - * {@link org.springframework.batch.io.support.HibernateAwareItemWriter#initDao()}. - * - * @throws Exception - */ - public void testAfterPropertiesSetWithDelegate() throws Exception { - writer.afterPropertiesSet(); - } - - /** - * Test method for - * {@link org.springframework.batch.io.support.HibernateAwareItemWriter#write(java.lang.Object)}. - * @throws Exception - */ - public void testWrite() throws Exception { - writer.write("foo"); - assertEquals(1, list.size()); - assertTrue(list.contains("foo")); - } - - /** - * Test method for - * {@link org.springframework.batch.io.support.HibernateAwareItemWriter#write(java.lang.Object)}. - */ - public void testFlushWithFailure() throws Exception{ - final RuntimeException ex = new RuntimeException("bar"); - writer.setHibernateTemplate(new HibernateTemplate() { - public void flush() throws DataAccessException { - throw ex; - } - }); - try { - writer.flush(); - fail("Expected RuntimeException"); - } catch (RuntimeException e) { - assertEquals("bar", e.getMessage()); - } - } - - /** - * Test method for - * {@link org.springframework.batch.io.support.HibernateAwareItemWriter#write(java.lang.Object)}. - * @throws Exception - */ - public void testWriteAndFlushWithFailure() throws Exception { - final RuntimeException ex = new RuntimeException("bar"); - writer.setHibernateTemplate(new HibernateTemplateWrapper() { - public void flush() throws DataAccessException { - throw ex; - } - }); - writer.write("foo"); - try { - writer.flush(); - fail("Expected RuntimeException"); - } catch (RuntimeException e) { - assertEquals("bar", e.getMessage()); - } - assertEquals(1, list.size()); - writer.setHibernateTemplate(new HibernateTemplateWrapper() { - public void flush() throws DataAccessException { - list.add("flush"); - } - }); - writer.write("foo"); - assertEquals(4, list.size()); - assertTrue(list.contains("flush")); - assertTrue(list.contains("clear")); - assertTrue(context.isCompleteOnly()); - } - - /** - * Test method for - * {@link org.springframework.batch.io.support.HibernateAwareItemWriter#close(org.springframework.batch.repeat.RepeatContext)}. - */ - public void testFlush() throws Exception{ - writer.flush(); - assertEquals(3, list.size()); - assertTrue(list.contains("flush")); - assertTrue(list.contains("clear")); - assertTrue(list.contains("delegateFlush")); - } - - /** - * Test method for - * {@link org.springframework.batch.io.support.HibernateAwareItemWriter#close(org.springframework.batch.repeat.RepeatContext)}. - */ - public void testClear() throws Exception{ - writer.clear(); - assertEquals(2, list.size()); - assertTrue(list.contains("clear")); - assertTrue(list.contains("delegateClear")); - } -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.io.support; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import junit.framework.TestCase; + +import org.springframework.batch.item.ItemWriter; +import org.springframework.batch.item.exception.ClearFailedException; +import org.springframework.batch.item.exception.FlushFailedException; +import org.springframework.batch.repeat.context.RepeatContextSupport; +import org.springframework.batch.repeat.synch.RepeatSynchronizationManager; +import org.springframework.dao.DataAccessException; +import org.springframework.orm.hibernate3.HibernateTemplate; +import org.springframework.transaction.support.TransactionSynchronizationManager; + +/** + * @author Dave Syer + * + */ +public class HibernateAwareItemWriterTests extends TestCase { + + private class HibernateTemplateWrapper extends HibernateTemplate { + public void flush() throws DataAccessException { + list.add("flush"); + } + public void clear() { + list.add("clear"); + }; + } + + private class StubItemWriter implements ItemWriter { + public void write(Object item) { + list.add(item); + } + + public void clear() throws ClearFailedException { + list.add("delegateClear"); + } + + public void flush() throws FlushFailedException { + list.add("delegateFlush"); + } + } + + HibernateAwareItemWriter writer = new HibernateAwareItemWriter(); + + final List list = new ArrayList(); + + private RepeatContextSupport context; + + /* + * (non-Javadoc) + * + * @see junit.framework.TestCase#setUp() + */ + protected void setUp() throws Exception { + writer.setDelegate(new StubItemWriter()); + context = new RepeatContextSupport(null); + RepeatSynchronizationManager.register(context); + writer.setHibernateTemplate(new HibernateTemplateWrapper()); + list.clear(); + } + + /* (non-Javadoc) + * @see junit.framework.TestCase#tearDown() + */ + protected void tearDown() throws Exception { + Map map = TransactionSynchronizationManager.getResourceMap(); + for (Iterator iterator = map.keySet().iterator(); iterator.hasNext();) { + String key = (String) iterator.next(); + TransactionSynchronizationManager.unbindResource(key); + } + RepeatSynchronizationManager.clear(); + } + + /** + * Test method for + * {@link org.springframework.batch.io.support.HibernateAwareItemWriter#initDao()}. + * + * @throws Exception + */ + public void testAfterPropertiesSet() throws Exception { + writer = new HibernateAwareItemWriter(); + try { + writer.afterPropertiesSet(); + fail("Expected IllegalArgumentException"); + } catch (IllegalArgumentException e) { + // expected + assertTrue("Wrong message for exception: " + e.getMessage(), e + .getMessage().indexOf("delegate") >= 0); + } + } + + /** + * Test method for + * {@link org.springframework.batch.io.support.HibernateAwareItemWriter#initDao()}. + * + * @throws Exception + */ + public void testAfterPropertiesSetWithDelegate() throws Exception { + writer.afterPropertiesSet(); + } + + /** + * Test method for + * {@link org.springframework.batch.io.support.HibernateAwareItemWriter#write(java.lang.Object)}. + * @throws Exception + */ + public void testWrite() throws Exception { + writer.write("foo"); + assertEquals(1, list.size()); + assertTrue(list.contains("foo")); + } + + /** + * Test method for + * {@link org.springframework.batch.io.support.HibernateAwareItemWriter#write(java.lang.Object)}. + */ + public void testFlushWithFailure() throws Exception{ + final RuntimeException ex = new RuntimeException("bar"); + writer.setHibernateTemplate(new HibernateTemplate() { + public void flush() throws DataAccessException { + throw ex; + } + }); + try { + writer.flush(); + fail("Expected RuntimeException"); + } catch (RuntimeException e) { + assertEquals("bar", e.getMessage()); + } + } + + /** + * Test method for + * {@link org.springframework.batch.io.support.HibernateAwareItemWriter#write(java.lang.Object)}. + * @throws Exception + */ + public void testWriteAndFlushWithFailure() throws Exception { + final RuntimeException ex = new RuntimeException("bar"); + writer.setHibernateTemplate(new HibernateTemplateWrapper() { + public void flush() throws DataAccessException { + throw ex; + } + }); + writer.write("foo"); + try { + writer.flush(); + fail("Expected RuntimeException"); + } catch (RuntimeException e) { + assertEquals("bar", e.getMessage()); + } + assertEquals(1, list.size()); + writer.setHibernateTemplate(new HibernateTemplateWrapper() { + public void flush() throws DataAccessException { + list.add("flush"); + } + }); + writer.write("foo"); + assertEquals(4, list.size()); + assertTrue(list.contains("flush")); + assertTrue(list.contains("clear")); + assertTrue(context.isCompleteOnly()); + } + + /** + * Test method for + * {@link org.springframework.batch.io.support.HibernateAwareItemWriter#close(org.springframework.batch.repeat.RepeatContext)}. + */ + public void testFlush() throws Exception{ + writer.flush(); + assertEquals(3, list.size()); + assertTrue(list.contains("flush")); + assertTrue(list.contains("clear")); + assertTrue(list.contains("delegateFlush")); + } + + /** + * Test method for + * {@link org.springframework.batch.io.support.HibernateAwareItemWriter#close(org.springframework.batch.repeat.RepeatContext)}. + */ + public void testClear() throws Exception{ + writer.clear(); + assertEquals(2, list.size()); + assertTrue(list.contains("clear")); + assertTrue(list.contains("delegateClear")); + } +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/xml/EventHelper.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/xml/EventHelper.java index ae6f664710..081d5c5245 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/xml/EventHelper.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/xml/EventHelper.java @@ -1,30 +1,30 @@ -package org.springframework.batch.io.xml; - -import javax.xml.stream.events.EndElement; -import javax.xml.stream.events.StartElement; -import javax.xml.stream.events.XMLEvent; - -/** - * Helper methods for working with XML Events. - * - * @author Robert Kasanicky - */ -public class EventHelper { - - //utility class - private EventHelper() {} - - /** - * @return element name assuming the event is instance of StartElement - */ - public static String startElementName(XMLEvent event) { - return ((StartElement) event).getName().getLocalPart(); - } - - /** - * @return element name assuming the event is instance of EndElement - */ - public static String endElementName(XMLEvent event) { - return ((EndElement) event).getName().getLocalPart(); - } -} +package org.springframework.batch.io.xml; + +import javax.xml.stream.events.EndElement; +import javax.xml.stream.events.StartElement; +import javax.xml.stream.events.XMLEvent; + +/** + * Helper methods for working with XML Events. + * + * @author Robert Kasanicky + */ +public class EventHelper { + + //utility class + private EventHelper() {} + + /** + * @return element name assuming the event is instance of StartElement + */ + public static String startElementName(XMLEvent event) { + return ((StartElement) event).getName().getLocalPart(); + } + + /** + * @return element name assuming the event is instance of EndElement + */ + public static String endElementName(XMLEvent event) { + return ((EndElement) event).getName().getLocalPart(); + } +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/xml/StaxEventItemReaderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/xml/StaxEventItemReaderTests.java index 1a0e5bdb45..09a57e7d9a 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/xml/StaxEventItemReaderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/xml/StaxEventItemReaderTests.java @@ -1,424 +1,424 @@ -package org.springframework.batch.io.xml; - -import java.io.IOException; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.List; - -import javax.xml.stream.FactoryConfigurationError; -import javax.xml.stream.XMLEventReader; -import javax.xml.stream.XMLInputFactory; -import javax.xml.stream.XMLStreamException; -import javax.xml.stream.events.EndElement; -import javax.xml.stream.events.XMLEvent; - -import junit.framework.TestCase; - -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.item.exception.StreamException; -import org.springframework.core.io.AbstractResource; -import org.springframework.core.io.ByteArrayResource; -import org.springframework.core.io.Resource; -import org.springframework.dao.DataAccessResourceFailureException; - -/** - * Tests for {@link StaxEventItemReader}. - * - * @author Robert Kasanicky - */ -public class StaxEventItemReaderTests extends TestCase { - - // object under test - private StaxEventItemReader source; - - // test xml input - private String xml = " testString "; - - private EventReaderDeserializer deserializer = new MockFragmentDeserializer(); - - private static final String FRAGMENT_ROOT_ELEMENT = "fragment"; - - private ExecutionContext executionContext; - - protected void setUp() throws Exception { - this.executionContext = new ExecutionContext(); - source = createNewInputSouce(); - } - - public void testAfterPropertiesSet() throws Exception { - source.afterPropertiesSet(); - } - - public void testAfterPropertesSetException() throws Exception { - source.setResource(null); - try { - source.afterPropertiesSet(); - fail(); - } - catch (IllegalArgumentException e) { - // expected; - } - - source = createNewInputSouce(); - source.setFragmentRootElementName(""); - try { - source.afterPropertiesSet(); - fail(); - } - catch (IllegalArgumentException e) { - // expected - } - - source = createNewInputSouce(); - source.setFragmentDeserializer(null); - try { - source.afterPropertiesSet(); - fail(); - } - catch (IllegalArgumentException e) { - // expected - } - } - - /** - * Regular usage scenario. ItemReader should pass XML fragments to - * deserializer wrapped with StartDocument and EndDocument events. - */ - public void testFragmentWrapping() throws Exception { - source.afterPropertiesSet(); - source.open(executionContext); - // see asserts in the mock deserializer - assertNotNull(source.read()); - assertNotNull(source.read()); - assertNull(source.read()); // there are only two fragments - - source.close(executionContext); - } - - /** - * Cursor is moved before beginning of next fragment. - */ - public void testMoveCursorToNextFragment() throws XMLStreamException, FactoryConfigurationError, IOException { - Resource resource = new ByteArrayResource(xml.getBytes()); - XMLEventReader reader = XMLInputFactory.newInstance().createXMLEventReader(resource.getInputStream()); - - final int EXPECTED_NUMBER_OF_FRAGMENTS = 2; - for (int i = 0; i < EXPECTED_NUMBER_OF_FRAGMENTS; i++) { - assertTrue(source.moveCursorToNextFragment(reader)); - assertTrue(EventHelper.startElementName(reader.peek()).equals("fragment")); - reader.nextEvent(); // move away from beginning of fragment - } - assertFalse(source.moveCursorToNextFragment(reader)); - } - - /** - * Save restart data and restore from it. - */ - public void testRestart() { - source.open(executionContext); - source.read(); - source.update(executionContext); - System.out.println(executionContext); - assertEquals(1, executionContext.getLong(StaxEventItemReader.class.getSimpleName() + ".read.count")); - List expectedAfterRestart = (List) source.read(); - - source = createNewInputSouce(); - source.open(executionContext); - List afterRestart = (List) source.read(); - assertEquals(expectedAfterRestart.size(), afterRestart.size()); - } - - /** - * Restore point must not exceed end of file, input source must not be - * already initialised when restoring. - */ - public void testInvalidRestore() { - ExecutionContext context = new ExecutionContext(); - context.putLong(StaxEventItemReader.class.getSimpleName() + ".read.count", 100000); - try { - source.open(context); - fail("Expected StreamException"); - } - catch (StreamException e) { - // expected - String message = e.getMessage(); - assertTrue("Wrong message: "+message, message.contains("must be before")); - } - } - - public void testRestoreWorksFromClosedStream() throws Exception { - source.close(executionContext); - source.update(executionContext); - } - /** - * Skipping marked records after rollback. - */ - public void testSkip() { - source.open(executionContext); - List first = (List) source.read(); - source.skip(); - List second = (List) source.read(); - assertFalse(first.equals(second)); - source.reset(); - - assertEquals(second, source.read()); - } - - /** - * Rollback to last commited record. - */ - public void testRollback() { - source.open(executionContext); - // rollback between deserializing records - List first = (List) source.read(); - source.mark(); - List second = (List) source.read(); - assertFalse(first.equals(second)); - source.reset(); - - assertEquals(second, source.read()); - - // rollback while deserializing record - source.reset(); - source.setFragmentDeserializer(new ExceptionFragmentDeserializer()); - try { - source.read(); - } - catch (Exception expected) { - source.reset(); - } - source.setFragmentDeserializer(deserializer); - - assertEquals(second, source.read()); - } - - /** - * Statistics return the current record count. Calling read after end of - * input does not increase the counter. - */ - public void testExecutionContext() { - final int NUMBER_OF_RECORDS = 2; - source.open(executionContext); - source.update(executionContext); - - for (int i = 0; i < NUMBER_OF_RECORDS; i++) { - long recordCount = extractRecordCount(); - assertEquals(i, recordCount); - source.read(); - source.update(executionContext); - } - - assertEquals(NUMBER_OF_RECORDS, extractRecordCount()); - source.read(); - assertEquals(NUMBER_OF_RECORDS, extractRecordCount()); - } - - private long extractRecordCount() { - return executionContext.getLong(StaxEventItemReader.class.getSimpleName() + ".read.count"); - } - - public void testCloseWithoutOpen() throws Exception { - source.close(null); - // No error! - } - - public void testClose() throws Exception { - MockStaxEventItemReader newSource = new MockStaxEventItemReader(); - Resource resource = new ByteArrayResource(xml.getBytes()); - newSource.setResource(resource); - - newSource.setFragmentRootElementName(FRAGMENT_ROOT_ELEMENT); - newSource.setFragmentDeserializer(deserializer); - - newSource.open(executionContext); - - Object item = newSource.read(); - assertNotNull(item); - assertTrue(newSource.isOpenCalled()); - - newSource.close(null); - newSource.setOpenCalled(false); - // calling read again should require re-initialization because of close - try { - item = newSource.read(); - fail("Expected StreamException"); - } - catch (StreamException e) { - // expected - } - } - - public void testOpenBadIOInput() { - - source.setResource(new AbstractResource() { - public String getDescription() { - return null; - } - - public InputStream getInputStream() throws IOException { - throw new IOException(); - } - - public boolean exists() { - return true; - } - }); - - try { - source.open(executionContext); - } - catch (DataAccessResourceFailureException ex) { - assertTrue(ex.getCause() instanceof IOException); - } - - } - - public void testNonExistentResource() throws Exception { - - source.setResource(new NonExistentResource()); - source.afterPropertiesSet(); - - try { - source.open(executionContext); - fail(); - } - catch (IllegalStateException ex) { - // expected - } - } - - public void testRuntimeFileCreation() throws Exception { - - source.setResource(new NonExistentResource()); - source.afterPropertiesSet(); - - source.setResource(new ByteArrayResource(xml.getBytes())); - source.open(executionContext); - source.read(); - } - - private StaxEventItemReader createNewInputSouce() { - Resource resource = new ByteArrayResource(xml.getBytes()); - - StaxEventItemReader newSource = new StaxEventItemReader(); - newSource.setResource(resource); - - newSource.setFragmentRootElementName(FRAGMENT_ROOT_ELEMENT); - newSource.setFragmentDeserializer(deserializer); - newSource.setSaveState(true); - - return newSource; - } - - /** - * A simple XMLEvent deserializer mock - check for the start and end - * document events for the fragment root & end tags + skips the fragment - * contents. - */ - private static class MockFragmentDeserializer implements EventReaderDeserializer { - - /** - * A simple mapFragment implementation checking the - * StaxEventReaderItemReader basic read functionality. - * @param eventReader - * @return list of the events from fragment body - */ - public Object deserializeFragment(XMLEventReader eventReader) { - List fragmentContent; - try { - // first event should be StartDocument - XMLEvent event1 = eventReader.nextEvent(); - assertTrue(event1.isStartDocument()); - - // second should be StartElement of the fragment - XMLEvent event2 = eventReader.nextEvent(); - assertTrue(event2.isStartElement()); - assertTrue(EventHelper.startElementName(event2).equals(FRAGMENT_ROOT_ELEMENT)); - - // jump before the end of fragment - fragmentContent = readRecordsInsideFragment(eventReader); - - // end of fragment - XMLEvent event3 = eventReader.nextEvent(); - assertTrue(event3.isEndElement()); - assertTrue(EventHelper.endElementName(event3).equals(FRAGMENT_ROOT_ELEMENT)); - - // EndDocument should follow the end of fragment - XMLEvent event4 = eventReader.nextEvent(); - assertTrue(event4.isEndDocument()); - - } - catch (XMLStreamException e) { - throw new RuntimeException("Error occured in FragmentDeserializer", e); - } - return fragmentContent; - } - - /** - * Skips the XML fragment contents. - */ - private List readRecordsInsideFragment(XMLEventReader eventReader) throws XMLStreamException { - XMLEvent eventInsideFragment; - List events = new ArrayList(); - do { - eventInsideFragment = eventReader.peek(); - if (eventInsideFragment instanceof EndElement - && ((EndElement) eventInsideFragment).getName().getLocalPart().equals(FRAGMENT_ROOT_ELEMENT)) { - break; - } - events.add(eventReader.nextEvent()); - } while (eventInsideFragment != null); - - return events; - } - - } - - /** - * Moves cursor inside the fragment body and causes rollback. - */ - private static class ExceptionFragmentDeserializer implements EventReaderDeserializer { - - public Object deserializeFragment(XMLEventReader eventReader) { - eventReader.next(); - throw new RuntimeException(); - } - - } - - private static class MockStaxEventItemReader extends StaxEventItemReader { - - private boolean openCalled = false; - - public void open(ExecutionContext executionContext) { - super.open(executionContext); - openCalled = true; - } - - public boolean isOpenCalled() { - return openCalled; - } - - public void setOpenCalled(boolean openCalled) { - this.openCalled = openCalled; - } - } - - private class NonExistentResource extends AbstractResource { - - public NonExistentResource() { - } - - public boolean exists() { - return false; - } - - public String getDescription() { - return "NonExistantResource"; - } - - public InputStream getInputStream() throws IOException { - return null; - } - } -} +package org.springframework.batch.io.xml; + +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; + +import javax.xml.stream.FactoryConfigurationError; +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.events.EndElement; +import javax.xml.stream.events.XMLEvent; + +import junit.framework.TestCase; + +import org.springframework.batch.item.ExecutionContext; +import org.springframework.batch.item.exception.StreamException; +import org.springframework.core.io.AbstractResource; +import org.springframework.core.io.ByteArrayResource; +import org.springframework.core.io.Resource; +import org.springframework.dao.DataAccessResourceFailureException; + +/** + * Tests for {@link StaxEventItemReader}. + * + * @author Robert Kasanicky + */ +public class StaxEventItemReaderTests extends TestCase { + + // object under test + private StaxEventItemReader source; + + // test xml input + private String xml = " testString "; + + private EventReaderDeserializer deserializer = new MockFragmentDeserializer(); + + private static final String FRAGMENT_ROOT_ELEMENT = "fragment"; + + private ExecutionContext executionContext; + + protected void setUp() throws Exception { + this.executionContext = new ExecutionContext(); + source = createNewInputSouce(); + } + + public void testAfterPropertiesSet() throws Exception { + source.afterPropertiesSet(); + } + + public void testAfterPropertesSetException() throws Exception { + source.setResource(null); + try { + source.afterPropertiesSet(); + fail(); + } + catch (IllegalArgumentException e) { + // expected; + } + + source = createNewInputSouce(); + source.setFragmentRootElementName(""); + try { + source.afterPropertiesSet(); + fail(); + } + catch (IllegalArgumentException e) { + // expected + } + + source = createNewInputSouce(); + source.setFragmentDeserializer(null); + try { + source.afterPropertiesSet(); + fail(); + } + catch (IllegalArgumentException e) { + // expected + } + } + + /** + * Regular usage scenario. ItemReader should pass XML fragments to + * deserializer wrapped with StartDocument and EndDocument events. + */ + public void testFragmentWrapping() throws Exception { + source.afterPropertiesSet(); + source.open(executionContext); + // see asserts in the mock deserializer + assertNotNull(source.read()); + assertNotNull(source.read()); + assertNull(source.read()); // there are only two fragments + + source.close(executionContext); + } + + /** + * Cursor is moved before beginning of next fragment. + */ + public void testMoveCursorToNextFragment() throws XMLStreamException, FactoryConfigurationError, IOException { + Resource resource = new ByteArrayResource(xml.getBytes()); + XMLEventReader reader = XMLInputFactory.newInstance().createXMLEventReader(resource.getInputStream()); + + final int EXPECTED_NUMBER_OF_FRAGMENTS = 2; + for (int i = 0; i < EXPECTED_NUMBER_OF_FRAGMENTS; i++) { + assertTrue(source.moveCursorToNextFragment(reader)); + assertTrue(EventHelper.startElementName(reader.peek()).equals("fragment")); + reader.nextEvent(); // move away from beginning of fragment + } + assertFalse(source.moveCursorToNextFragment(reader)); + } + + /** + * Save restart data and restore from it. + */ + public void testRestart() { + source.open(executionContext); + source.read(); + source.update(executionContext); + System.out.println(executionContext); + assertEquals(1, executionContext.getLong(StaxEventItemReader.class.getSimpleName() + ".read.count")); + List expectedAfterRestart = (List) source.read(); + + source = createNewInputSouce(); + source.open(executionContext); + List afterRestart = (List) source.read(); + assertEquals(expectedAfterRestart.size(), afterRestart.size()); + } + + /** + * Restore point must not exceed end of file, input source must not be + * already initialised when restoring. + */ + public void testInvalidRestore() { + ExecutionContext context = new ExecutionContext(); + context.putLong(StaxEventItemReader.class.getSimpleName() + ".read.count", 100000); + try { + source.open(context); + fail("Expected StreamException"); + } + catch (StreamException e) { + // expected + String message = e.getMessage(); + assertTrue("Wrong message: "+message, message.contains("must be before")); + } + } + + public void testRestoreWorksFromClosedStream() throws Exception { + source.close(executionContext); + source.update(executionContext); + } + /** + * Skipping marked records after rollback. + */ + public void testSkip() { + source.open(executionContext); + List first = (List) source.read(); + source.skip(); + List second = (List) source.read(); + assertFalse(first.equals(second)); + source.reset(); + + assertEquals(second, source.read()); + } + + /** + * Rollback to last commited record. + */ + public void testRollback() { + source.open(executionContext); + // rollback between deserializing records + List first = (List) source.read(); + source.mark(); + List second = (List) source.read(); + assertFalse(first.equals(second)); + source.reset(); + + assertEquals(second, source.read()); + + // rollback while deserializing record + source.reset(); + source.setFragmentDeserializer(new ExceptionFragmentDeserializer()); + try { + source.read(); + } + catch (Exception expected) { + source.reset(); + } + source.setFragmentDeserializer(deserializer); + + assertEquals(second, source.read()); + } + + /** + * Statistics return the current record count. Calling read after end of + * input does not increase the counter. + */ + public void testExecutionContext() { + final int NUMBER_OF_RECORDS = 2; + source.open(executionContext); + source.update(executionContext); + + for (int i = 0; i < NUMBER_OF_RECORDS; i++) { + long recordCount = extractRecordCount(); + assertEquals(i, recordCount); + source.read(); + source.update(executionContext); + } + + assertEquals(NUMBER_OF_RECORDS, extractRecordCount()); + source.read(); + assertEquals(NUMBER_OF_RECORDS, extractRecordCount()); + } + + private long extractRecordCount() { + return executionContext.getLong(StaxEventItemReader.class.getSimpleName() + ".read.count"); + } + + public void testCloseWithoutOpen() throws Exception { + source.close(null); + // No error! + } + + public void testClose() throws Exception { + MockStaxEventItemReader newSource = new MockStaxEventItemReader(); + Resource resource = new ByteArrayResource(xml.getBytes()); + newSource.setResource(resource); + + newSource.setFragmentRootElementName(FRAGMENT_ROOT_ELEMENT); + newSource.setFragmentDeserializer(deserializer); + + newSource.open(executionContext); + + Object item = newSource.read(); + assertNotNull(item); + assertTrue(newSource.isOpenCalled()); + + newSource.close(null); + newSource.setOpenCalled(false); + // calling read again should require re-initialization because of close + try { + item = newSource.read(); + fail("Expected StreamException"); + } + catch (StreamException e) { + // expected + } + } + + public void testOpenBadIOInput() { + + source.setResource(new AbstractResource() { + public String getDescription() { + return null; + } + + public InputStream getInputStream() throws IOException { + throw new IOException(); + } + + public boolean exists() { + return true; + } + }); + + try { + source.open(executionContext); + } + catch (DataAccessResourceFailureException ex) { + assertTrue(ex.getCause() instanceof IOException); + } + + } + + public void testNonExistentResource() throws Exception { + + source.setResource(new NonExistentResource()); + source.afterPropertiesSet(); + + try { + source.open(executionContext); + fail(); + } + catch (IllegalStateException ex) { + // expected + } + } + + public void testRuntimeFileCreation() throws Exception { + + source.setResource(new NonExistentResource()); + source.afterPropertiesSet(); + + source.setResource(new ByteArrayResource(xml.getBytes())); + source.open(executionContext); + source.read(); + } + + private StaxEventItemReader createNewInputSouce() { + Resource resource = new ByteArrayResource(xml.getBytes()); + + StaxEventItemReader newSource = new StaxEventItemReader(); + newSource.setResource(resource); + + newSource.setFragmentRootElementName(FRAGMENT_ROOT_ELEMENT); + newSource.setFragmentDeserializer(deserializer); + newSource.setSaveState(true); + + return newSource; + } + + /** + * A simple XMLEvent deserializer mock - check for the start and end + * document events for the fragment root & end tags + skips the fragment + * contents. + */ + private static class MockFragmentDeserializer implements EventReaderDeserializer { + + /** + * A simple mapFragment implementation checking the + * StaxEventReaderItemReader basic read functionality. + * @param eventReader + * @return list of the events from fragment body + */ + public Object deserializeFragment(XMLEventReader eventReader) { + List fragmentContent; + try { + // first event should be StartDocument + XMLEvent event1 = eventReader.nextEvent(); + assertTrue(event1.isStartDocument()); + + // second should be StartElement of the fragment + XMLEvent event2 = eventReader.nextEvent(); + assertTrue(event2.isStartElement()); + assertTrue(EventHelper.startElementName(event2).equals(FRAGMENT_ROOT_ELEMENT)); + + // jump before the end of fragment + fragmentContent = readRecordsInsideFragment(eventReader); + + // end of fragment + XMLEvent event3 = eventReader.nextEvent(); + assertTrue(event3.isEndElement()); + assertTrue(EventHelper.endElementName(event3).equals(FRAGMENT_ROOT_ELEMENT)); + + // EndDocument should follow the end of fragment + XMLEvent event4 = eventReader.nextEvent(); + assertTrue(event4.isEndDocument()); + + } + catch (XMLStreamException e) { + throw new RuntimeException("Error occured in FragmentDeserializer", e); + } + return fragmentContent; + } + + /** + * Skips the XML fragment contents. + */ + private List readRecordsInsideFragment(XMLEventReader eventReader) throws XMLStreamException { + XMLEvent eventInsideFragment; + List events = new ArrayList(); + do { + eventInsideFragment = eventReader.peek(); + if (eventInsideFragment instanceof EndElement + && ((EndElement) eventInsideFragment).getName().getLocalPart().equals(FRAGMENT_ROOT_ELEMENT)) { + break; + } + events.add(eventReader.nextEvent()); + } while (eventInsideFragment != null); + + return events; + } + + } + + /** + * Moves cursor inside the fragment body and causes rollback. + */ + private static class ExceptionFragmentDeserializer implements EventReaderDeserializer { + + public Object deserializeFragment(XMLEventReader eventReader) { + eventReader.next(); + throw new RuntimeException(); + } + + } + + private static class MockStaxEventItemReader extends StaxEventItemReader { + + private boolean openCalled = false; + + public void open(ExecutionContext executionContext) { + super.open(executionContext); + openCalled = true; + } + + public boolean isOpenCalled() { + return openCalled; + } + + public void setOpenCalled(boolean openCalled) { + this.openCalled = openCalled; + } + } + + private class NonExistentResource extends AbstractResource { + + public NonExistentResource() { + } + + public boolean exists() { + return false; + } + + public String getDescription() { + return "NonExistantResource"; + } + + public InputStream getInputStream() throws IOException { + return null; + } + } +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/xml/StaxEventItemWriterTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/xml/StaxEventItemWriterTests.java index 9740548f78..ef84fc0a32 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/xml/StaxEventItemWriterTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/xml/StaxEventItemWriterTests.java @@ -1,234 +1,234 @@ -package org.springframework.batch.io.xml; - -import java.io.File; -import java.io.IOException; -import java.util.HashMap; - -import javax.xml.stream.XMLEventFactory; -import javax.xml.stream.XMLStreamException; -import javax.xml.transform.Result; - -import junit.framework.TestCase; - -import org.apache.commons.io.FileUtils; -import org.springframework.batch.io.xml.oxm.MarshallingEventWriterSerializer; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.core.io.FileSystemResource; -import org.springframework.core.io.Resource; -import org.springframework.oxm.Marshaller; -import org.springframework.oxm.XmlMappingException; -import org.springframework.util.Assert; -import org.springframework.xml.transform.StaxResult; - -/** - * Tests for {@link StaxEventItemWriter}. - */ -public class StaxEventItemWriterTests extends TestCase { - - // object under test - private StaxEventItemWriter writer; - - // output file - private Resource resource; - - private ExecutionContext executionContext; - - // test item for writing to output - private Object item = new Object() { - public String toString() { - return TEST_STRING; - } - }; - - private static final String TEST_STRING = StaxEventItemWriter.class.getSimpleName() + "-testString"; - - private static final int NOT_FOUND = -1; - - protected void setUp() throws Exception { - resource = new FileSystemResource(File.createTempFile("StaxEventWriterOutputSourceTests", "xml")); - writer = createItemWriter(); - executionContext = new ExecutionContext(); - } - - /** - * Flush should pass buffered items to Serializer. - */ - public void testFlush() throws Exception { - writer.open(executionContext); - InputCheckMarshaller marshaller = new InputCheckMarshaller(); - MarshallingEventWriterSerializer serializer = new MarshallingEventWriterSerializer(marshaller); - writer.setSerializer(serializer); - - // see asserts in the marshaller - writer.write(item); - assertFalse(marshaller.wasCalled); - - writer.flush(); - assertTrue(marshaller.wasCalled); - - } - - public void testClear() throws Exception { - writer.open(executionContext); - writer.write(item); - writer.write(item); - writer.clear(); - //writer.write(item); - writer.flush(); - assertFalse(outputFileContent().contains(TEST_STRING)); - } - - /** - * Rolled back records should not be written to output file. - */ - public void testRollback() throws Exception { - writer.open(executionContext); - writer.write(item); - // rollback - writer.clear(); - assertEquals("", outputFileContent()); - } - - /** - * Item is written to the output file only after flush. - */ - public void testWriteAndFlush() throws Exception { - writer.open(executionContext); - writer.write(item); - assertEquals("", outputFileContent()); - writer.flush(); - assertTrue(outputFileContent().contains(TEST_STRING)); - } - - /** - * Restart scenario - content is appended to the output file after restart. - */ - public void testRestart() throws Exception { - writer.open(executionContext); - // write item - writer.write(item); - writer.flush(); - writer.update(executionContext); - writer.close(executionContext); - - // create new writer from saved restart data and continue writing - writer = createItemWriter(); - writer.open(executionContext); - writer.write(item); - writer.close(executionContext); - - // check the output is concatenation of 'before restart' and 'after - // restart' writes. - String outputFile = outputFileContent(); - int firstRecord = outputFile.indexOf(TEST_STRING); - int secondRecord = outputFile.indexOf(TEST_STRING, firstRecord + TEST_STRING.length()); - int thirdRecord = outputFile.indexOf(TEST_STRING, secondRecord + TEST_STRING.length()); - - // (two records should be written) - assertTrue(firstRecord != NOT_FOUND); - assertTrue(secondRecord != NOT_FOUND); - assertEquals(NOT_FOUND, thirdRecord); - } - - /** - * Count of 'records written so far' is returned as statistics. - */ - public void testStreamContext() throws Exception { - writer.open(executionContext); - final int NUMBER_OF_RECORDS = 10; - for (int i = 1; i <= NUMBER_OF_RECORDS; i++) { - writer.write(item); - writer.update(executionContext); - long writeStatistics = executionContext.getLong(StaxEventItemWriter.class.getSimpleName() + ".record.count"); - - assertEquals(i, writeStatistics); - } - } - - /** - * Open method writes the root tag, close method adds corresponding end tag. - */ - public void testOpenAndClose() throws Exception { - writer.setRootTagName("testroot"); - writer.setRootElementAttributes(new HashMap() { - { - put("attribute", "value"); - } - }); - writer.open(executionContext); - writer.flush(); - - assertTrue(outputFileContent().indexOf("")); - } - - /** - * Checks the received parameters. - */ - private class InputCheckMarshaller implements Marshaller { - - boolean wasCalled = false; - - public void marshal(Object graph, Result result) { - wasCalled = true; - assertTrue(result instanceof StaxResult); - assertSame(item, graph); - } - - public boolean supports(Class clazz) { - return true; - } - } - - /** - * Writes object's toString representation as XML comment. - */ - private static class SimpleMarshaller implements Marshaller { - public void marshal(Object graph, Result result) throws XmlMappingException, IOException { - Assert.isInstanceOf(StaxResult.class, result); - - StaxResult staxResult = (StaxResult) result; - try { - staxResult.getXMLEventWriter().add(XMLEventFactory.newInstance().createComment(graph.toString())); - } - catch (XMLStreamException e) { - throw new RuntimeException("Exception while writing to output file", e); - } - } - - public boolean supports(Class clazz) { - return true; - } - } - - /** - * @return output file content as String - */ - private String outputFileContent() throws IOException { - return FileUtils.readFileToString(resource.getFile(), null); - } - - /** - * @return new instance of fully configured writer - */ - private StaxEventItemWriter createItemWriter() throws Exception { - StaxEventItemWriter source = new StaxEventItemWriter(); - source.setResource(resource); - - Marshaller marshaller = new SimpleMarshaller(); - MarshallingEventWriterSerializer serializer = new MarshallingEventWriterSerializer(marshaller); - source.setSerializer(serializer); - - source.setEncoding("UTF-8"); - source.setRootTagName("root"); - source.setVersion("1.0"); - source.setOverwriteOutput(true); - source.setSaveState(true); - - source.afterPropertiesSet(); - - return source; - } -} +package org.springframework.batch.io.xml; + +import java.io.File; +import java.io.IOException; +import java.util.HashMap; + +import javax.xml.stream.XMLEventFactory; +import javax.xml.stream.XMLStreamException; +import javax.xml.transform.Result; + +import junit.framework.TestCase; + +import org.apache.commons.io.FileUtils; +import org.springframework.batch.io.xml.oxm.MarshallingEventWriterSerializer; +import org.springframework.batch.item.ExecutionContext; +import org.springframework.core.io.FileSystemResource; +import org.springframework.core.io.Resource; +import org.springframework.oxm.Marshaller; +import org.springframework.oxm.XmlMappingException; +import org.springframework.util.Assert; +import org.springframework.xml.transform.StaxResult; + +/** + * Tests for {@link StaxEventItemWriter}. + */ +public class StaxEventItemWriterTests extends TestCase { + + // object under test + private StaxEventItemWriter writer; + + // output file + private Resource resource; + + private ExecutionContext executionContext; + + // test item for writing to output + private Object item = new Object() { + public String toString() { + return TEST_STRING; + } + }; + + private static final String TEST_STRING = StaxEventItemWriter.class.getSimpleName() + "-testString"; + + private static final int NOT_FOUND = -1; + + protected void setUp() throws Exception { + resource = new FileSystemResource(File.createTempFile("StaxEventWriterOutputSourceTests", "xml")); + writer = createItemWriter(); + executionContext = new ExecutionContext(); + } + + /** + * Flush should pass buffered items to Serializer. + */ + public void testFlush() throws Exception { + writer.open(executionContext); + InputCheckMarshaller marshaller = new InputCheckMarshaller(); + MarshallingEventWriterSerializer serializer = new MarshallingEventWriterSerializer(marshaller); + writer.setSerializer(serializer); + + // see asserts in the marshaller + writer.write(item); + assertFalse(marshaller.wasCalled); + + writer.flush(); + assertTrue(marshaller.wasCalled); + + } + + public void testClear() throws Exception { + writer.open(executionContext); + writer.write(item); + writer.write(item); + writer.clear(); + //writer.write(item); + writer.flush(); + assertFalse(outputFileContent().contains(TEST_STRING)); + } + + /** + * Rolled back records should not be written to output file. + */ + public void testRollback() throws Exception { + writer.open(executionContext); + writer.write(item); + // rollback + writer.clear(); + assertEquals("", outputFileContent()); + } + + /** + * Item is written to the output file only after flush. + */ + public void testWriteAndFlush() throws Exception { + writer.open(executionContext); + writer.write(item); + assertEquals("", outputFileContent()); + writer.flush(); + assertTrue(outputFileContent().contains(TEST_STRING)); + } + + /** + * Restart scenario - content is appended to the output file after restart. + */ + public void testRestart() throws Exception { + writer.open(executionContext); + // write item + writer.write(item); + writer.flush(); + writer.update(executionContext); + writer.close(executionContext); + + // create new writer from saved restart data and continue writing + writer = createItemWriter(); + writer.open(executionContext); + writer.write(item); + writer.close(executionContext); + + // check the output is concatenation of 'before restart' and 'after + // restart' writes. + String outputFile = outputFileContent(); + int firstRecord = outputFile.indexOf(TEST_STRING); + int secondRecord = outputFile.indexOf(TEST_STRING, firstRecord + TEST_STRING.length()); + int thirdRecord = outputFile.indexOf(TEST_STRING, secondRecord + TEST_STRING.length()); + + // (two records should be written) + assertTrue(firstRecord != NOT_FOUND); + assertTrue(secondRecord != NOT_FOUND); + assertEquals(NOT_FOUND, thirdRecord); + } + + /** + * Count of 'records written so far' is returned as statistics. + */ + public void testStreamContext() throws Exception { + writer.open(executionContext); + final int NUMBER_OF_RECORDS = 10; + for (int i = 1; i <= NUMBER_OF_RECORDS; i++) { + writer.write(item); + writer.update(executionContext); + long writeStatistics = executionContext.getLong(StaxEventItemWriter.class.getSimpleName() + ".record.count"); + + assertEquals(i, writeStatistics); + } + } + + /** + * Open method writes the root tag, close method adds corresponding end tag. + */ + public void testOpenAndClose() throws Exception { + writer.setRootTagName("testroot"); + writer.setRootElementAttributes(new HashMap() { + { + put("attribute", "value"); + } + }); + writer.open(executionContext); + writer.flush(); + + assertTrue(outputFileContent().indexOf("")); + } + + /** + * Checks the received parameters. + */ + private class InputCheckMarshaller implements Marshaller { + + boolean wasCalled = false; + + public void marshal(Object graph, Result result) { + wasCalled = true; + assertTrue(result instanceof StaxResult); + assertSame(item, graph); + } + + public boolean supports(Class clazz) { + return true; + } + } + + /** + * Writes object's toString representation as XML comment. + */ + private static class SimpleMarshaller implements Marshaller { + public void marshal(Object graph, Result result) throws XmlMappingException, IOException { + Assert.isInstanceOf(StaxResult.class, result); + + StaxResult staxResult = (StaxResult) result; + try { + staxResult.getXMLEventWriter().add(XMLEventFactory.newInstance().createComment(graph.toString())); + } + catch (XMLStreamException e) { + throw new RuntimeException("Exception while writing to output file", e); + } + } + + public boolean supports(Class clazz) { + return true; + } + } + + /** + * @return output file content as String + */ + private String outputFileContent() throws IOException { + return FileUtils.readFileToString(resource.getFile(), null); + } + + /** + * @return new instance of fully configured writer + */ + private StaxEventItemWriter createItemWriter() throws Exception { + StaxEventItemWriter source = new StaxEventItemWriter(); + source.setResource(resource); + + Marshaller marshaller = new SimpleMarshaller(); + MarshallingEventWriterSerializer serializer = new MarshallingEventWriterSerializer(marshaller); + source.setSerializer(serializer); + + source.setEncoding("UTF-8"); + source.setRootTagName("root"); + source.setVersion("1.0"); + source.setOverwriteOutput(true); + source.setSaveState(true); + + source.afterPropertiesSet(); + + return source; + } +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/xml/oxm/MarshallingObjectToXmlSerializerTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/xml/oxm/MarshallingObjectToXmlSerializerTests.java index 6d75e901ec..8d94da11b7 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/xml/oxm/MarshallingObjectToXmlSerializerTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/xml/oxm/MarshallingObjectToXmlSerializerTests.java @@ -1,132 +1,132 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.io.xml.oxm; - -import java.io.IOException; - -import javax.xml.namespace.NamespaceContext; -import javax.xml.stream.XMLEventReader; -import javax.xml.stream.XMLEventWriter; -import javax.xml.stream.XMLStreamException; -import javax.xml.stream.events.XMLEvent; -import javax.xml.transform.Result; - -import junit.framework.TestCase; - -import org.springframework.batch.io.xml.oxm.MarshallingEventWriterSerializer; -import org.springframework.dao.DataAccessResourceFailureException; -import org.springframework.oxm.Marshaller; -import org.springframework.oxm.XmlMappingException; - -/** - * - * - * @author Lucas Ward - * - */ -public class MarshallingObjectToXmlSerializerTests extends TestCase { - - MarshallingEventWriterSerializer xmlSerializer; - - MockMarshaller mockMarshaller = new MockMarshaller(); - - private StubXmlEventWriter writer; - - protected void setUp() throws Exception { - super.setUp(); - - xmlSerializer = new MarshallingEventWriterSerializer(mockMarshaller); - writer = new StubXmlEventWriter(); - } - - public void testSuccessfulWrite(){ - - Object objectToOutput = new Object(); - xmlSerializer.serializeObject(writer, objectToOutput); - assertEquals(objectToOutput, mockMarshaller.getMarshalledObject()); - } - - public void testUnsucessfulWrite(){ - - mockMarshaller.setThrowException(true); - try{ - xmlSerializer.serializeObject(writer, new Object()); - fail("Exception expected"); - }catch(DataAccessResourceFailureException ex){ - //expected - } - } - - private static class MockMarshaller implements Marshaller{ - - private Object marshalledObject; - private boolean throwException = false; - - public void marshal(Object arg0, Result arg1) - throws XmlMappingException, IOException { - if(throwException){ - throw new IOException(); - } - marshalledObject = arg0; - } - - public boolean supports(Class arg0) { - return false; - } - - public Object getMarshalledObject() { - return marshalledObject; - } - - public void setThrowException(boolean throwException) { - this.throwException = throwException; - } - } - - private static class StubXmlEventWriter implements XMLEventWriter{ - - public void add(XMLEvent arg0) throws XMLStreamException { } - - public void add(XMLEventReader arg0) throws XMLStreamException { } - - public void close() throws XMLStreamException { - } - - public void flush() throws XMLStreamException { - } - - public NamespaceContext getNamespaceContext() { - return null; - } - - public String getPrefix(String arg0) throws XMLStreamException { - return null; - } - - public void setDefaultNamespace(String arg0) throws XMLStreamException { - } - - public void setNamespaceContext(NamespaceContext arg0) - throws XMLStreamException { - } - - public void setPrefix(String arg0, String arg1) - throws XMLStreamException { - } - - } -} - +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.io.xml.oxm; + +import java.io.IOException; + +import javax.xml.namespace.NamespaceContext; +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.XMLEventWriter; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.events.XMLEvent; +import javax.xml.transform.Result; + +import junit.framework.TestCase; + +import org.springframework.batch.io.xml.oxm.MarshallingEventWriterSerializer; +import org.springframework.dao.DataAccessResourceFailureException; +import org.springframework.oxm.Marshaller; +import org.springframework.oxm.XmlMappingException; + +/** + * + * + * @author Lucas Ward + * + */ +public class MarshallingObjectToXmlSerializerTests extends TestCase { + + MarshallingEventWriterSerializer xmlSerializer; + + MockMarshaller mockMarshaller = new MockMarshaller(); + + private StubXmlEventWriter writer; + + protected void setUp() throws Exception { + super.setUp(); + + xmlSerializer = new MarshallingEventWriterSerializer(mockMarshaller); + writer = new StubXmlEventWriter(); + } + + public void testSuccessfulWrite(){ + + Object objectToOutput = new Object(); + xmlSerializer.serializeObject(writer, objectToOutput); + assertEquals(objectToOutput, mockMarshaller.getMarshalledObject()); + } + + public void testUnsucessfulWrite(){ + + mockMarshaller.setThrowException(true); + try{ + xmlSerializer.serializeObject(writer, new Object()); + fail("Exception expected"); + }catch(DataAccessResourceFailureException ex){ + //expected + } + } + + private static class MockMarshaller implements Marshaller{ + + private Object marshalledObject; + private boolean throwException = false; + + public void marshal(Object arg0, Result arg1) + throws XmlMappingException, IOException { + if(throwException){ + throw new IOException(); + } + marshalledObject = arg0; + } + + public boolean supports(Class arg0) { + return false; + } + + public Object getMarshalledObject() { + return marshalledObject; + } + + public void setThrowException(boolean throwException) { + this.throwException = throwException; + } + } + + private static class StubXmlEventWriter implements XMLEventWriter{ + + public void add(XMLEvent arg0) throws XMLStreamException { } + + public void add(XMLEventReader arg0) throws XMLStreamException { } + + public void close() throws XMLStreamException { + } + + public void flush() throws XMLStreamException { + } + + public NamespaceContext getNamespaceContext() { + return null; + } + + public String getPrefix(String arg0) throws XMLStreamException { + return null; + } + + public void setDefaultNamespace(String arg0) throws XMLStreamException { + } + + public void setNamespaceContext(NamespaceContext arg0) + throws XMLStreamException { + } + + public void setPrefix(String arg0, String arg1) + throws XMLStreamException { + } + + } +} + diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/xml/oxm/UnmarshallingFragmentDeserializerTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/xml/oxm/UnmarshallingFragmentDeserializerTests.java index 119d356786..e1a56fa76f 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/xml/oxm/UnmarshallingFragmentDeserializerTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/xml/oxm/UnmarshallingFragmentDeserializerTests.java @@ -1,92 +1,92 @@ -package org.springframework.batch.io.xml.oxm; - -import java.io.IOException; - -import javax.xml.stream.XMLEventReader; -import javax.xml.stream.XMLInputFactory; - -import junit.framework.TestCase; - -import org.easymock.MockControl; -import org.springframework.batch.io.xml.oxm.UnmarshallingEventReaderDeserializer; -import org.springframework.core.io.ByteArrayResource; -import org.springframework.core.io.Resource; -import org.springframework.dao.DataAccessException; -import org.springframework.oxm.Unmarshaller; - -/** - * Tests for {@link UnmarshallingEventReaderDeserializer} - * - * @author Robert Kasanicky - */ -public class UnmarshallingFragmentDeserializerTests extends TestCase { - - // object under test - private UnmarshallingEventReaderDeserializer deserializer; - - private XMLEventReader eventReader; - private String xml = " "; - - private Unmarshaller unmarshaller; - private MockControl unmarshallerControl = MockControl.createStrictControl(Unmarshaller.class); - - - - protected void setUp() throws Exception { - Resource input = new ByteArrayResource(xml.getBytes()); - eventReader = XMLInputFactory.newInstance().createXMLEventReader(input.getInputStream()); - unmarshaller = (Unmarshaller) unmarshallerControl.getMock(); - unmarshallerControl.setDefaultMatcher(MockControl.ALWAYS_MATCHER); - deserializer = new UnmarshallingEventReaderDeserializer(unmarshaller); - } - - /** - * Regular scenario when deserializer returns the object provided by Unmarshaller - */ - public void testSuccessfulDeserialization() throws Exception { - Object expectedResult = new Object(); - unmarshaller.unmarshal(null); - unmarshallerControl.setReturnValue(expectedResult); - unmarshallerControl.replay(); - - Object result = deserializer.deserializeFragment(eventReader); - - assertEquals(expectedResult, result); - - unmarshallerControl.verify(); - } - - /** - * Appropriate exception rethrown in case of failure. - */ - public void testFailedDeserialization() throws Exception { - unmarshaller.unmarshal(null); - unmarshallerControl.setThrowable(new IOException()); - unmarshallerControl.replay(); - - try { - deserializer.deserializeFragment(eventReader); - fail("Exception expected"); - } - catch (DataAccessException e) { - // expected - } - - unmarshallerControl.verify(); - } - - /** - * It makes no sense to create UnmarshallingFragmentDeserializer with null Unmarshaller, - * therefore it should cause exception. - */ - public void testExceptionOnNullUnmarshaller() { - try { - deserializer = new UnmarshallingEventReaderDeserializer(null); - fail("Exception expected"); - } - catch (IllegalArgumentException e) { - // expected - } - - } -} +package org.springframework.batch.io.xml.oxm; + +import java.io.IOException; + +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.XMLInputFactory; + +import junit.framework.TestCase; + +import org.easymock.MockControl; +import org.springframework.batch.io.xml.oxm.UnmarshallingEventReaderDeserializer; +import org.springframework.core.io.ByteArrayResource; +import org.springframework.core.io.Resource; +import org.springframework.dao.DataAccessException; +import org.springframework.oxm.Unmarshaller; + +/** + * Tests for {@link UnmarshallingEventReaderDeserializer} + * + * @author Robert Kasanicky + */ +public class UnmarshallingFragmentDeserializerTests extends TestCase { + + // object under test + private UnmarshallingEventReaderDeserializer deserializer; + + private XMLEventReader eventReader; + private String xml = " "; + + private Unmarshaller unmarshaller; + private MockControl unmarshallerControl = MockControl.createStrictControl(Unmarshaller.class); + + + + protected void setUp() throws Exception { + Resource input = new ByteArrayResource(xml.getBytes()); + eventReader = XMLInputFactory.newInstance().createXMLEventReader(input.getInputStream()); + unmarshaller = (Unmarshaller) unmarshallerControl.getMock(); + unmarshallerControl.setDefaultMatcher(MockControl.ALWAYS_MATCHER); + deserializer = new UnmarshallingEventReaderDeserializer(unmarshaller); + } + + /** + * Regular scenario when deserializer returns the object provided by Unmarshaller + */ + public void testSuccessfulDeserialization() throws Exception { + Object expectedResult = new Object(); + unmarshaller.unmarshal(null); + unmarshallerControl.setReturnValue(expectedResult); + unmarshallerControl.replay(); + + Object result = deserializer.deserializeFragment(eventReader); + + assertEquals(expectedResult, result); + + unmarshallerControl.verify(); + } + + /** + * Appropriate exception rethrown in case of failure. + */ + public void testFailedDeserialization() throws Exception { + unmarshaller.unmarshal(null); + unmarshallerControl.setThrowable(new IOException()); + unmarshallerControl.replay(); + + try { + deserializer.deserializeFragment(eventReader); + fail("Exception expected"); + } + catch (DataAccessException e) { + // expected + } + + unmarshallerControl.verify(); + } + + /** + * It makes no sense to create UnmarshallingFragmentDeserializer with null Unmarshaller, + * therefore it should cause exception. + */ + public void testExceptionOnNullUnmarshaller() { + try { + deserializer = new UnmarshallingEventReaderDeserializer(null); + fail("Exception expected"); + } + catch (IllegalArgumentException e) { + // expected + } + + } +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/xml/stax/AbstractEventReaderWrapperTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/xml/stax/AbstractEventReaderWrapperTests.java index d81892bda2..907cf88faa 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/xml/stax/AbstractEventReaderWrapperTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/xml/stax/AbstractEventReaderWrapperTests.java @@ -1,135 +1,135 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.io.xml.stax; - -import javax.xml.stream.XMLEventReader; -import javax.xml.stream.XMLStreamException; -import javax.xml.stream.events.XMLEvent; - -import junit.framework.TestCase; - -import org.easymock.MockControl; -import org.springframework.batch.io.xml.stax.AbstractEventReaderWrapper; - -import com.bea.xml.stream.events.StartDocumentEvent; - -/** - * @author Lucas Ward - * - */ -public class AbstractEventReaderWrapperTests extends TestCase { - - AbstractEventReaderWrapper eventReaderWrapper; - MockControl mockEventReaderControl = MockControl.createControl(XMLEventReader.class); - XMLEventReader xmlEventReader; - - protected void setUp() throws Exception { - super.setUp(); - - xmlEventReader = (XMLEventReader)mockEventReaderControl.getMock(); - eventReaderWrapper = new StubEventReader(xmlEventReader); - } - - public void testClose() throws XMLStreamException { - xmlEventReader.close(); - mockEventReaderControl.replay(); - eventReaderWrapper.close(); - mockEventReaderControl.verify(); - } - - public void testGetElementText() throws XMLStreamException { - - String text = "text"; - xmlEventReader.getElementText(); - mockEventReaderControl.setReturnValue(text); - mockEventReaderControl.replay(); - assertEquals(eventReaderWrapper.getElementText(), text); - mockEventReaderControl.verify(); - } - - public void testGetProperty() throws IllegalArgumentException { - - String text = "text"; - xmlEventReader.getProperty("name"); - mockEventReaderControl.setReturnValue(text); - mockEventReaderControl.replay(); - assertEquals(eventReaderWrapper.getProperty("name"), text); - mockEventReaderControl.verify(); - } - - public void testHasNext() { - - xmlEventReader.hasNext(); - mockEventReaderControl.setReturnValue(true); - mockEventReaderControl.replay(); - assertTrue(eventReaderWrapper.hasNext()); - mockEventReaderControl.verify(); - } - - public void testNext() { - - String text = "text"; - xmlEventReader.next(); - mockEventReaderControl.setReturnValue(text); - mockEventReaderControl.replay(); - assertEquals(eventReaderWrapper.next(), text); - mockEventReaderControl.verify(); - } - - public void testNextEvent() throws XMLStreamException { - - XMLEvent event = new StartDocumentEvent(); - xmlEventReader.nextEvent(); - mockEventReaderControl.setReturnValue(event); - mockEventReaderControl.replay(); - assertEquals(eventReaderWrapper.nextEvent(), event); - mockEventReaderControl.verify(); - } - - public void testNextTag() throws XMLStreamException { - - XMLEvent event = new StartDocumentEvent(); - xmlEventReader.nextTag(); - mockEventReaderControl.setReturnValue(event); - mockEventReaderControl.replay(); - assertEquals(eventReaderWrapper.nextTag(), event); - mockEventReaderControl.verify(); - } - - public void testPeek() throws XMLStreamException { - - XMLEvent event = new StartDocumentEvent(); - xmlEventReader.peek(); - mockEventReaderControl.setReturnValue(event); - mockEventReaderControl.replay(); - assertEquals(eventReaderWrapper.peek(), event); - mockEventReaderControl.verify(); - } - - public void testRemove() { - - xmlEventReader.remove(); - mockEventReaderControl.replay(); - eventReaderWrapper.remove(); - mockEventReaderControl.verify(); - } - - private static class StubEventReader extends AbstractEventReaderWrapper{ - public StubEventReader(XMLEventReader wrappedEventReader) { - super(wrappedEventReader); - } - } -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.io.xml.stax; + +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.events.XMLEvent; + +import junit.framework.TestCase; + +import org.easymock.MockControl; +import org.springframework.batch.io.xml.stax.AbstractEventReaderWrapper; + +import com.bea.xml.stream.events.StartDocumentEvent; + +/** + * @author Lucas Ward + * + */ +public class AbstractEventReaderWrapperTests extends TestCase { + + AbstractEventReaderWrapper eventReaderWrapper; + MockControl mockEventReaderControl = MockControl.createControl(XMLEventReader.class); + XMLEventReader xmlEventReader; + + protected void setUp() throws Exception { + super.setUp(); + + xmlEventReader = (XMLEventReader)mockEventReaderControl.getMock(); + eventReaderWrapper = new StubEventReader(xmlEventReader); + } + + public void testClose() throws XMLStreamException { + xmlEventReader.close(); + mockEventReaderControl.replay(); + eventReaderWrapper.close(); + mockEventReaderControl.verify(); + } + + public void testGetElementText() throws XMLStreamException { + + String text = "text"; + xmlEventReader.getElementText(); + mockEventReaderControl.setReturnValue(text); + mockEventReaderControl.replay(); + assertEquals(eventReaderWrapper.getElementText(), text); + mockEventReaderControl.verify(); + } + + public void testGetProperty() throws IllegalArgumentException { + + String text = "text"; + xmlEventReader.getProperty("name"); + mockEventReaderControl.setReturnValue(text); + mockEventReaderControl.replay(); + assertEquals(eventReaderWrapper.getProperty("name"), text); + mockEventReaderControl.verify(); + } + + public void testHasNext() { + + xmlEventReader.hasNext(); + mockEventReaderControl.setReturnValue(true); + mockEventReaderControl.replay(); + assertTrue(eventReaderWrapper.hasNext()); + mockEventReaderControl.verify(); + } + + public void testNext() { + + String text = "text"; + xmlEventReader.next(); + mockEventReaderControl.setReturnValue(text); + mockEventReaderControl.replay(); + assertEquals(eventReaderWrapper.next(), text); + mockEventReaderControl.verify(); + } + + public void testNextEvent() throws XMLStreamException { + + XMLEvent event = new StartDocumentEvent(); + xmlEventReader.nextEvent(); + mockEventReaderControl.setReturnValue(event); + mockEventReaderControl.replay(); + assertEquals(eventReaderWrapper.nextEvent(), event); + mockEventReaderControl.verify(); + } + + public void testNextTag() throws XMLStreamException { + + XMLEvent event = new StartDocumentEvent(); + xmlEventReader.nextTag(); + mockEventReaderControl.setReturnValue(event); + mockEventReaderControl.replay(); + assertEquals(eventReaderWrapper.nextTag(), event); + mockEventReaderControl.verify(); + } + + public void testPeek() throws XMLStreamException { + + XMLEvent event = new StartDocumentEvent(); + xmlEventReader.peek(); + mockEventReaderControl.setReturnValue(event); + mockEventReaderControl.replay(); + assertEquals(eventReaderWrapper.peek(), event); + mockEventReaderControl.verify(); + } + + public void testRemove() { + + xmlEventReader.remove(); + mockEventReaderControl.replay(); + eventReaderWrapper.remove(); + mockEventReaderControl.verify(); + } + + private static class StubEventReader extends AbstractEventReaderWrapper{ + public StubEventReader(XMLEventReader wrappedEventReader) { + super(wrappedEventReader); + } + } +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/xml/stax/AbstractEventWriterWrapperTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/xml/stax/AbstractEventWriterWrapperTests.java index 2279aee81c..1f9b53bd16 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/xml/stax/AbstractEventWriterWrapperTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/xml/stax/AbstractEventWriterWrapperTests.java @@ -1,135 +1,135 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.io.xml.stax; - -import javax.xml.namespace.NamespaceContext; -import javax.xml.stream.XMLEventReader; -import javax.xml.stream.XMLEventWriter; -import javax.xml.stream.XMLStreamException; -import javax.xml.stream.events.XMLEvent; - -import junit.framework.TestCase; - -import org.easymock.MockControl; -import org.springframework.batch.io.xml.stax.AbstractEventWriterWrapper; - -import com.bea.xml.stream.events.StartDocumentEvent; -import com.bea.xml.stream.util.NamespaceContextImpl; - -/** - * @author Lucas Ward - * - */ -public class AbstractEventWriterWrapperTests extends TestCase { - - AbstractEventWriterWrapper eventWriterWrapper; - MockControl mockEventWriterControl = MockControl.createControl(XMLEventWriter.class); - XMLEventWriter xmlEventWriter; - - protected void setUp() throws Exception { - super.setUp(); - - xmlEventWriter = (XMLEventWriter)mockEventWriterControl.getMock(); - eventWriterWrapper = new StubEventWriter(xmlEventWriter); - } - - public void testAdd() throws XMLStreamException { - - XMLEvent event = new StartDocumentEvent(); - xmlEventWriter.add(event); - mockEventWriterControl.replay(); - eventWriterWrapper.add(event); - mockEventWriterControl.verify(); - - } - - public void testAddReader() throws XMLStreamException { - - MockControl readerControl = MockControl.createControl(XMLEventReader.class); - XMLEventReader reader = (XMLEventReader)readerControl.getMock(); - xmlEventWriter.add(reader); - mockEventWriterControl.replay(); - eventWriterWrapper.add(reader); - mockEventWriterControl.verify(); - } - - public void testClose() throws XMLStreamException { - xmlEventWriter.close(); - mockEventWriterControl.replay(); - eventWriterWrapper.close(); - mockEventWriterControl.verify(); - } - - public void testFlush() throws XMLStreamException { - xmlEventWriter.flush(); - mockEventWriterControl.replay(); - eventWriterWrapper.flush(); - mockEventWriterControl.verify(); - } - - public void testGetNamespaceContext() { - NamespaceContext context = new NamespaceContextImpl(); - xmlEventWriter.getNamespaceContext(); - mockEventWriterControl.setReturnValue(context); - mockEventWriterControl.replay(); - assertEquals(eventWriterWrapper.getNamespaceContext(), context); - mockEventWriterControl.verify(); - } - - public void testGetPrefix() throws XMLStreamException { - - String uri = "uri"; - xmlEventWriter.getPrefix(uri); - mockEventWriterControl.setReturnValue(uri); - mockEventWriterControl.replay(); - assertEquals(eventWriterWrapper.getPrefix(uri), uri); - mockEventWriterControl.verify(); - } - - public void testSetDefaultNamespace() throws XMLStreamException { - String uri = "uri"; - xmlEventWriter.setDefaultNamespace(uri); - mockEventWriterControl.replay(); - eventWriterWrapper.setDefaultNamespace(uri); - mockEventWriterControl.verify(); - } - - public void testSetNamespaceContext() - throws XMLStreamException { - - NamespaceContext context = new NamespaceContextImpl(); - xmlEventWriter.setNamespaceContext(context); - mockEventWriterControl.replay(); - eventWriterWrapper.setNamespaceContext(context); - mockEventWriterControl.verify(); - } - - public void testSetPrefix() throws XMLStreamException { - - String uri = "uri"; - String prefix = "prefix"; - xmlEventWriter.setPrefix(prefix, uri); - mockEventWriterControl.replay(); - eventWriterWrapper.setPrefix(prefix, uri); - mockEventWriterControl.verify(); - } - - private static class StubEventWriter extends AbstractEventWriterWrapper{ - public StubEventWriter(XMLEventWriter wrappedEventWriter) { - super(wrappedEventWriter); - } - } -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.io.xml.stax; + +import javax.xml.namespace.NamespaceContext; +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.XMLEventWriter; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.events.XMLEvent; + +import junit.framework.TestCase; + +import org.easymock.MockControl; +import org.springframework.batch.io.xml.stax.AbstractEventWriterWrapper; + +import com.bea.xml.stream.events.StartDocumentEvent; +import com.bea.xml.stream.util.NamespaceContextImpl; + +/** + * @author Lucas Ward + * + */ +public class AbstractEventWriterWrapperTests extends TestCase { + + AbstractEventWriterWrapper eventWriterWrapper; + MockControl mockEventWriterControl = MockControl.createControl(XMLEventWriter.class); + XMLEventWriter xmlEventWriter; + + protected void setUp() throws Exception { + super.setUp(); + + xmlEventWriter = (XMLEventWriter)mockEventWriterControl.getMock(); + eventWriterWrapper = new StubEventWriter(xmlEventWriter); + } + + public void testAdd() throws XMLStreamException { + + XMLEvent event = new StartDocumentEvent(); + xmlEventWriter.add(event); + mockEventWriterControl.replay(); + eventWriterWrapper.add(event); + mockEventWriterControl.verify(); + + } + + public void testAddReader() throws XMLStreamException { + + MockControl readerControl = MockControl.createControl(XMLEventReader.class); + XMLEventReader reader = (XMLEventReader)readerControl.getMock(); + xmlEventWriter.add(reader); + mockEventWriterControl.replay(); + eventWriterWrapper.add(reader); + mockEventWriterControl.verify(); + } + + public void testClose() throws XMLStreamException { + xmlEventWriter.close(); + mockEventWriterControl.replay(); + eventWriterWrapper.close(); + mockEventWriterControl.verify(); + } + + public void testFlush() throws XMLStreamException { + xmlEventWriter.flush(); + mockEventWriterControl.replay(); + eventWriterWrapper.flush(); + mockEventWriterControl.verify(); + } + + public void testGetNamespaceContext() { + NamespaceContext context = new NamespaceContextImpl(); + xmlEventWriter.getNamespaceContext(); + mockEventWriterControl.setReturnValue(context); + mockEventWriterControl.replay(); + assertEquals(eventWriterWrapper.getNamespaceContext(), context); + mockEventWriterControl.verify(); + } + + public void testGetPrefix() throws XMLStreamException { + + String uri = "uri"; + xmlEventWriter.getPrefix(uri); + mockEventWriterControl.setReturnValue(uri); + mockEventWriterControl.replay(); + assertEquals(eventWriterWrapper.getPrefix(uri), uri); + mockEventWriterControl.verify(); + } + + public void testSetDefaultNamespace() throws XMLStreamException { + String uri = "uri"; + xmlEventWriter.setDefaultNamespace(uri); + mockEventWriterControl.replay(); + eventWriterWrapper.setDefaultNamespace(uri); + mockEventWriterControl.verify(); + } + + public void testSetNamespaceContext() + throws XMLStreamException { + + NamespaceContext context = new NamespaceContextImpl(); + xmlEventWriter.setNamespaceContext(context); + mockEventWriterControl.replay(); + eventWriterWrapper.setNamespaceContext(context); + mockEventWriterControl.verify(); + } + + public void testSetPrefix() throws XMLStreamException { + + String uri = "uri"; + String prefix = "prefix"; + xmlEventWriter.setPrefix(prefix, uri); + mockEventWriterControl.replay(); + eventWriterWrapper.setPrefix(prefix, uri); + mockEventWriterControl.verify(); + } + + private static class StubEventWriter extends AbstractEventWriterWrapper{ + public StubEventWriter(XMLEventWriter wrappedEventWriter) { + super(wrappedEventWriter); + } + } +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/xml/stax/DefaultFragmentEventReaderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/xml/stax/DefaultFragmentEventReaderTests.java index b3f810af57..97a22a1b4f 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/xml/stax/DefaultFragmentEventReaderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/xml/stax/DefaultFragmentEventReaderTests.java @@ -1,144 +1,144 @@ -package org.springframework.batch.io.xml.stax; - -import java.util.NoSuchElementException; - -import javax.xml.stream.XMLEventReader; -import javax.xml.stream.XMLInputFactory; -import javax.xml.stream.XMLStreamException; -import javax.xml.stream.events.XMLEvent; - -import junit.framework.TestCase; - -import org.springframework.batch.io.xml.EventHelper; -import org.springframework.batch.io.xml.stax.DefaultFragmentEventReader; -import org.springframework.batch.io.xml.stax.DefaultTransactionalEventReader; -import org.springframework.core.io.ByteArrayResource; -import org.springframework.core.io.Resource; - -/** - * Tests for {@link DefaultFragmentEventReader}. - * - * @author Robert Kasanicky - */ -public class DefaultFragmentEventReaderTests extends TestCase { - - // object under test - private FragmentEventReader fragmentReader; - - // wrapped event fragmentReader - private XMLEventReader eventReader; - - // test xml input - private String xml = " "; - - /** - * Setup the fragmentReader to read the test input. - */ - protected void setUp() throws Exception { - Resource input = new ByteArrayResource(xml.getBytes()); - eventReader = new DefaultTransactionalEventReader(XMLInputFactory.newInstance().createXMLEventReader( - input.getInputStream())); - fragmentReader = new DefaultFragmentEventReader(eventReader); - } - - /** - * Marked element should be wrapped with StartDocument and EndDocument - * events. - * Test uses redundant peek() calls before nextEvent() in important moments to assure - * peek() has no side effects on the inner state of reader. - */ - public void testFragmentWrapping() throws XMLStreamException { - - assertTrue(fragmentReader.hasNext()); - moveCursorBeforeFragmentStart(); - - fragmentReader.markStartFragment(); // mark the fragment - assertTrue(EventHelper.startElementName(eventReader.peek()).equals("fragment")); - - // StartDocument inserted before StartElement - assertTrue(fragmentReader.peek().isStartDocument()); - assertTrue(fragmentReader.nextEvent().isStartDocument()); - // StartElement follows in the next step - assertTrue(EventHelper.startElementName(fragmentReader.nextEvent()).equals("fragment")); - - moveCursorToNextElementEvent(); // misc1 start - fragmentReader.nextEvent(); // skip it - moveCursorToNextElementEvent(); // misc1 end - fragmentReader.nextEvent(); // skip it - moveCursorToNextElementEvent(); // move to end of fragment - - // expected EndElement, peek first which should have no side effect - assertTrue(EventHelper.endElementName(fragmentReader.nextEvent()).equals("fragment")); - // inserted EndDocument - assertTrue(fragmentReader.peek().isEndDocument()); - assertTrue(fragmentReader.nextEvent().isEndDocument()); - - // now the reader should behave like the document has finished - assertTrue(fragmentReader.peek() == null); - assertFalse(fragmentReader.hasNext()); - - try{ - fragmentReader.nextEvent(); - fail("nextEvent should simulate behavior as if document ended"); - } - catch (NoSuchElementException expected) { - //expected - } - - } - - /** - * When fragment is marked as processed the cursor is moved after the end of - * the fragment. - */ - public void testMarkFragmentProcessed() throws XMLStreamException { - moveCursorBeforeFragmentStart(); - - fragmentReader.markStartFragment(); // mark the fragment start - - // read only one event to move inside the fragment - XMLEvent startFragment = fragmentReader.nextEvent(); - assertTrue(startFragment.isStartDocument()); - fragmentReader.markFragmentProcessed(); // mark fragment as processed - - fragmentReader.nextEvent(); // skip whitespace - // the next element after fragment end is - XMLEvent misc2 = fragmentReader.nextEvent(); - assertTrue(EventHelper.startElementName(misc2).equals("misc2")); - } - - /** - * Cursor is moved to the end of the fragment as usually even - * if nothing was read from the event reader after beginning - * of fragment was marked. - */ - public void testMarkFragmentProcessedImmediatelyAfterMarkFragmentStart() throws Exception { - moveCursorBeforeFragmentStart(); - - fragmentReader.markStartFragment(); - fragmentReader.markFragmentProcessed(); - - fragmentReader.nextEvent(); // skip whitespace - // the next element after fragment end is - XMLEvent misc2 = fragmentReader.nextEvent(); - assertTrue(EventHelper.startElementName(misc2).equals("misc2")); - } - - - private void moveCursorToNextElementEvent() throws XMLStreamException { - XMLEvent event = eventReader.peek(); - while (!event.isStartElement() && !event.isEndElement()) { - eventReader.nextEvent(); - event = eventReader.peek(); - } - } - - private void moveCursorBeforeFragmentStart() throws XMLStreamException { - XMLEvent event = eventReader.peek(); - while (!event.isStartElement() || !EventHelper.startElementName(event).equals("fragment")) { - eventReader.nextEvent(); - event = eventReader.peek(); - } - } - -} +package org.springframework.batch.io.xml.stax; + +import java.util.NoSuchElementException; + +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.events.XMLEvent; + +import junit.framework.TestCase; + +import org.springframework.batch.io.xml.EventHelper; +import org.springframework.batch.io.xml.stax.DefaultFragmentEventReader; +import org.springframework.batch.io.xml.stax.DefaultTransactionalEventReader; +import org.springframework.core.io.ByteArrayResource; +import org.springframework.core.io.Resource; + +/** + * Tests for {@link DefaultFragmentEventReader}. + * + * @author Robert Kasanicky + */ +public class DefaultFragmentEventReaderTests extends TestCase { + + // object under test + private FragmentEventReader fragmentReader; + + // wrapped event fragmentReader + private XMLEventReader eventReader; + + // test xml input + private String xml = " "; + + /** + * Setup the fragmentReader to read the test input. + */ + protected void setUp() throws Exception { + Resource input = new ByteArrayResource(xml.getBytes()); + eventReader = new DefaultTransactionalEventReader(XMLInputFactory.newInstance().createXMLEventReader( + input.getInputStream())); + fragmentReader = new DefaultFragmentEventReader(eventReader); + } + + /** + * Marked element should be wrapped with StartDocument and EndDocument + * events. + * Test uses redundant peek() calls before nextEvent() in important moments to assure + * peek() has no side effects on the inner state of reader. + */ + public void testFragmentWrapping() throws XMLStreamException { + + assertTrue(fragmentReader.hasNext()); + moveCursorBeforeFragmentStart(); + + fragmentReader.markStartFragment(); // mark the fragment + assertTrue(EventHelper.startElementName(eventReader.peek()).equals("fragment")); + + // StartDocument inserted before StartElement + assertTrue(fragmentReader.peek().isStartDocument()); + assertTrue(fragmentReader.nextEvent().isStartDocument()); + // StartElement follows in the next step + assertTrue(EventHelper.startElementName(fragmentReader.nextEvent()).equals("fragment")); + + moveCursorToNextElementEvent(); // misc1 start + fragmentReader.nextEvent(); // skip it + moveCursorToNextElementEvent(); // misc1 end + fragmentReader.nextEvent(); // skip it + moveCursorToNextElementEvent(); // move to end of fragment + + // expected EndElement, peek first which should have no side effect + assertTrue(EventHelper.endElementName(fragmentReader.nextEvent()).equals("fragment")); + // inserted EndDocument + assertTrue(fragmentReader.peek().isEndDocument()); + assertTrue(fragmentReader.nextEvent().isEndDocument()); + + // now the reader should behave like the document has finished + assertTrue(fragmentReader.peek() == null); + assertFalse(fragmentReader.hasNext()); + + try{ + fragmentReader.nextEvent(); + fail("nextEvent should simulate behavior as if document ended"); + } + catch (NoSuchElementException expected) { + //expected + } + + } + + /** + * When fragment is marked as processed the cursor is moved after the end of + * the fragment. + */ + public void testMarkFragmentProcessed() throws XMLStreamException { + moveCursorBeforeFragmentStart(); + + fragmentReader.markStartFragment(); // mark the fragment start + + // read only one event to move inside the fragment + XMLEvent startFragment = fragmentReader.nextEvent(); + assertTrue(startFragment.isStartDocument()); + fragmentReader.markFragmentProcessed(); // mark fragment as processed + + fragmentReader.nextEvent(); // skip whitespace + // the next element after fragment end is + XMLEvent misc2 = fragmentReader.nextEvent(); + assertTrue(EventHelper.startElementName(misc2).equals("misc2")); + } + + /** + * Cursor is moved to the end of the fragment as usually even + * if nothing was read from the event reader after beginning + * of fragment was marked. + */ + public void testMarkFragmentProcessedImmediatelyAfterMarkFragmentStart() throws Exception { + moveCursorBeforeFragmentStart(); + + fragmentReader.markStartFragment(); + fragmentReader.markFragmentProcessed(); + + fragmentReader.nextEvent(); // skip whitespace + // the next element after fragment end is + XMLEvent misc2 = fragmentReader.nextEvent(); + assertTrue(EventHelper.startElementName(misc2).equals("misc2")); + } + + + private void moveCursorToNextElementEvent() throws XMLStreamException { + XMLEvent event = eventReader.peek(); + while (!event.isStartElement() && !event.isEndElement()) { + eventReader.nextEvent(); + event = eventReader.peek(); + } + } + + private void moveCursorBeforeFragmentStart() throws XMLStreamException { + XMLEvent event = eventReader.peek(); + while (!event.isStartElement() || !EventHelper.startElementName(event).equals("fragment")) { + eventReader.nextEvent(); + event = eventReader.peek(); + } + } + +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/xml/stax/DefaultTransactionalEventReaderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/xml/stax/DefaultTransactionalEventReaderTests.java index b42534844e..c178cc7ea4 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/xml/stax/DefaultTransactionalEventReaderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/xml/stax/DefaultTransactionalEventReaderTests.java @@ -1,68 +1,68 @@ -package org.springframework.batch.io.xml.stax; - -import javax.xml.stream.XMLEventReader; -import javax.xml.stream.XMLInputFactory; - -import junit.framework.TestCase; - -import org.springframework.batch.io.xml.EventHelper; -import org.springframework.batch.io.xml.stax.DefaultTransactionalEventReader; -import org.springframework.core.io.ByteArrayResource; -import org.springframework.core.io.Resource; - -/** - * Tests for {@link DefaultTransactionalEventReader}. - * - * @author Robert Kasanicky - */ -public class DefaultTransactionalEventReaderTests extends TestCase { - - // object under test - private TransactionalEventReader reader; - - // test xml input - private String xml = " "; - - - protected void setUp() throws Exception { - Resource resource = new ByteArrayResource(xml.getBytes()); - XMLEventReader wrappedReader = XMLInputFactory.newInstance().createXMLEventReader(resource.getInputStream()); - reader = new DefaultTransactionalEventReader(wrappedReader); - } - - /** - * Rollback scenario. - */ - public void testRollback() throws Exception { - assertTrue(reader.hasNext()); - reader.nextEvent(); //start document - reader.nextEvent(); //start root element - reader.nextEvent(); //whitespace - - reader.onCommit(); // commit point - - assertTrue(EventHelper.startElementName(reader.nextEvent()).equals("fragment")); - reader.nextEvent(); //whitespace - assertTrue(EventHelper.startElementName(reader.nextEvent()).equals("misc1")); - assertTrue(EventHelper.endElementName(reader.peek()).equals("misc1")); - - reader.onRollback(); // now we should be at the last commit point - assertTrue(reader.hasNext()); - assertTrue(EventHelper.startElementName(reader.nextEvent()).equals("fragment")); - reader.nextEvent(); - assertTrue(EventHelper.startElementName(reader.nextEvent()).equals("misc1")); - } - - /** - * Remove operation is not supported - */ - public void testRemove() { - try { - reader.remove(); - fail("UnsupportedOperationException expected on calling remove()"); - } - catch (UnsupportedOperationException e) { - // expected - } - } -} +package org.springframework.batch.io.xml.stax; + +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.XMLInputFactory; + +import junit.framework.TestCase; + +import org.springframework.batch.io.xml.EventHelper; +import org.springframework.batch.io.xml.stax.DefaultTransactionalEventReader; +import org.springframework.core.io.ByteArrayResource; +import org.springframework.core.io.Resource; + +/** + * Tests for {@link DefaultTransactionalEventReader}. + * + * @author Robert Kasanicky + */ +public class DefaultTransactionalEventReaderTests extends TestCase { + + // object under test + private TransactionalEventReader reader; + + // test xml input + private String xml = " "; + + + protected void setUp() throws Exception { + Resource resource = new ByteArrayResource(xml.getBytes()); + XMLEventReader wrappedReader = XMLInputFactory.newInstance().createXMLEventReader(resource.getInputStream()); + reader = new DefaultTransactionalEventReader(wrappedReader); + } + + /** + * Rollback scenario. + */ + public void testRollback() throws Exception { + assertTrue(reader.hasNext()); + reader.nextEvent(); //start document + reader.nextEvent(); //start root element + reader.nextEvent(); //whitespace + + reader.onCommit(); // commit point + + assertTrue(EventHelper.startElementName(reader.nextEvent()).equals("fragment")); + reader.nextEvent(); //whitespace + assertTrue(EventHelper.startElementName(reader.nextEvent()).equals("misc1")); + assertTrue(EventHelper.endElementName(reader.peek()).equals("misc1")); + + reader.onRollback(); // now we should be at the last commit point + assertTrue(reader.hasNext()); + assertTrue(EventHelper.startElementName(reader.nextEvent()).equals("fragment")); + reader.nextEvent(); + assertTrue(EventHelper.startElementName(reader.nextEvent()).equals("misc1")); + } + + /** + * Remove operation is not supported + */ + public void testRemove() { + try { + reader.remove(); + fail("UnsupportedOperationException expected on calling remove()"); + } + catch (UnsupportedOperationException e) { + // expected + } + } +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/xml/stax/EventSequenceTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/xml/stax/EventSequenceTests.java index eb29832b79..b7be0c56b3 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/xml/stax/EventSequenceTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/xml/stax/EventSequenceTests.java @@ -1,39 +1,39 @@ -package org.springframework.batch.io.xml.stax; - -import javax.xml.stream.XMLEventFactory; -import javax.xml.stream.events.XMLEvent; - -import org.springframework.batch.io.xml.stax.EventSequence; - -import junit.framework.TestCase; - -/** - * Tests for {@link EventSequence} - * - * @author Robert Kasanicky - */ -public class EventSequenceTests extends TestCase { - - // object under test - private EventSequence seq = new EventSequence(); - - private XMLEventFactory factory = XMLEventFactory.newInstance(); - - /** - * Common usage scenario. - */ - public void testCommonUse() { - XMLEvent event1 = factory.createComment("testString1"); - XMLEvent event2 = factory.createCData("testString2"); - seq.addEvent(event1); - seq.addEvent(event2); - - assertTrue(seq.hasNext()); - assertSame(event1, seq.nextEvent()); - assertTrue(seq.hasNext()); - assertSame(event2, seq.nextEvent()); - assertFalse(seq.hasNext()); - assertNull(seq.nextEvent()); - - } -} +package org.springframework.batch.io.xml.stax; + +import javax.xml.stream.XMLEventFactory; +import javax.xml.stream.events.XMLEvent; + +import org.springframework.batch.io.xml.stax.EventSequence; + +import junit.framework.TestCase; + +/** + * Tests for {@link EventSequence} + * + * @author Robert Kasanicky + */ +public class EventSequenceTests extends TestCase { + + // object under test + private EventSequence seq = new EventSequence(); + + private XMLEventFactory factory = XMLEventFactory.newInstance(); + + /** + * Common usage scenario. + */ + public void testCommonUse() { + XMLEvent event1 = factory.createComment("testString1"); + XMLEvent event2 = factory.createCData("testString2"); + seq.addEvent(event1); + seq.addEvent(event2); + + assertTrue(seq.hasNext()); + assertSame(event1, seq.nextEvent()); + assertTrue(seq.hasNext()); + assertSame(event2, seq.nextEvent()); + assertFalse(seq.hasNext()); + assertNull(seq.nextEvent()); + + } +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/xml/stax/NoStartEndDocumentWriterTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/xml/stax/NoStartEndDocumentWriterTests.java index b012e1f7c9..5b76396793 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/xml/stax/NoStartEndDocumentWriterTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/io/xml/stax/NoStartEndDocumentWriterTests.java @@ -1,51 +1,51 @@ -package org.springframework.batch.io.xml.stax; - -import javax.xml.stream.XMLEventFactory; -import javax.xml.stream.XMLEventWriter; -import javax.xml.stream.events.XMLEvent; - -import junit.framework.TestCase; - -import org.easymock.MockControl; -import org.springframework.batch.io.xml.stax.NoStartEndDocumentStreamWriter; - -/** - * Tests for {@link NoStartEndDocumentStreamWriter} - * - * @author Robert Kasanicky - */ -public class NoStartEndDocumentWriterTests extends TestCase { - - // object under test - private NoStartEndDocumentStreamWriter writer; - - private XMLEventWriter wrappedWriter; - private MockControl wrappedWriterControl = MockControl.createStrictControl(XMLEventWriter.class); - - private XMLEventFactory eventFactory = XMLEventFactory.newInstance(); - - - protected void setUp() throws Exception { - wrappedWriter = (XMLEventWriter) wrappedWriterControl.getMock(); - writer = new NoStartEndDocumentStreamWriter(wrappedWriter); - } - - - /** - * StartDocument and EndDocument events are not passed to the wrapped writer. - */ - public void testNoStartEnd() throws Exception { - XMLEvent event = eventFactory.createComment("testEvent"); - - //mock expects only a single event - wrappedWriter.add(event); - wrappedWriterControl.setVoidCallable(); - wrappedWriterControl.replay(); - - writer.add(eventFactory.createStartDocument()); - writer.add(event); - writer.add(eventFactory.createEndDocument()); - - wrappedWriterControl.verify(); - } -} +package org.springframework.batch.io.xml.stax; + +import javax.xml.stream.XMLEventFactory; +import javax.xml.stream.XMLEventWriter; +import javax.xml.stream.events.XMLEvent; + +import junit.framework.TestCase; + +import org.easymock.MockControl; +import org.springframework.batch.io.xml.stax.NoStartEndDocumentStreamWriter; + +/** + * Tests for {@link NoStartEndDocumentStreamWriter} + * + * @author Robert Kasanicky + */ +public class NoStartEndDocumentWriterTests extends TestCase { + + // object under test + private NoStartEndDocumentStreamWriter writer; + + private XMLEventWriter wrappedWriter; + private MockControl wrappedWriterControl = MockControl.createStrictControl(XMLEventWriter.class); + + private XMLEventFactory eventFactory = XMLEventFactory.newInstance(); + + + protected void setUp() throws Exception { + wrappedWriter = (XMLEventWriter) wrappedWriterControl.getMock(); + writer = new NoStartEndDocumentStreamWriter(wrappedWriter); + } + + + /** + * StartDocument and EndDocument events are not passed to the wrapped writer. + */ + public void testNoStartEnd() throws Exception { + XMLEvent event = eventFactory.createComment("testEvent"); + + //mock expects only a single event + wrappedWriter.add(event); + wrappedWriterControl.setVoidCallable(); + wrappedWriterControl.replay(); + + writer.add(eventFactory.createStartDocument()); + writer.add(event); + writer.add(eventFactory.createEndDocument()); + + wrappedWriterControl.verify(); + } +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/ExecutionContextUserSupportTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/ExecutionContextUserSupportTests.java index 213aa31c3e..5229fb98ad 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/ExecutionContextUserSupportTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/ExecutionContextUserSupportTests.java @@ -1,34 +1,34 @@ -package org.springframework.batch.item; - -import junit.framework.TestCase; - -/** - * Tests for {@link ExecutionContextUserSupport}. - */ -public class ExecutionContextUserSupportTests extends TestCase { - - ExecutionContextUserSupport tested = new ExecutionContextUserSupport(); - - /** - * Regular usage scenario - prepends the name (supposed to be unique) to - * argument. - */ - public void testGetKey() { - tested.setName("uniqueName"); - assertEquals("uniqueName.key", tested.getKey("key")); - } - - /** - * Exception scenario - name must not be empty. - */ - public void testGetKeyWithNoNameSet() { - tested.setName(""); - try { - tested.getKey("arbitrary string"); - fail(); - } - catch (IllegalArgumentException e) { - // expected - } - } -} +package org.springframework.batch.item; + +import junit.framework.TestCase; + +/** + * Tests for {@link ExecutionContextUserSupport}. + */ +public class ExecutionContextUserSupportTests extends TestCase { + + ExecutionContextUserSupport tested = new ExecutionContextUserSupport(); + + /** + * Regular usage scenario - prepends the name (supposed to be unique) to + * argument. + */ + public void testGetKey() { + tested.setName("uniqueName"); + assertEquals("uniqueName.key", tested.getKey("key")); + } + + /** + * Exception scenario - name must not be empty. + */ + public void testGetKeyWithNoNameSet() { + tested.setName(""); + try { + tested.getKey("arbitrary string"); + fail(); + } + catch (IllegalArgumentException e) { + // expected + } + } +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/reader/AggregateItemReaderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/reader/AggregateItemReaderTests.java index 0e44a1afe0..271521f39a 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/reader/AggregateItemReaderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/reader/AggregateItemReaderTests.java @@ -1,60 +1,60 @@ -package org.springframework.batch.item.reader; - -import java.util.Collection; -import java.util.Iterator; - -import junit.framework.TestCase; - -import org.easymock.MockControl; -import org.springframework.batch.item.ItemReader; -import org.springframework.batch.item.reader.AggregateItemReader; - -public class AggregateItemReaderTests extends TestCase { - - private MockControl inputControl; - private ItemReader input; - private AggregateItemReader provider; - - public void setUp() { - - //create mock for input - inputControl = MockControl.createControl(ItemReader.class); - input = (ItemReader) inputControl.getMock(); - - //create provider - provider = new AggregateItemReader(); - provider.setItemReader(input); - } - - public void testNext() throws Exception { - - //set-up mock input - input.read(); - inputControl.setReturnValue(AggregateItemReader.BEGIN_RECORD); - input.read(); - inputControl.setReturnValue("line",3); - input.read(); - inputControl.setReturnValue(AggregateItemReader.END_RECORD); - input.read(); - inputControl.setReturnValue(null); - inputControl.replay(); - - //read object - Object result = provider.read(); - - //it should be collection of 3 strings "line" - assertTrue(result instanceof Collection); - Collection lines = (Collection)result; - assertEquals(3, lines.size()); - - for (Iterator i = lines.iterator(); i.hasNext();) { - assertEquals("line", i.next()); - } - - //read object again - it should return null - assertNull(provider.read()); - - //verify method calls - inputControl.verify(); - } -} +package org.springframework.batch.item.reader; + +import java.util.Collection; +import java.util.Iterator; + +import junit.framework.TestCase; + +import org.easymock.MockControl; +import org.springframework.batch.item.ItemReader; +import org.springframework.batch.item.reader.AggregateItemReader; + +public class AggregateItemReaderTests extends TestCase { + + private MockControl inputControl; + private ItemReader input; + private AggregateItemReader provider; + + public void setUp() { + + //create mock for input + inputControl = MockControl.createControl(ItemReader.class); + input = (ItemReader) inputControl.getMock(); + + //create provider + provider = new AggregateItemReader(); + provider.setItemReader(input); + } + + public void testNext() throws Exception { + + //set-up mock input + input.read(); + inputControl.setReturnValue(AggregateItemReader.BEGIN_RECORD); + input.read(); + inputControl.setReturnValue("line",3); + input.read(); + inputControl.setReturnValue(AggregateItemReader.END_RECORD); + input.read(); + inputControl.setReturnValue(null); + inputControl.replay(); + + //read object + Object result = provider.read(); + + //it should be collection of 3 strings "line" + assertTrue(result instanceof Collection); + Collection lines = (Collection)result; + assertEquals(3, lines.size()); + + for (Iterator i = lines.iterator(); i.hasNext();) { + assertEquals("line", i.next()); + } + + //read object again - it should return null + assertNull(provider.read()); + + //verify method calls + inputControl.verify(); + } +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/reader/DelegatingItemReaderIntegrationTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/reader/DelegatingItemReaderIntegrationTests.java index d5ce025283..4d66596741 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/reader/DelegatingItemReaderIntegrationTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/reader/DelegatingItemReaderIntegrationTests.java @@ -1,52 +1,52 @@ -package org.springframework.batch.item.reader; - -import java.util.ArrayList; -import java.util.List; - -import org.springframework.batch.io.sample.domain.FooService; -import org.springframework.test.AbstractDependencyInjectionSpringContextTests; - -/** - * Tests for {@link ItemReaderAdapter}. - * - * @author Robert Kasanicky - */ -public class DelegatingItemReaderIntegrationTests extends AbstractDependencyInjectionSpringContextTests { - - private ItemReaderAdapter provider; - - private FooService fooService; - - protected String getConfigPath() { - return "delegating-item-provider.xml"; - } - - /** - * Regular usage scenario - items are retrieved from the service injected - * invoker points to. - */ - public void testNext() throws Exception { - List returnedItems = new ArrayList(); - Object item; - while ((item = provider.read()) != null) { - returnedItems.add(item); - } - - List input = fooService.getGeneratedFoos(); - assertEquals(input.size(), returnedItems.size()); - assertFalse(returnedItems.isEmpty()); - - for (int i = 0; i < input.size(); i++) { - assertSame(input.get(i), returnedItems.get(i)); - } - } - - public void setProvider(ItemReaderAdapter provider) { - this.provider = provider; - } - - public void setFooService(FooService fooService) { - this.fooService = fooService; - } - -} +package org.springframework.batch.item.reader; + +import java.util.ArrayList; +import java.util.List; + +import org.springframework.batch.io.sample.domain.FooService; +import org.springframework.test.AbstractDependencyInjectionSpringContextTests; + +/** + * Tests for {@link ItemReaderAdapter}. + * + * @author Robert Kasanicky + */ +public class DelegatingItemReaderIntegrationTests extends AbstractDependencyInjectionSpringContextTests { + + private ItemReaderAdapter provider; + + private FooService fooService; + + protected String getConfigPath() { + return "delegating-item-provider.xml"; + } + + /** + * Regular usage scenario - items are retrieved from the service injected + * invoker points to. + */ + public void testNext() throws Exception { + List returnedItems = new ArrayList(); + Object item; + while ((item = provider.read()) != null) { + returnedItems.add(item); + } + + List input = fooService.getGeneratedFoos(); + assertEquals(input.size(), returnedItems.size()); + assertFalse(returnedItems.isEmpty()); + + for (int i = 0; i < input.size(); i++) { + assertSame(input.get(i), returnedItems.get(i)); + } + } + + public void setProvider(ItemReaderAdapter provider) { + this.provider = provider; + } + + public void setFooService(FooService fooService) { + this.fooService = fooService; + } + +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/reader/DelegatingItemReaderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/reader/DelegatingItemReaderTests.java index 5361c57833..86b7c08d86 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/reader/DelegatingItemReaderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/reader/DelegatingItemReaderTests.java @@ -1,111 +1,111 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.batch.item.reader; - -import junit.framework.TestCase; - -import org.springframework.batch.io.Skippable; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.item.ItemReader; -import org.springframework.batch.item.ItemStream; - -/** - * Unit test for {@link DelegatingItemReader} - * - * @author Robert Kasanicky - */ -public class DelegatingItemReaderTests extends TestCase { - - // object under test - private DelegatingItemReader itemProvider = new DelegatingItemReader(); - - private ItemReader source; - - private ExecutionContext executionContext; - - // create input template and inject it to data provider - protected void setUp() throws Exception { - executionContext = new ExecutionContext(); - source = new MockItemReader(this, executionContext); - itemProvider.setItemReader(source); - } - - public void testAfterPropertiesSet() throws Exception { - // shouldn't throw an exception since the input source is set - itemProvider.afterPropertiesSet(); - } - - public void testNullItemReader() { - try { - itemProvider.setItemReader(null); - itemProvider.afterPropertiesSet(); - fail(); - } - catch (Exception ex) { - assertTrue(ex instanceof IllegalArgumentException); - } - } - - /** - * Uses input template to provide the domain object. - * @throws Exception - */ - public void testNext() throws Exception { - Object result = itemProvider.read(); - assertSame("domain object is provided by the input template", this, result); - } - - public void testSkip() throws Exception { - itemProvider.skip(); - assertEquals("after skip", itemProvider.read()); - } - - private static class MockItemReader extends AbstractItemReader implements ItemReader, ItemStream, Skippable { - - private Object value; - - public void update(ExecutionContext executionContext) { - executionContext.putString("value", "foo"); - } - - public MockItemReader(Object value, ExecutionContext executionContext) { - this.value = value; - } - - public Object read() { - return value; - } - - public void close(ExecutionContext executionContext) { - } - - public void open(ExecutionContext executionContext) { - } - - public void skip() { - value = "after skip"; - } - - public void mark() { - } - - public void reset() { - } - - } - -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.batch.item.reader; + +import junit.framework.TestCase; + +import org.springframework.batch.io.Skippable; +import org.springframework.batch.item.ExecutionContext; +import org.springframework.batch.item.ItemReader; +import org.springframework.batch.item.ItemStream; + +/** + * Unit test for {@link DelegatingItemReader} + * + * @author Robert Kasanicky + */ +public class DelegatingItemReaderTests extends TestCase { + + // object under test + private DelegatingItemReader itemProvider = new DelegatingItemReader(); + + private ItemReader source; + + private ExecutionContext executionContext; + + // create input template and inject it to data provider + protected void setUp() throws Exception { + executionContext = new ExecutionContext(); + source = new MockItemReader(this, executionContext); + itemProvider.setItemReader(source); + } + + public void testAfterPropertiesSet() throws Exception { + // shouldn't throw an exception since the input source is set + itemProvider.afterPropertiesSet(); + } + + public void testNullItemReader() { + try { + itemProvider.setItemReader(null); + itemProvider.afterPropertiesSet(); + fail(); + } + catch (Exception ex) { + assertTrue(ex instanceof IllegalArgumentException); + } + } + + /** + * Uses input template to provide the domain object. + * @throws Exception + */ + public void testNext() throws Exception { + Object result = itemProvider.read(); + assertSame("domain object is provided by the input template", this, result); + } + + public void testSkip() throws Exception { + itemProvider.skip(); + assertEquals("after skip", itemProvider.read()); + } + + private static class MockItemReader extends AbstractItemReader implements ItemReader, ItemStream, Skippable { + + private Object value; + + public void update(ExecutionContext executionContext) { + executionContext.putString("value", "foo"); + } + + public MockItemReader(Object value, ExecutionContext executionContext) { + this.value = value; + } + + public Object read() { + return value; + } + + public void close(ExecutionContext executionContext) { + } + + public void open(ExecutionContext executionContext) { + } + + public void skip() { + value = "after skip"; + } + + public void mark() { + } + + public void reset() { + } + + } + +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/reader/ValidatingItemReaderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/reader/ValidatingItemReaderTests.java index abc9f23b18..dfcc618cbc 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/reader/ValidatingItemReaderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/reader/ValidatingItemReaderTests.java @@ -1,116 +1,116 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.item.reader; - -import junit.framework.TestCase; - -import org.easymock.MockControl; -import org.springframework.batch.io.exception.ValidationException; -import org.springframework.batch.item.ItemReader; -import org.springframework.batch.item.reader.AbstractItemReader; -import org.springframework.batch.item.reader.ValidatingItemReader; -import org.springframework.batch.item.validator.Validator; - -/** - * @author Lucas Ward - * - */ -public class ValidatingItemReaderTests extends TestCase { - - ItemReader inputSource; - ValidatingItemReader itemProvider; - Validator validator; - MockControl validatorControl = MockControl.createControl(Validator.class); - - /* (non-Javadoc) - * @see junit.framework.TestCase#setUp() - */ - protected void setUp() throws Exception { - super.setUp(); - - inputSource = new MockItemReader(this); - validator = (Validator)validatorControl.getMock(); - itemProvider = new ValidatingItemReader(); - itemProvider.setItemReader(inputSource); - itemProvider.setValidator(validator); - } - - /* - * Super class' afterPropertieSet should be called to - * ensure ItemReader is set. - */ - public void testItemReaderPropertiesSet(){ - try{ - itemProvider.setItemReader(null); - itemProvider.afterPropertiesSet(); - fail(); - }catch(Exception ex){ - assertTrue(ex instanceof IllegalArgumentException); - } - } - - public void testValidatorPropertesSet(){ - try{ - itemProvider.setValidator(null); - itemProvider.afterPropertiesSet(); - fail(); - }catch(Exception ex){ - assertTrue(ex instanceof IllegalArgumentException); - } - } - - public void testValidation() throws Exception{ - - validator.validate(this); - validatorControl.replay(); - assertEquals(itemProvider.read(), this); - validatorControl.verify(); - } - - public void testValidationException() throws Exception{ - - validator.validate(this); - validatorControl.setThrowable(new ValidationException("")); - validatorControl.replay(); - try{ - itemProvider.read(); - fail(); - }catch(ValidationException ex){ - //expected - } - } - - public void testNullInput() throws Exception{ - validatorControl.replay(); - itemProvider.setItemReader(new MockItemReader(null)); - assertNull(itemProvider.read()); - //assert validator wasn't called. - validatorControl.verify(); - } - - private static class MockItemReader extends AbstractItemReader { - - Object value; - - public MockItemReader(Object value){ - this.value = value; - } - - public Object read() { - return value; - } - } -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.item.reader; + +import junit.framework.TestCase; + +import org.easymock.MockControl; +import org.springframework.batch.io.exception.ValidationException; +import org.springframework.batch.item.ItemReader; +import org.springframework.batch.item.reader.AbstractItemReader; +import org.springframework.batch.item.reader.ValidatingItemReader; +import org.springframework.batch.item.validator.Validator; + +/** + * @author Lucas Ward + * + */ +public class ValidatingItemReaderTests extends TestCase { + + ItemReader inputSource; + ValidatingItemReader itemProvider; + Validator validator; + MockControl validatorControl = MockControl.createControl(Validator.class); + + /* (non-Javadoc) + * @see junit.framework.TestCase#setUp() + */ + protected void setUp() throws Exception { + super.setUp(); + + inputSource = new MockItemReader(this); + validator = (Validator)validatorControl.getMock(); + itemProvider = new ValidatingItemReader(); + itemProvider.setItemReader(inputSource); + itemProvider.setValidator(validator); + } + + /* + * Super class' afterPropertieSet should be called to + * ensure ItemReader is set. + */ + public void testItemReaderPropertiesSet(){ + try{ + itemProvider.setItemReader(null); + itemProvider.afterPropertiesSet(); + fail(); + }catch(Exception ex){ + assertTrue(ex instanceof IllegalArgumentException); + } + } + + public void testValidatorPropertesSet(){ + try{ + itemProvider.setValidator(null); + itemProvider.afterPropertiesSet(); + fail(); + }catch(Exception ex){ + assertTrue(ex instanceof IllegalArgumentException); + } + } + + public void testValidation() throws Exception{ + + validator.validate(this); + validatorControl.replay(); + assertEquals(itemProvider.read(), this); + validatorControl.verify(); + } + + public void testValidationException() throws Exception{ + + validator.validate(this); + validatorControl.setThrowable(new ValidationException("")); + validatorControl.replay(); + try{ + itemProvider.read(); + fail(); + }catch(ValidationException ex){ + //expected + } + } + + public void testNullInput() throws Exception{ + validatorControl.replay(); + itemProvider.setItemReader(new MockItemReader(null)); + assertNull(itemProvider.read()); + //assert validator wasn't called. + validatorControl.verify(); + } + + private static class MockItemReader extends AbstractItemReader { + + Object value; + + public MockItemReader(Object value){ + this.value = value; + } + + public Object read() { + return value; + } + } +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/writer/CompositeItemTransformerTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/writer/CompositeItemTransformerTests.java index 1852fd7b7d..e45cfcfb7d 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/writer/CompositeItemTransformerTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/writer/CompositeItemTransformerTests.java @@ -1,97 +1,97 @@ -package org.springframework.batch.item.writer; - -import java.util.ArrayList; - -import junit.framework.TestCase; - -import org.easymock.MockControl; -import org.springframework.batch.item.writer.CompositeItemTransformer; -import org.springframework.batch.item.writer.ItemTransformer; - -/** - * Tests for {@link CompositeItemTransformer}. - * - * @author Robert Kasanicky - */ -public class CompositeItemTransformerTests extends TestCase { - - private CompositeItemTransformer composite = new CompositeItemTransformer(); - - private ItemTransformer transformer1; - private ItemTransformer transformer2; - - private MockControl tControl1 = MockControl.createControl(ItemTransformer.class); - private MockControl tControl2 = MockControl.createControl(ItemTransformer.class); - - protected void setUp() throws Exception { - transformer1 = (ItemTransformer) tControl1.getMock(); - transformer2 = (ItemTransformer) tControl2 .getMock(); - - composite.setItemTransformers(new ArrayList() {{ - add(transformer1); add(transformer2); - }}); - - composite.afterPropertiesSet(); - } - - /** - * Regular usage scenario - item is passed through the processing chain, - * return value of the of the last transformation is returned by the composite. - */ - public void testTransform() throws Exception { - Object item = new Object(); - Object itemAfterFirstTransfromation = new Object(); - Object itemAfterSecondTransformation = new Object(); - - transformer1.transform(item); - tControl1.setReturnValue(itemAfterFirstTransfromation); - - transformer2.transform(itemAfterFirstTransfromation); - tControl2.setReturnValue(itemAfterSecondTransformation); - - tControl1.replay(); - tControl2.replay(); - - assertSame(itemAfterSecondTransformation, composite.transform(item)); - - tControl1.verify(); - tControl2.verify(); - } - - /** - * The list of transformers must not be null or empty and - * can contain only instances of {@link ItemTransformer}. - */ - public void testAfterPropertiesSet() throws Exception { - - // value not set - composite.setItemTransformers(null); - try { - composite.afterPropertiesSet(); - fail(); - } - catch (IllegalArgumentException e) { - // expected - } - - // empty list - composite.setItemTransformers(new ArrayList()); - try { - composite.afterPropertiesSet(); - fail(); - } - catch (IllegalArgumentException e) { - // expected - } - - // invalid list member - composite.setItemTransformers(new ArrayList() {{ add(new Object()); }}); - try { - composite.afterPropertiesSet(); - fail(); - } - catch (IllegalArgumentException e) { - // expected - } - } -} +package org.springframework.batch.item.writer; + +import java.util.ArrayList; + +import junit.framework.TestCase; + +import org.easymock.MockControl; +import org.springframework.batch.item.writer.CompositeItemTransformer; +import org.springframework.batch.item.writer.ItemTransformer; + +/** + * Tests for {@link CompositeItemTransformer}. + * + * @author Robert Kasanicky + */ +public class CompositeItemTransformerTests extends TestCase { + + private CompositeItemTransformer composite = new CompositeItemTransformer(); + + private ItemTransformer transformer1; + private ItemTransformer transformer2; + + private MockControl tControl1 = MockControl.createControl(ItemTransformer.class); + private MockControl tControl2 = MockControl.createControl(ItemTransformer.class); + + protected void setUp() throws Exception { + transformer1 = (ItemTransformer) tControl1.getMock(); + transformer2 = (ItemTransformer) tControl2 .getMock(); + + composite.setItemTransformers(new ArrayList() {{ + add(transformer1); add(transformer2); + }}); + + composite.afterPropertiesSet(); + } + + /** + * Regular usage scenario - item is passed through the processing chain, + * return value of the of the last transformation is returned by the composite. + */ + public void testTransform() throws Exception { + Object item = new Object(); + Object itemAfterFirstTransfromation = new Object(); + Object itemAfterSecondTransformation = new Object(); + + transformer1.transform(item); + tControl1.setReturnValue(itemAfterFirstTransfromation); + + transformer2.transform(itemAfterFirstTransfromation); + tControl2.setReturnValue(itemAfterSecondTransformation); + + tControl1.replay(); + tControl2.replay(); + + assertSame(itemAfterSecondTransformation, composite.transform(item)); + + tControl1.verify(); + tControl2.verify(); + } + + /** + * The list of transformers must not be null or empty and + * can contain only instances of {@link ItemTransformer}. + */ + public void testAfterPropertiesSet() throws Exception { + + // value not set + composite.setItemTransformers(null); + try { + composite.afterPropertiesSet(); + fail(); + } + catch (IllegalArgumentException e) { + // expected + } + + // empty list + composite.setItemTransformers(new ArrayList()); + try { + composite.afterPropertiesSet(); + fail(); + } + catch (IllegalArgumentException e) { + // expected + } + + // invalid list member + composite.setItemTransformers(new ArrayList() {{ add(new Object()); }}); + try { + composite.afterPropertiesSet(); + fail(); + } + catch (IllegalArgumentException e) { + // expected + } + } +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/writer/CompositeItemWriterTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/writer/CompositeItemWriterTests.java index 2a0a95f191..fc153c0db7 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/writer/CompositeItemWriterTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/writer/CompositeItemWriterTests.java @@ -1,55 +1,55 @@ -package org.springframework.batch.item.writer; - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -import junit.framework.TestCase; - -import org.easymock.MockControl; -import org.springframework.batch.item.ItemWriter; - -/** - * Tests for {@link CompositeItemWriter} - * - * @author Robert Kasanicky - */ -public class CompositeItemWriterTests extends TestCase { - - // object under test - private CompositeItemWriter itemProcessor = new CompositeItemWriter(); - - /** - * Regular usage scenario. - * All injected processors should be called. - */ - public void testProcess() throws Exception { - - final int NUMBER_OF_PROCESSORS = 10; - Object data = new Object(); - - List controls = new ArrayList(NUMBER_OF_PROCESSORS); - List processors = new ArrayList(NUMBER_OF_PROCESSORS); - - for (int i = 0; i < NUMBER_OF_PROCESSORS; i++) { - MockControl control = MockControl.createStrictControl(ItemWriter.class); - ItemWriter processor = (ItemWriter) control.getMock(); - - processor.write(data); - control.setVoidCallable(); - control.replay(); - - processors.add(processor); - controls.add(control); - } - - itemProcessor.setDelegates(processors); - itemProcessor.write(data); - - for (Iterator iterator = controls.iterator(); iterator.hasNext();) { - MockControl control = (MockControl) iterator.next(); - control.verify(); - } - } - -} +package org.springframework.batch.item.writer; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import junit.framework.TestCase; + +import org.easymock.MockControl; +import org.springframework.batch.item.ItemWriter; + +/** + * Tests for {@link CompositeItemWriter} + * + * @author Robert Kasanicky + */ +public class CompositeItemWriterTests extends TestCase { + + // object under test + private CompositeItemWriter itemProcessor = new CompositeItemWriter(); + + /** + * Regular usage scenario. + * All injected processors should be called. + */ + public void testProcess() throws Exception { + + final int NUMBER_OF_PROCESSORS = 10; + Object data = new Object(); + + List controls = new ArrayList(NUMBER_OF_PROCESSORS); + List processors = new ArrayList(NUMBER_OF_PROCESSORS); + + for (int i = 0; i < NUMBER_OF_PROCESSORS; i++) { + MockControl control = MockControl.createStrictControl(ItemWriter.class); + ItemWriter processor = (ItemWriter) control.getMock(); + + processor.write(data); + control.setVoidCallable(); + control.replay(); + + processors.add(processor); + controls.add(control); + } + + itemProcessor.setDelegates(processors); + itemProcessor.write(data); + + for (Iterator iterator = controls.iterator(); iterator.hasNext();) { + MockControl control = (MockControl) iterator.next(); + control.verify(); + } + } + +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/writer/ItemTransformerItemWriterTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/writer/ItemTransformerItemWriterTests.java index 3edc3c14f4..0a883e647b 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/writer/ItemTransformerItemWriterTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/writer/ItemTransformerItemWriterTests.java @@ -1,72 +1,72 @@ -package org.springframework.batch.item.writer; - -import junit.framework.TestCase; - -import org.easymock.MockControl; -import org.springframework.batch.item.ItemWriter; -import org.springframework.batch.item.writer.ItemTransformer; -import org.springframework.batch.item.writer.ItemTransformerItemWriter; - -/** - * Tests for {@link ItemTransformerItemWriter}. - * - * @author Robert Kasanicky - */ -public class ItemTransformerItemWriterTests extends TestCase { - - private ItemTransformerItemWriter processor = new ItemTransformerItemWriter(); - - private ItemTransformer transformer; - private ItemWriter itemWriter; - - private MockControl tControl = MockControl.createControl(ItemTransformer.class); - private MockControl outControl = MockControl.createControl(ItemWriter.class); - - protected void setUp() throws Exception { - transformer = (ItemTransformer) tControl.getMock(); - itemWriter = (ItemWriter) outControl.getMock(); - - processor.setItemTransformer(transformer); - processor.setDelegate(itemWriter); - processor.afterPropertiesSet(); - } - - /** - * Regular usage scenario - item is passed to transformer - * and the result of transformation is passed to output source. - */ - public void testProcess() throws Exception { - Object item = new Object(); - Object itemAfterTransformation = new Object(); - - transformer.transform(item); - tControl.setReturnValue(itemAfterTransformation); - - itemWriter.write(itemAfterTransformation); - outControl.setVoidCallable(); - - tControl.replay(); - outControl.replay(); - - processor.write(item); - - tControl.verify(); - outControl.verify(); - } - - /** - * Item transformer must be set. - */ - public void testAfterPropertiesSet() throws Exception { - - // value not set - processor.setItemTransformer(null); - try { - processor.afterPropertiesSet(); - fail(); - } - catch (IllegalArgumentException e) { - // expected - } - } -} +package org.springframework.batch.item.writer; + +import junit.framework.TestCase; + +import org.easymock.MockControl; +import org.springframework.batch.item.ItemWriter; +import org.springframework.batch.item.writer.ItemTransformer; +import org.springframework.batch.item.writer.ItemTransformerItemWriter; + +/** + * Tests for {@link ItemTransformerItemWriter}. + * + * @author Robert Kasanicky + */ +public class ItemTransformerItemWriterTests extends TestCase { + + private ItemTransformerItemWriter processor = new ItemTransformerItemWriter(); + + private ItemTransformer transformer; + private ItemWriter itemWriter; + + private MockControl tControl = MockControl.createControl(ItemTransformer.class); + private MockControl outControl = MockControl.createControl(ItemWriter.class); + + protected void setUp() throws Exception { + transformer = (ItemTransformer) tControl.getMock(); + itemWriter = (ItemWriter) outControl.getMock(); + + processor.setItemTransformer(transformer); + processor.setDelegate(itemWriter); + processor.afterPropertiesSet(); + } + + /** + * Regular usage scenario - item is passed to transformer + * and the result of transformation is passed to output source. + */ + public void testProcess() throws Exception { + Object item = new Object(); + Object itemAfterTransformation = new Object(); + + transformer.transform(item); + tControl.setReturnValue(itemAfterTransformation); + + itemWriter.write(itemAfterTransformation); + outControl.setVoidCallable(); + + tControl.replay(); + outControl.replay(); + + processor.write(item); + + tControl.verify(); + outControl.verify(); + } + + /** + * Item transformer must be set. + */ + public void testAfterPropertiesSet() throws Exception { + + // value not set + processor.setItemTransformer(null); + try { + processor.afterPropertiesSet(); + fail(); + } + catch (IllegalArgumentException e) { + // expected + } + } +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/writer/ItemWriterAdapterTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/writer/ItemWriterAdapterTests.java index 76fafac7a9..dda6031eb2 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/writer/ItemWriterAdapterTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/writer/ItemWriterAdapterTests.java @@ -1,56 +1,56 @@ -package org.springframework.batch.item.writer; - -import java.util.List; - -import org.springframework.batch.io.sample.domain.Foo; -import org.springframework.batch.io.sample.domain.FooService; -import org.springframework.batch.item.ItemWriter; -import org.springframework.test.AbstractDependencyInjectionSpringContextTests; - -/** - * Tests for {@link ItemWriterAdapter}. - * - * @author Robert Kasanicky - */ -public class ItemWriterAdapterTests extends AbstractDependencyInjectionSpringContextTests { - - private ItemWriter processor; - - private FooService fooService; - - - protected String getConfigPath() { - return "delegating-item-writer.xml"; - } - - /** - * Regular usage scenario - input object should be passed to - * the service the injected invoker points to. - */ - public void testProcess() throws Exception { - Foo foo; - while ((foo = fooService.generateFoo()) != null) { - processor.write(foo); - } - - List input = fooService.getGeneratedFoos(); - List processed = fooService.getProcessedFoos(); - assertEquals(input.size(), processed.size()); - assertFalse(fooService.getProcessedFoos().isEmpty()); - - for (int i = 0; i < input.size(); i++) { - assertSame(input.get(i), processed.get(i)); - } - - } - - //setter for auto-injection - public void setProcessor(ItemWriter processor) { - this.processor = processor; - } - - //setter for auto-injection - public void setFooService(FooService fooService) { - this.fooService = fooService; - } -} +package org.springframework.batch.item.writer; + +import java.util.List; + +import org.springframework.batch.io.sample.domain.Foo; +import org.springframework.batch.io.sample.domain.FooService; +import org.springframework.batch.item.ItemWriter; +import org.springframework.test.AbstractDependencyInjectionSpringContextTests; + +/** + * Tests for {@link ItemWriterAdapter}. + * + * @author Robert Kasanicky + */ +public class ItemWriterAdapterTests extends AbstractDependencyInjectionSpringContextTests { + + private ItemWriter processor; + + private FooService fooService; + + + protected String getConfigPath() { + return "delegating-item-writer.xml"; + } + + /** + * Regular usage scenario - input object should be passed to + * the service the injected invoker points to. + */ + public void testProcess() throws Exception { + Foo foo; + while ((foo = fooService.generateFoo()) != null) { + processor.write(foo); + } + + List input = fooService.getGeneratedFoos(); + List processed = fooService.getProcessedFoos(); + assertEquals(input.size(), processed.size()); + assertFalse(fooService.getProcessedFoos().isEmpty()); + + for (int i = 0; i < input.size(); i++) { + assertSame(input.get(i), processed.get(i)); + } + + } + + //setter for auto-injection + public void setProcessor(ItemWriter processor) { + this.processor = processor; + } + + //setter for auto-injection + public void setFooService(FooService fooService) { + this.fooService = fooService; + } +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/writer/PropertyExtractingDelegatingItemProccessorIntegrationTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/writer/PropertyExtractingDelegatingItemProccessorIntegrationTests.java index 42aad4b870..91fb5568c9 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/writer/PropertyExtractingDelegatingItemProccessorIntegrationTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/writer/PropertyExtractingDelegatingItemProccessorIntegrationTests.java @@ -1,59 +1,59 @@ -package org.springframework.batch.item.writer; - -import java.util.List; - -import org.springframework.batch.io.sample.domain.Foo; -import org.springframework.batch.io.sample.domain.FooService; -import org.springframework.batch.item.writer.PropertyExtractingDelegatingItemWriter; -import org.springframework.test.AbstractDependencyInjectionSpringContextTests; - -/** - * Tests for {@link PropertyExtractingDelegatingItemWriter} - * - * @author Robert Kasanicky - */ -public class PropertyExtractingDelegatingItemProccessorIntegrationTests - extends AbstractDependencyInjectionSpringContextTests { - - private PropertyExtractingDelegatingItemWriter processor; - - private FooService fooService; - - protected String getConfigPath() { - return "pe-delegating-item-writer.xml"; - } - - /** - * Regular usage scenario - input object should be passed to - * the service the injected invoker points to. - */ - public void testProcess() throws Exception { - Foo foo; - while ((foo = fooService.generateFoo()) != null) { - processor.write(foo); - } - - List input = fooService.getGeneratedFoos(); - List processed = fooService.getProcessedFooNameValuePairs(); - assertEquals(input.size(), processed.size()); - assertFalse(fooService.getProcessedFooNameValuePairs().isEmpty()); - - for (int i = 0; i < input.size(); i++) { - Foo inputFoo = (Foo) input.get(i); - Foo outputFoo = (Foo) processed.get(i); - assertEquals(inputFoo.getName(), outputFoo.getName()); - assertEquals(inputFoo.getValue(), outputFoo.getValue()); - assertEquals(0, outputFoo.getId()); - } - - } - - public void setProcessor(PropertyExtractingDelegatingItemWriter processor) { - this.processor = processor; - } - - public void setFooService(FooService fooService) { - this.fooService = fooService; - } - -} +package org.springframework.batch.item.writer; + +import java.util.List; + +import org.springframework.batch.io.sample.domain.Foo; +import org.springframework.batch.io.sample.domain.FooService; +import org.springframework.batch.item.writer.PropertyExtractingDelegatingItemWriter; +import org.springframework.test.AbstractDependencyInjectionSpringContextTests; + +/** + * Tests for {@link PropertyExtractingDelegatingItemWriter} + * + * @author Robert Kasanicky + */ +public class PropertyExtractingDelegatingItemProccessorIntegrationTests + extends AbstractDependencyInjectionSpringContextTests { + + private PropertyExtractingDelegatingItemWriter processor; + + private FooService fooService; + + protected String getConfigPath() { + return "pe-delegating-item-writer.xml"; + } + + /** + * Regular usage scenario - input object should be passed to + * the service the injected invoker points to. + */ + public void testProcess() throws Exception { + Foo foo; + while ((foo = fooService.generateFoo()) != null) { + processor.write(foo); + } + + List input = fooService.getGeneratedFoos(); + List processed = fooService.getProcessedFooNameValuePairs(); + assertEquals(input.size(), processed.size()); + assertFalse(fooService.getProcessedFooNameValuePairs().isEmpty()); + + for (int i = 0; i < input.size(); i++) { + Foo inputFoo = (Foo) input.get(i); + Foo outputFoo = (Foo) processed.get(i); + assertEquals(inputFoo.getName(), outputFoo.getName()); + assertEquals(inputFoo.getValue(), outputFoo.getValue()); + assertEquals(0, outputFoo.getId()); + } + + } + + public void setProcessor(PropertyExtractingDelegatingItemWriter processor) { + this.processor = processor; + } + + public void setFooService(FooService fooService) { + this.fooService = fooService; + } + +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/ExitStatusTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/ExitStatusTests.java index 21ccc969f9..b9df674486 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/ExitStatusTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/ExitStatusTests.java @@ -1,210 +1,210 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.repeat; - -import org.apache.commons.lang.SerializationUtils; - -import junit.framework.TestCase; - -/** - * @author Dave Syer - * - */ -public class ExitStatusTests extends TestCase { - - /** - * Test method for - * {@link org.springframework.batch.repeat.ExitStatus#ExitStatus(boolean, int)}. - */ - public void testExitStatusBooleanInt() { - ExitStatus status = new ExitStatus(true, "10"); - assertTrue(status.isContinuable()); - assertEquals("10", status.getExitCode()); - } - - /** - * Test method for - * {@link org.springframework.batch.repeat.ExitStatus#ExitStatus(boolean, int)}. - */ - public void testExitStatusConstantsContinuable() { - ExitStatus status = ExitStatus.CONTINUABLE; - assertTrue(status.isContinuable()); - assertEquals("CONTINUABLE", status.getExitCode()); - } - - /** - * Test method for - * {@link org.springframework.batch.repeat.ExitStatus#ExitStatus(boolean, int)}. - */ - public void testExitStatusConstantsFinished() { - ExitStatus status = ExitStatus.FINISHED; - assertFalse(status.isContinuable()); - assertEquals("COMPLETED", status.getExitCode()); - } - - /** - * Test equality of exit statuses. - * - * @throws Exception - */ - public void testEqualsWithSameProperties() throws Exception { - assertEquals(ExitStatus.CONTINUABLE, new ExitStatus(true, "CONTINUABLE")); - } - - public void testEqualsSelf() { - ExitStatus status = new ExitStatus(true, "test"); - assertEquals(status, status); - } - - public void testEquals() { - assertEquals(new ExitStatus(true, "test"), new ExitStatus(true, "test")); - } - - /** - * Test equality of exit statuses. - * - * @throws Exception - */ - public void testEqualsWithNull() throws Exception { - assertFalse(ExitStatus.CONTINUABLE.equals(null)); - } - - /** - * Test equality of exit statuses. - * - * @throws Exception - */ - public void testHashcode() throws Exception { - assertEquals(ExitStatus.CONTINUABLE.toString().hashCode(), ExitStatus.CONTINUABLE.hashCode()); - } - - /** - * Test method for - * {@link org.springframework.batch.repeat.ExitStatus#and(boolean)}. - */ - public void testAndBoolean() { - assertTrue(ExitStatus.CONTINUABLE.and(true).isContinuable()); - assertFalse(ExitStatus.CONTINUABLE.and(false).isContinuable()); - ExitStatus status = new ExitStatus(false, "CUSTOM_CODE", "CUSTOM_DESCRIPTION"); - assertTrue(status.and(true).getExitCode() == "CUSTOM_CODE"); - assertTrue(status.and(true).getExitDescription() == "CUSTOM_DESCRIPTION"); - } - - /** - * Test method for - * {@link org.springframework.batch.repeat.ExitStatus#and(org.springframework.batch.repeat.ExitStatus)}. - */ - public void testAndExitStatusStillContinuable() { - assertTrue(ExitStatus.CONTINUABLE.and(ExitStatus.CONTINUABLE).isContinuable()); - assertFalse(ExitStatus.CONTINUABLE.and(ExitStatus.FINISHED).isContinuable()); - assertTrue(ExitStatus.CONTINUABLE.and(ExitStatus.CONTINUABLE).getExitCode() == ExitStatus.CONTINUABLE - .getExitCode()); - } - - /** - * Test method for - * {@link org.springframework.batch.repeat.ExitStatus#and(org.springframework.batch.repeat.ExitStatus)}. - */ - public void testAndExitStatusWhenFinishedAddedToContinuable() { - assertEquals(ExitStatus.FINISHED.getExitCode(), ExitStatus.CONTINUABLE.and(ExitStatus.FINISHED).getExitCode()); - } - - /** - * Test method for - * {@link org.springframework.batch.repeat.ExitStatus#and(org.springframework.batch.repeat.ExitStatus)}. - */ - public void testAndExitStatusWhenContinuableAddedToFinished() { - assertEquals(ExitStatus.FINISHED.getExitCode(), ExitStatus.FINISHED.and(ExitStatus.CONTINUABLE).getExitCode()); - } - - /** - * Test method for - * {@link org.springframework.batch.repeat.ExitStatus#and(org.springframework.batch.repeat.ExitStatus)}. - */ - public void testAndExitStatusWhenCustomContinuableAddedToContinuable() { - assertEquals("CUSTOM", ExitStatus.CONTINUABLE.and(ExitStatus.CONTINUABLE.replaceExitCode("CUSTOM")) - .getExitCode()); - } - - /** - * Test method for - * {@link org.springframework.batch.repeat.ExitStatus#and(org.springframework.batch.repeat.ExitStatus)}. - */ - public void testAndExitStatusWhenCustomContinuableAddedToFinished() { - assertEquals(ExitStatus.FINISHED.getExitCode(), ExitStatus.FINISHED.and(ExitStatus.CONTINUABLE.replaceExitCode("CUSTOM")) - .getExitCode()); - } - - public void testAddExitCode() throws Exception { - ExitStatus status = ExitStatus.CONTINUABLE.replaceExitCode("FOO"); - assertTrue(ExitStatus.CONTINUABLE != status); - assertTrue(status.isContinuable()); - assertEquals("FOO", status.getExitCode()); - } - - public void testAddExitCodeToExistingStatus() throws Exception { - ExitStatus status = ExitStatus.CONTINUABLE.replaceExitCode("FOO").replaceExitCode("BAR"); - assertTrue(ExitStatus.CONTINUABLE != status); - assertTrue(status.isContinuable()); - assertEquals("BAR", status.getExitCode()); - } - - public void testAddExitCodeToSameStatus() throws Exception { - ExitStatus status = ExitStatus.CONTINUABLE.replaceExitCode(ExitStatus.CONTINUABLE.getExitCode()); - assertTrue(ExitStatus.CONTINUABLE != status); - assertTrue(status.isContinuable()); - assertEquals(ExitStatus.CONTINUABLE.getExitCode(), status.getExitCode()); - } - - public void testAddExitDescription() throws Exception { - ExitStatus status = ExitStatus.CONTINUABLE.addExitDescription("Foo"); - assertTrue(ExitStatus.CONTINUABLE != status); - assertTrue(status.isContinuable()); - assertEquals("Foo", status.getExitDescription()); - } - - public void testAddExitDescriptionToSameStatus() throws Exception { - ExitStatus status = ExitStatus.CONTINUABLE.addExitDescription("Foo").addExitDescription("Foo"); - assertTrue(ExitStatus.CONTINUABLE != status); - assertTrue(status.isContinuable()); - assertEquals("Foo", status.getExitDescription()); - } - - public void testAddExitCodeWithDescription() throws Exception { - ExitStatus status = new ExitStatus(true, "BAR", "Bar").replaceExitCode("FOO"); - assertEquals("FOO", status.getExitCode()); - assertEquals("Bar", status.getExitDescription()); - } - - public void testRunningIsRunning() throws Exception { - assertTrue(ExitStatus.RUNNING.isRunning()); - assertTrue(new ExitStatus(true, "RUNNING").isRunning()); - } - - public void testUnkownIsRunning() throws Exception { - assertTrue(ExitStatus.UNKNOWN.isRunning()); - } - - public void testSerializable() throws Exception { - ExitStatus status = ExitStatus.CONTINUABLE.replaceExitCode("FOO"); - byte[] bytes = SerializationUtils.serialize(status); - Object object = SerializationUtils.deserialize(bytes); - assertTrue(object instanceof ExitStatus); - ExitStatus restored = (ExitStatus) object; - assertTrue(restored.isContinuable()); - assertEquals(status.getExitCode(), restored.getExitCode()); - } -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.repeat; + +import org.apache.commons.lang.SerializationUtils; + +import junit.framework.TestCase; + +/** + * @author Dave Syer + * + */ +public class ExitStatusTests extends TestCase { + + /** + * Test method for + * {@link org.springframework.batch.repeat.ExitStatus#ExitStatus(boolean, int)}. + */ + public void testExitStatusBooleanInt() { + ExitStatus status = new ExitStatus(true, "10"); + assertTrue(status.isContinuable()); + assertEquals("10", status.getExitCode()); + } + + /** + * Test method for + * {@link org.springframework.batch.repeat.ExitStatus#ExitStatus(boolean, int)}. + */ + public void testExitStatusConstantsContinuable() { + ExitStatus status = ExitStatus.CONTINUABLE; + assertTrue(status.isContinuable()); + assertEquals("CONTINUABLE", status.getExitCode()); + } + + /** + * Test method for + * {@link org.springframework.batch.repeat.ExitStatus#ExitStatus(boolean, int)}. + */ + public void testExitStatusConstantsFinished() { + ExitStatus status = ExitStatus.FINISHED; + assertFalse(status.isContinuable()); + assertEquals("COMPLETED", status.getExitCode()); + } + + /** + * Test equality of exit statuses. + * + * @throws Exception + */ + public void testEqualsWithSameProperties() throws Exception { + assertEquals(ExitStatus.CONTINUABLE, new ExitStatus(true, "CONTINUABLE")); + } + + public void testEqualsSelf() { + ExitStatus status = new ExitStatus(true, "test"); + assertEquals(status, status); + } + + public void testEquals() { + assertEquals(new ExitStatus(true, "test"), new ExitStatus(true, "test")); + } + + /** + * Test equality of exit statuses. + * + * @throws Exception + */ + public void testEqualsWithNull() throws Exception { + assertFalse(ExitStatus.CONTINUABLE.equals(null)); + } + + /** + * Test equality of exit statuses. + * + * @throws Exception + */ + public void testHashcode() throws Exception { + assertEquals(ExitStatus.CONTINUABLE.toString().hashCode(), ExitStatus.CONTINUABLE.hashCode()); + } + + /** + * Test method for + * {@link org.springframework.batch.repeat.ExitStatus#and(boolean)}. + */ + public void testAndBoolean() { + assertTrue(ExitStatus.CONTINUABLE.and(true).isContinuable()); + assertFalse(ExitStatus.CONTINUABLE.and(false).isContinuable()); + ExitStatus status = new ExitStatus(false, "CUSTOM_CODE", "CUSTOM_DESCRIPTION"); + assertTrue(status.and(true).getExitCode() == "CUSTOM_CODE"); + assertTrue(status.and(true).getExitDescription() == "CUSTOM_DESCRIPTION"); + } + + /** + * Test method for + * {@link org.springframework.batch.repeat.ExitStatus#and(org.springframework.batch.repeat.ExitStatus)}. + */ + public void testAndExitStatusStillContinuable() { + assertTrue(ExitStatus.CONTINUABLE.and(ExitStatus.CONTINUABLE).isContinuable()); + assertFalse(ExitStatus.CONTINUABLE.and(ExitStatus.FINISHED).isContinuable()); + assertTrue(ExitStatus.CONTINUABLE.and(ExitStatus.CONTINUABLE).getExitCode() == ExitStatus.CONTINUABLE + .getExitCode()); + } + + /** + * Test method for + * {@link org.springframework.batch.repeat.ExitStatus#and(org.springframework.batch.repeat.ExitStatus)}. + */ + public void testAndExitStatusWhenFinishedAddedToContinuable() { + assertEquals(ExitStatus.FINISHED.getExitCode(), ExitStatus.CONTINUABLE.and(ExitStatus.FINISHED).getExitCode()); + } + + /** + * Test method for + * {@link org.springframework.batch.repeat.ExitStatus#and(org.springframework.batch.repeat.ExitStatus)}. + */ + public void testAndExitStatusWhenContinuableAddedToFinished() { + assertEquals(ExitStatus.FINISHED.getExitCode(), ExitStatus.FINISHED.and(ExitStatus.CONTINUABLE).getExitCode()); + } + + /** + * Test method for + * {@link org.springframework.batch.repeat.ExitStatus#and(org.springframework.batch.repeat.ExitStatus)}. + */ + public void testAndExitStatusWhenCustomContinuableAddedToContinuable() { + assertEquals("CUSTOM", ExitStatus.CONTINUABLE.and(ExitStatus.CONTINUABLE.replaceExitCode("CUSTOM")) + .getExitCode()); + } + + /** + * Test method for + * {@link org.springframework.batch.repeat.ExitStatus#and(org.springframework.batch.repeat.ExitStatus)}. + */ + public void testAndExitStatusWhenCustomContinuableAddedToFinished() { + assertEquals(ExitStatus.FINISHED.getExitCode(), ExitStatus.FINISHED.and(ExitStatus.CONTINUABLE.replaceExitCode("CUSTOM")) + .getExitCode()); + } + + public void testAddExitCode() throws Exception { + ExitStatus status = ExitStatus.CONTINUABLE.replaceExitCode("FOO"); + assertTrue(ExitStatus.CONTINUABLE != status); + assertTrue(status.isContinuable()); + assertEquals("FOO", status.getExitCode()); + } + + public void testAddExitCodeToExistingStatus() throws Exception { + ExitStatus status = ExitStatus.CONTINUABLE.replaceExitCode("FOO").replaceExitCode("BAR"); + assertTrue(ExitStatus.CONTINUABLE != status); + assertTrue(status.isContinuable()); + assertEquals("BAR", status.getExitCode()); + } + + public void testAddExitCodeToSameStatus() throws Exception { + ExitStatus status = ExitStatus.CONTINUABLE.replaceExitCode(ExitStatus.CONTINUABLE.getExitCode()); + assertTrue(ExitStatus.CONTINUABLE != status); + assertTrue(status.isContinuable()); + assertEquals(ExitStatus.CONTINUABLE.getExitCode(), status.getExitCode()); + } + + public void testAddExitDescription() throws Exception { + ExitStatus status = ExitStatus.CONTINUABLE.addExitDescription("Foo"); + assertTrue(ExitStatus.CONTINUABLE != status); + assertTrue(status.isContinuable()); + assertEquals("Foo", status.getExitDescription()); + } + + public void testAddExitDescriptionToSameStatus() throws Exception { + ExitStatus status = ExitStatus.CONTINUABLE.addExitDescription("Foo").addExitDescription("Foo"); + assertTrue(ExitStatus.CONTINUABLE != status); + assertTrue(status.isContinuable()); + assertEquals("Foo", status.getExitDescription()); + } + + public void testAddExitCodeWithDescription() throws Exception { + ExitStatus status = new ExitStatus(true, "BAR", "Bar").replaceExitCode("FOO"); + assertEquals("FOO", status.getExitCode()); + assertEquals("Bar", status.getExitDescription()); + } + + public void testRunningIsRunning() throws Exception { + assertTrue(ExitStatus.RUNNING.isRunning()); + assertTrue(new ExitStatus(true, "RUNNING").isRunning()); + } + + public void testUnkownIsRunning() throws Exception { + assertTrue(ExitStatus.UNKNOWN.isRunning()); + } + + public void testSerializable() throws Exception { + ExitStatus status = ExitStatus.CONTINUABLE.replaceExitCode("FOO"); + byte[] bytes = SerializationUtils.serialize(status); + Object object = SerializationUtils.deserialize(bytes); + assertTrue(object instanceof ExitStatus); + ExitStatus restored = (ExitStatus) object; + assertTrue(restored.isContinuable()); + assertEquals(status.getExitCode(), restored.getExitCode()); + } +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/context/RepeatContextSupportTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/context/RepeatContextSupportTests.java index dced65425e..c9dca170e8 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/context/RepeatContextSupportTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/repeat/context/RepeatContextSupportTests.java @@ -1,93 +1,93 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.repeat.context; - -import java.util.ArrayList; -import java.util.List; - -import junit.framework.TestCase; - -/** - * @author dsyer - * - */ -public class RepeatContextSupportTests extends TestCase { - - private List list = new ArrayList(); - - /** - * Test method for {@link org.springframework.batch.repeat.context.RepeatContextSupport#registerDestructionCallback(java.lang.String, java.lang.Runnable)}. - */ - public void testDestructionCallbackSunnyDay() throws Exception { - RepeatContextSupport context = new RepeatContextSupport(null); - context.setAttribute("foo", "FOO"); - context.registerDestructionCallback("foo", new Runnable() { - public void run() { - list.add("bar"); - } - }); - context.close(); - assertEquals(1, list.size()); - assertEquals("bar", list.get(0)); - } - - /** - * Test method for {@link org.springframework.batch.repeat.context.RepeatContextSupport#registerDestructionCallback(java.lang.String, java.lang.Runnable)}. - */ - public void testDestructionCallbackMissingAttribute() throws Exception { - RepeatContextSupport context = new RepeatContextSupport(null); - context.registerDestructionCallback("foo", new Runnable() { - public void run() { - list.add("bar"); - } - }); - context.close(); - // No check for the attribute before executing callback - assertEquals(1, list.size()); - } - - /** - * Test method for {@link org.springframework.batch.repeat.context.RepeatContextSupport#registerDestructionCallback(java.lang.String, java.lang.Runnable)}. - */ - public void testDestructionCallbackWithException() throws Exception { - RepeatContextSupport context = new RepeatContextSupport(null); - context.setAttribute("foo", "FOO"); - context.setAttribute("bar", "BAR"); - context.registerDestructionCallback("bar", new Runnable() { - public void run() { - list.add("spam"); - throw new RuntimeException("fail!"); - } - }); - context.registerDestructionCallback("foo", new Runnable() { - public void run() { - list.add("bar"); - throw new RuntimeException("fail!"); - } - }); - try { - context.close(); - fail("Expected RuntimeException"); - } catch (RuntimeException e) { - // We don't care which one was thrown... - assertEquals("fail!", e.getMessage()); - } - // ...but we do care that both were executed: - assertEquals(2, list.size()); - assertTrue(list.contains("bar")); - assertTrue(list.contains("spam")); - } -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.repeat.context; + +import java.util.ArrayList; +import java.util.List; + +import junit.framework.TestCase; + +/** + * @author dsyer + * + */ +public class RepeatContextSupportTests extends TestCase { + + private List list = new ArrayList(); + + /** + * Test method for {@link org.springframework.batch.repeat.context.RepeatContextSupport#registerDestructionCallback(java.lang.String, java.lang.Runnable)}. + */ + public void testDestructionCallbackSunnyDay() throws Exception { + RepeatContextSupport context = new RepeatContextSupport(null); + context.setAttribute("foo", "FOO"); + context.registerDestructionCallback("foo", new Runnable() { + public void run() { + list.add("bar"); + } + }); + context.close(); + assertEquals(1, list.size()); + assertEquals("bar", list.get(0)); + } + + /** + * Test method for {@link org.springframework.batch.repeat.context.RepeatContextSupport#registerDestructionCallback(java.lang.String, java.lang.Runnable)}. + */ + public void testDestructionCallbackMissingAttribute() throws Exception { + RepeatContextSupport context = new RepeatContextSupport(null); + context.registerDestructionCallback("foo", new Runnable() { + public void run() { + list.add("bar"); + } + }); + context.close(); + // No check for the attribute before executing callback + assertEquals(1, list.size()); + } + + /** + * Test method for {@link org.springframework.batch.repeat.context.RepeatContextSupport#registerDestructionCallback(java.lang.String, java.lang.Runnable)}. + */ + public void testDestructionCallbackWithException() throws Exception { + RepeatContextSupport context = new RepeatContextSupport(null); + context.setAttribute("foo", "FOO"); + context.setAttribute("bar", "BAR"); + context.registerDestructionCallback("bar", new Runnable() { + public void run() { + list.add("spam"); + throw new RuntimeException("fail!"); + } + }); + context.registerDestructionCallback("foo", new Runnable() { + public void run() { + list.add("bar"); + throw new RuntimeException("fail!"); + } + }); + try { + context.close(); + fail("Expected RuntimeException"); + } catch (RuntimeException e) { + // We don't care which one was thrown... + assertEquals("fail!", e.getMessage()); + } + // ...but we do care that both were executed: + assertEquals(2, list.size()); + assertTrue(list.contains("bar")); + assertTrue(list.contains("spam")); + } +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/support/AbstractDelegatorTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/support/AbstractDelegatorTests.java index cff7032d90..42e7a5a3f8 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/support/AbstractDelegatorTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/support/AbstractDelegatorTests.java @@ -1,172 +1,172 @@ -package org.springframework.batch.support; - -import junit.framework.TestCase; - -import org.springframework.batch.io.exception.DynamicMethodInvocationException; -import org.springframework.batch.io.sample.domain.Foo; -import org.springframework.batch.io.sample.domain.FooService; -import org.springframework.util.Assert; - -/** - * Tests for {@link AbstractMethodInvokingDelegator} - * - * @author Robert Kasanicky - */ -public class AbstractDelegatorTests extends TestCase { - - private static class ConcreteDelegator extends AbstractMethodInvokingDelegator { - } - - private AbstractMethodInvokingDelegator delegator = new ConcreteDelegator(); - - private Foo foo = new Foo(0, "foo", 1); - - protected void setUp() throws Exception { - delegator.setTargetObject(foo); - delegator.setArguments(null); - } - - /** - * Regular use - calling methods directly and via delegator leads to same - * results - */ - public void testDelegation() throws Exception { - delegator.setTargetMethod("getName"); - delegator.afterPropertiesSet(); - - assertEquals(foo.getName(), delegator.invokeDelegateMethod()); - } - - /** - * Regular use - calling methods directly and via delegator leads to same - * results - */ - public void testDelegationWithArgument() throws Exception { - delegator.setTargetMethod("setName"); - final String NEW_FOO_NAME = "newFooName"; - delegator.afterPropertiesSet(); - - delegator.invokeDelegateMethodWithArgument(NEW_FOO_NAME); - assertEquals(NEW_FOO_NAME, foo.getName()); - - // using the arguments setter should work equally well - foo.setName("foo"); - Assert.state(!foo.getName().equals(NEW_FOO_NAME)); - delegator.setArguments(new Object[] { NEW_FOO_NAME }); - delegator.afterPropertiesSet(); - delegator.invokeDelegateMethod(); - assertEquals(NEW_FOO_NAME, foo.getName()); - } - - /** - * Regular use - calling methods directly and via delegator leads to same - * results - */ - public void testDelegationWithMultipleArguments() throws Exception { - FooService fooService = new FooService(); - delegator.setTargetObject(fooService); - delegator.setTargetMethod("processNameValuePair"); - delegator.afterPropertiesSet(); - - final String FOO_NAME = "fooName"; - final int FOO_VALUE = 12345; - - delegator.invokeDelegateMethodWithArguments(new Object[]{FOO_NAME, new Integer(FOO_VALUE)}); - Foo foo = (Foo) fooService.getProcessedFooNameValuePairs().get(0); - assertEquals(FOO_NAME, foo.getName()); - assertEquals(FOO_VALUE, foo.getValue()); - } - - /** - * Exception scenario - target method is not declared by target object. - */ - public void testInvalidMethodName() throws Exception { - delegator.setTargetMethod("not-existing-method-name"); - - try { - delegator.afterPropertiesSet(); - fail(); - } - catch (IllegalStateException e) { - // expected - } - - try { - delegator.invokeDelegateMethod(); - fail(); - } - catch (DynamicMethodInvocationException e) { - // expected - } - } - - /** - * Exception scenario - target method is called with invalid arguments. - */ - public void testInvalidArgumentsForExistingMethod() throws Exception { - delegator.setTargetMethod("setName"); - delegator.afterPropertiesSet(); - try { - delegator.invokeDelegateMethodWithArgument(new Object()); - fail(); - } - catch (DynamicMethodInvocationException e) { - // expected - } - } - - /** - * Exception scenario - target method is called with incorrect number of - * arguments. - */ - public void testIncorrectArgumentCount() throws Exception { - delegator.setTargetMethod("setName"); - delegator.afterPropertiesSet(); - try { - // single argument expected but none provided - delegator.invokeDelegateMethod(); - fail(); - } - catch (DynamicMethodInvocationException e) { - // expected - } - - try { - // single argument expected but two provided - delegator.invokeDelegateMethodWithArguments(new Object[]{"name", "anotherName"}); - fail(); - } - catch (DynamicMethodInvocationException e) { - // expected - } - } - - /** - * Exception scenario - incorrect static arguments set. - */ - public void testIncorrectNumberOfStaticArguments() throws Exception { - delegator.setTargetMethod("setName"); - - // incorrect argument count - delegator.setArguments(new Object[]{"first", "second"}); - try { - delegator.afterPropertiesSet(); - fail(); - } - catch (IllegalStateException e) { - // expected - } - - // correct argument count, but invalid argument type - delegator.setArguments(new Object[]{new Object()}); - try { - delegator.afterPropertiesSet(); - fail(); - } - catch (IllegalStateException e) { - // expected - } - } - - -} +package org.springframework.batch.support; + +import junit.framework.TestCase; + +import org.springframework.batch.io.exception.DynamicMethodInvocationException; +import org.springframework.batch.io.sample.domain.Foo; +import org.springframework.batch.io.sample.domain.FooService; +import org.springframework.util.Assert; + +/** + * Tests for {@link AbstractMethodInvokingDelegator} + * + * @author Robert Kasanicky + */ +public class AbstractDelegatorTests extends TestCase { + + private static class ConcreteDelegator extends AbstractMethodInvokingDelegator { + } + + private AbstractMethodInvokingDelegator delegator = new ConcreteDelegator(); + + private Foo foo = new Foo(0, "foo", 1); + + protected void setUp() throws Exception { + delegator.setTargetObject(foo); + delegator.setArguments(null); + } + + /** + * Regular use - calling methods directly and via delegator leads to same + * results + */ + public void testDelegation() throws Exception { + delegator.setTargetMethod("getName"); + delegator.afterPropertiesSet(); + + assertEquals(foo.getName(), delegator.invokeDelegateMethod()); + } + + /** + * Regular use - calling methods directly and via delegator leads to same + * results + */ + public void testDelegationWithArgument() throws Exception { + delegator.setTargetMethod("setName"); + final String NEW_FOO_NAME = "newFooName"; + delegator.afterPropertiesSet(); + + delegator.invokeDelegateMethodWithArgument(NEW_FOO_NAME); + assertEquals(NEW_FOO_NAME, foo.getName()); + + // using the arguments setter should work equally well + foo.setName("foo"); + Assert.state(!foo.getName().equals(NEW_FOO_NAME)); + delegator.setArguments(new Object[] { NEW_FOO_NAME }); + delegator.afterPropertiesSet(); + delegator.invokeDelegateMethod(); + assertEquals(NEW_FOO_NAME, foo.getName()); + } + + /** + * Regular use - calling methods directly and via delegator leads to same + * results + */ + public void testDelegationWithMultipleArguments() throws Exception { + FooService fooService = new FooService(); + delegator.setTargetObject(fooService); + delegator.setTargetMethod("processNameValuePair"); + delegator.afterPropertiesSet(); + + final String FOO_NAME = "fooName"; + final int FOO_VALUE = 12345; + + delegator.invokeDelegateMethodWithArguments(new Object[]{FOO_NAME, new Integer(FOO_VALUE)}); + Foo foo = (Foo) fooService.getProcessedFooNameValuePairs().get(0); + assertEquals(FOO_NAME, foo.getName()); + assertEquals(FOO_VALUE, foo.getValue()); + } + + /** + * Exception scenario - target method is not declared by target object. + */ + public void testInvalidMethodName() throws Exception { + delegator.setTargetMethod("not-existing-method-name"); + + try { + delegator.afterPropertiesSet(); + fail(); + } + catch (IllegalStateException e) { + // expected + } + + try { + delegator.invokeDelegateMethod(); + fail(); + } + catch (DynamicMethodInvocationException e) { + // expected + } + } + + /** + * Exception scenario - target method is called with invalid arguments. + */ + public void testInvalidArgumentsForExistingMethod() throws Exception { + delegator.setTargetMethod("setName"); + delegator.afterPropertiesSet(); + try { + delegator.invokeDelegateMethodWithArgument(new Object()); + fail(); + } + catch (DynamicMethodInvocationException e) { + // expected + } + } + + /** + * Exception scenario - target method is called with incorrect number of + * arguments. + */ + public void testIncorrectArgumentCount() throws Exception { + delegator.setTargetMethod("setName"); + delegator.afterPropertiesSet(); + try { + // single argument expected but none provided + delegator.invokeDelegateMethod(); + fail(); + } + catch (DynamicMethodInvocationException e) { + // expected + } + + try { + // single argument expected but two provided + delegator.invokeDelegateMethodWithArguments(new Object[]{"name", "anotherName"}); + fail(); + } + catch (DynamicMethodInvocationException e) { + // expected + } + } + + /** + * Exception scenario - incorrect static arguments set. + */ + public void testIncorrectNumberOfStaticArguments() throws Exception { + delegator.setTargetMethod("setName"); + + // incorrect argument count + delegator.setArguments(new Object[]{"first", "second"}); + try { + delegator.afterPropertiesSet(); + fail(); + } + catch (IllegalStateException e) { + // expected + } + + // correct argument count, but invalid argument type + delegator.setArguments(new Object[]{new Object()}); + try { + delegator.afterPropertiesSet(); + fail(); + } + catch (IllegalStateException e) { + // expected + } + } + + +} diff --git a/spring-batch-infrastructure/src/test/resources/org/springframework/batch/io/cursor/Foo-write.hbm.xml b/spring-batch-infrastructure/src/test/resources/org/springframework/batch/io/cursor/Foo-write.hbm.xml index 67b35901c4..85a7e0d6aa 100644 --- a/spring-batch-infrastructure/src/test/resources/org/springframework/batch/io/cursor/Foo-write.hbm.xml +++ b/spring-batch-infrastructure/src/test/resources/org/springframework/batch/io/cursor/Foo-write.hbm.xml @@ -1,15 +1,15 @@ - - - - - - - - - - - - + + + + + + + + + + + + \ No newline at end of file diff --git a/spring-batch-infrastructure/src/test/resources/org/springframework/batch/io/cursor/Foo.hbm.xml b/spring-batch-infrastructure/src/test/resources/org/springframework/batch/io/cursor/Foo.hbm.xml index 8a23dece94..1ab66cebf0 100644 --- a/spring-batch-infrastructure/src/test/resources/org/springframework/batch/io/cursor/Foo.hbm.xml +++ b/spring-batch-infrastructure/src/test/resources/org/springframework/batch/io/cursor/Foo.hbm.xml @@ -1,15 +1,15 @@ - - - - - - - - - - - - + + + + + + + + + + + + \ No newline at end of file diff --git a/spring-batch-infrastructure/src/test/resources/org/springframework/batch/io/driving/ibatis-config.xml b/spring-batch-infrastructure/src/test/resources/org/springframework/batch/io/driving/ibatis-config.xml index e171484a3a..e61d448695 100644 --- a/spring-batch-infrastructure/src/test/resources/org/springframework/batch/io/driving/ibatis-config.xml +++ b/spring-batch-infrastructure/src/test/resources/org/springframework/batch/io/driving/ibatis-config.xml @@ -1,12 +1,12 @@ - - - - - - - - - + + + + + + + + + \ No newline at end of file diff --git a/spring-batch-infrastructure/src/test/resources/org/springframework/batch/io/driving/ibatis-foo.xml b/spring-batch-infrastructure/src/test/resources/org/springframework/batch/io/driving/ibatis-foo.xml index bed6511488..64be724a3b 100644 --- a/spring-batch-infrastructure/src/test/resources/org/springframework/batch/io/driving/ibatis-foo.xml +++ b/spring-batch-infrastructure/src/test/resources/org/springframework/batch/io/driving/ibatis-foo.xml @@ -1,41 +1,41 @@ - - - - - - - - - - - - - - - - - - - - - insert INTO T_WRITE_FOOS (ID, NAME, VALUE) VALUES (#id#, #name#, #value#) - - - - update T_WRITE_FOOS set NAME = #name#, VALUE = #value# where ID = #id# - - - - delete from T_WRITE_FOOS where ID = #id# - - + + + + + + + + + + + + + + + + + + + + + insert INTO T_WRITE_FOOS (ID, NAME, VALUE) VALUES (#id#, #name#, #value#) + + + + update T_WRITE_FOOS set NAME = #name#, VALUE = #value# where ID = #id# + + + + delete from T_WRITE_FOOS where ID = #id# + + \ No newline at end of file diff --git a/spring-batch-infrastructure/src/test/resources/org/springframework/batch/io/sql/destroy-foo-schema-hsqldb.sql b/spring-batch-infrastructure/src/test/resources/org/springframework/batch/io/sql/destroy-foo-schema-hsqldb.sql index 34ac26db08..1c03cad828 100644 --- a/spring-batch-infrastructure/src/test/resources/org/springframework/batch/io/sql/destroy-foo-schema-hsqldb.sql +++ b/spring-batch-infrastructure/src/test/resources/org/springframework/batch/io/sql/destroy-foo-schema-hsqldb.sql @@ -1,2 +1,2 @@ -DROP TABLE T_FOOS; +DROP TABLE T_FOOS; DROP TABLE T_WRITE_FOOS; \ No newline at end of file diff --git a/spring-batch-infrastructure/src/test/resources/org/springframework/batch/io/sql/init-foo-schema-hsqldb.sql b/spring-batch-infrastructure/src/test/resources/org/springframework/batch/io/sql/init-foo-schema-hsqldb.sql index c6b0e562fb..84490ed2fb 100644 --- a/spring-batch-infrastructure/src/test/resources/org/springframework/batch/io/sql/init-foo-schema-hsqldb.sql +++ b/spring-batch-infrastructure/src/test/resources/org/springframework/batch/io/sql/init-foo-schema-hsqldb.sql @@ -1,21 +1,21 @@ -CREATE TABLE T_FOOS ( - ID BIGINT NOT NULL, - NAME VARCHAR(45), - VALUE INTEGER -); - -ALTER TABLE T_FOOS ADD PRIMARY KEY (ID); - -INSERT INTO t_foos (id, name, value) VALUES (1, 'bar1', 1); -INSERT INTO t_foos (id, name, value) VALUES (2, 'bar2', 2); -INSERT INTO t_foos (id, name, value) VALUES (3, 'bar3', 3); -INSERT INTO t_foos (id, name, value) VALUES (4, 'bar4', 4); -INSERT INTO t_foos (id, name, value) VALUES (5, 'bar5', 5); - -CREATE TABLE T_WRITE_FOOS ( - ID BIGINT NOT NULL, - NAME VARCHAR(45), - VALUE INTEGER -); - -ALTER TABLE T_WRITE_FOOS ADD PRIMARY KEY (ID); +CREATE TABLE T_FOOS ( + ID BIGINT NOT NULL, + NAME VARCHAR(45), + VALUE INTEGER +); + +ALTER TABLE T_FOOS ADD PRIMARY KEY (ID); + +INSERT INTO t_foos (id, name, value) VALUES (1, 'bar1', 1); +INSERT INTO t_foos (id, name, value) VALUES (2, 'bar2', 2); +INSERT INTO t_foos (id, name, value) VALUES (3, 'bar3', 3); +INSERT INTO t_foos (id, name, value) VALUES (4, 'bar4', 4); +INSERT INTO t_foos (id, name, value) VALUES (5, 'bar5', 5); + +CREATE TABLE T_WRITE_FOOS ( + ID BIGINT NOT NULL, + NAME VARCHAR(45), + VALUE INTEGER +); + +ALTER TABLE T_WRITE_FOOS ADD PRIMARY KEY (ID); diff --git a/spring-batch-infrastructure/src/test/resources/org/springframework/batch/item/reader/delegating-item-provider.xml b/spring-batch-infrastructure/src/test/resources/org/springframework/batch/item/reader/delegating-item-provider.xml index caeb5da97c..0738be8a77 100644 --- a/spring-batch-infrastructure/src/test/resources/org/springframework/batch/item/reader/delegating-item-provider.xml +++ b/spring-batch-infrastructure/src/test/resources/org/springframework/batch/item/reader/delegating-item-provider.xml @@ -1,12 +1,12 @@ - - - - - - - - - - + + + + + + + + + + \ No newline at end of file diff --git a/spring-batch-infrastructure/src/test/resources/org/springframework/batch/item/writer/delegating-item-writer.xml b/spring-batch-infrastructure/src/test/resources/org/springframework/batch/item/writer/delegating-item-writer.xml index 8cc5f837f7..f6b903332e 100644 --- a/spring-batch-infrastructure/src/test/resources/org/springframework/batch/item/writer/delegating-item-writer.xml +++ b/spring-batch-infrastructure/src/test/resources/org/springframework/batch/item/writer/delegating-item-writer.xml @@ -1,12 +1,12 @@ - - - - - - - - - - + + + + + + + + + + \ No newline at end of file diff --git a/spring-batch-infrastructure/src/test/resources/org/springframework/batch/item/writer/pe-delegating-item-writer.xml b/spring-batch-infrastructure/src/test/resources/org/springframework/batch/item/writer/pe-delegating-item-writer.xml index fb862ca68f..b6ae21c151 100644 --- a/spring-batch-infrastructure/src/test/resources/org/springframework/batch/item/writer/pe-delegating-item-writer.xml +++ b/spring-batch-infrastructure/src/test/resources/org/springframework/batch/item/writer/pe-delegating-item-writer.xml @@ -1,13 +1,13 @@ - - - - - - - - - - - + + + + + + + + + + + \ No newline at end of file diff --git a/spring-batch-infrastructure/src/test/resources/org/springframework/batch/retry/aop/retry-transaction-test.xml b/spring-batch-infrastructure/src/test/resources/org/springframework/batch/retry/aop/retry-transaction-test.xml index 01f9f7733f..0a147b4a5a 100644 --- a/spring-batch-infrastructure/src/test/resources/org/springframework/batch/retry/aop/retry-transaction-test.xml +++ b/spring-batch-infrastructure/src/test/resources/org/springframework/batch/retry/aop/retry-transaction-test.xml @@ -1,35 +1,35 @@ - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + diff --git a/spring-batch-integration/.project b/spring-batch-integration/.project index 13ed44f541..857b0fc822 100644 --- a/spring-batch-integration/.project +++ b/spring-batch-integration/.project @@ -1,30 +1,30 @@ - - - spring-batch-integration - Integration tests for the Spring Batch Infrastructure - - spring-batch-infrastructure - - - - org.eclipse.jdt.core.javabuilder - - - - - org.springframework.ide.eclipse.core.springbuilder - - - - - org.devzuz.q.maven.jdt.core.mavenIncrementalBuilder - - - - - - org.springframework.ide.eclipse.core.springnature - org.eclipse.jdt.core.javanature - org.devzuz.q.maven.jdt.core.mavenNature - - + + + spring-batch-integration + Integration tests for the Spring Batch Infrastructure + + spring-batch-infrastructure + + + + org.eclipse.jdt.core.javabuilder + + + + + org.springframework.ide.eclipse.core.springbuilder + + + + + org.devzuz.q.maven.jdt.core.mavenIncrementalBuilder + + + + + + org.springframework.ide.eclipse.core.springnature + org.eclipse.jdt.core.javanature + org.devzuz.q.maven.jdt.core.mavenNature + + diff --git a/spring-batch-integration/.settings/org.eclipse.mylyn.tasks.ui.prefs b/spring-batch-integration/.settings/org.eclipse.mylyn.tasks.ui.prefs index 5e49252fa4..a0153a2940 100644 --- a/spring-batch-integration/.settings/org.eclipse.mylyn.tasks.ui.prefs +++ b/spring-batch-integration/.settings/org.eclipse.mylyn.tasks.ui.prefs @@ -1,4 +1,4 @@ -#Thu Aug 23 07:01:43 BST 2007 -eclipse.preferences.version=1 -project.repository.kind=jira -project.repository.url=http\://opensource.atlassian.com/projects/spring +#Thu Aug 23 07:01:43 BST 2007 +eclipse.preferences.version=1 +project.repository.kind=jira +project.repository.url=http\://opensource.atlassian.com/projects/spring diff --git a/spring-batch-integration/.springBeans b/spring-batch-integration/.springBeans index 1128b99cb7..a17ff62ef3 100644 --- a/spring-batch-integration/.springBeans +++ b/spring-batch-integration/.springBeans @@ -1,37 +1,37 @@ - - - - xml - - - src/test/resources/org/springframework/batch/jms/jms-context.xml - src/test/resources/data-source.xml - - - - - true - false - - src/test/resources/data-source.xml - - - - - true - false - - src/test/resources/data-source.xml - src/test/resources/org/springframework/batch/jms/jms-context.xml - - - - - true - false - - src/test/resources/data-source.xml - - - - + + + + xml + + + src/test/resources/org/springframework/batch/jms/jms-context.xml + src/test/resources/data-source.xml + + + + + true + false + + src/test/resources/data-source.xml + + + + + true + false + + src/test/resources/data-source.xml + src/test/resources/org/springframework/batch/jms/jms-context.xml + + + + + true + false + + src/test/resources/data-source.xml + + + + diff --git a/spring-batch-integration/src/test/java/org/springframework/batch/io/oxm/AbstractStaxEventReaderItemReaderTests.java b/spring-batch-integration/src/test/java/org/springframework/batch/io/oxm/AbstractStaxEventReaderItemReaderTests.java index 1ab2d32fad..378867d800 100644 --- a/spring-batch-integration/src/test/java/org/springframework/batch/io/oxm/AbstractStaxEventReaderItemReaderTests.java +++ b/spring-batch-integration/src/test/java/org/springframework/batch/io/oxm/AbstractStaxEventReaderItemReaderTests.java @@ -1,84 +1,84 @@ -package org.springframework.batch.io.oxm; - -import java.math.BigDecimal; -import java.util.ArrayList; -import java.util.List; - -import junit.framework.TestCase; - -import org.springframework.batch.io.oxm.domain.Trade; -import org.springframework.batch.io.xml.StaxEventItemReader; -import org.springframework.batch.io.xml.oxm.UnmarshallingEventReaderDeserializer; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.core.io.ClassPathResource; -import org.springframework.core.io.Resource; -import org.springframework.oxm.Unmarshaller; - -public abstract class AbstractStaxEventReaderItemReaderTests extends TestCase { - - private StaxEventItemReader source = new StaxEventItemReader(); - - protected Resource resource = new ClassPathResource( - "org/springframework/batch/io/oxm/input.xml"); - - - protected void setUp() throws Exception { - //TODO sensible resource allocation - source.setResource(resource); - - source.setFragmentRootElementName("trade"); - UnmarshallingEventReaderDeserializer deserializer = new UnmarshallingEventReaderDeserializer(getUnmarshaller()); - source.setFragmentDeserializer(deserializer); - - source.open(new ExecutionContext()); - - } - - public void testRead() { - Object result; - List results = new ArrayList(); - while ((result = source.read()) != null) { - results.add(result); - } - checkResults(results); - - } - - /** - * @return Unmarshaller specific to the OXM library used - */ - protected abstract Unmarshaller getUnmarshaller() throws Exception; - - /** - * @param results list of domain objects returned by input source - */ - protected void checkResults(List results){ - assertEquals(3, results.size()); - - Trade trade1 = (Trade) results.get(0); - assertEquals("XYZ0001", trade1.getIsin()); - assertEquals(5, trade1.getQuantity()); - assertEquals(BigDecimal.valueOf(11.39), trade1.getPrice()); - assertEquals("Customer1", trade1.getCustomer()); - - Trade trade2 = (Trade) results.get(1); - assertEquals("XYZ0002", trade2.getIsin()); - assertEquals(2, trade2.getQuantity()); - assertEquals(BigDecimal.valueOf(72.99), trade2.getPrice()); - assertEquals("Customer2", trade2.getCustomer()); - - Trade trade3 = (Trade) results.get(2); - assertEquals("XYZ0003", trade3.getIsin()); - assertEquals(9, trade3.getQuantity()); - assertEquals(BigDecimal.valueOf(99.99), trade3.getPrice()); - assertEquals("Customer3", trade3.getCustomer()); - } - - protected void tearDown() throws Exception { - source.close(null); - } - - public void setResource(Resource resource) { - this.resource = resource; - } -} +package org.springframework.batch.io.oxm; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.List; + +import junit.framework.TestCase; + +import org.springframework.batch.io.oxm.domain.Trade; +import org.springframework.batch.io.xml.StaxEventItemReader; +import org.springframework.batch.io.xml.oxm.UnmarshallingEventReaderDeserializer; +import org.springframework.batch.item.ExecutionContext; +import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.Resource; +import org.springframework.oxm.Unmarshaller; + +public abstract class AbstractStaxEventReaderItemReaderTests extends TestCase { + + private StaxEventItemReader source = new StaxEventItemReader(); + + protected Resource resource = new ClassPathResource( + "org/springframework/batch/io/oxm/input.xml"); + + + protected void setUp() throws Exception { + //TODO sensible resource allocation + source.setResource(resource); + + source.setFragmentRootElementName("trade"); + UnmarshallingEventReaderDeserializer deserializer = new UnmarshallingEventReaderDeserializer(getUnmarshaller()); + source.setFragmentDeserializer(deserializer); + + source.open(new ExecutionContext()); + + } + + public void testRead() { + Object result; + List results = new ArrayList(); + while ((result = source.read()) != null) { + results.add(result); + } + checkResults(results); + + } + + /** + * @return Unmarshaller specific to the OXM library used + */ + protected abstract Unmarshaller getUnmarshaller() throws Exception; + + /** + * @param results list of domain objects returned by input source + */ + protected void checkResults(List results){ + assertEquals(3, results.size()); + + Trade trade1 = (Trade) results.get(0); + assertEquals("XYZ0001", trade1.getIsin()); + assertEquals(5, trade1.getQuantity()); + assertEquals(BigDecimal.valueOf(11.39), trade1.getPrice()); + assertEquals("Customer1", trade1.getCustomer()); + + Trade trade2 = (Trade) results.get(1); + assertEquals("XYZ0002", trade2.getIsin()); + assertEquals(2, trade2.getQuantity()); + assertEquals(BigDecimal.valueOf(72.99), trade2.getPrice()); + assertEquals("Customer2", trade2.getCustomer()); + + Trade trade3 = (Trade) results.get(2); + assertEquals("XYZ0003", trade3.getIsin()); + assertEquals(9, trade3.getQuantity()); + assertEquals(BigDecimal.valueOf(99.99), trade3.getPrice()); + assertEquals("Customer3", trade3.getCustomer()); + } + + protected void tearDown() throws Exception { + source.close(null); + } + + public void setResource(Resource resource) { + this.resource = resource; + } +} diff --git a/spring-batch-integration/src/test/java/org/springframework/batch/io/oxm/AbstractStaxEventWriterItemWriterTests.java b/spring-batch-integration/src/test/java/org/springframework/batch/io/oxm/AbstractStaxEventWriterItemWriterTests.java index 161e667c1a..091b25b669 100644 --- a/spring-batch-integration/src/test/java/org/springframework/batch/io/oxm/AbstractStaxEventWriterItemWriterTests.java +++ b/spring-batch-integration/src/test/java/org/springframework/batch/io/oxm/AbstractStaxEventWriterItemWriterTests.java @@ -1,77 +1,77 @@ -package org.springframework.batch.io.oxm; - -import java.io.File; -import java.io.FileReader; -import java.math.BigDecimal; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -import junit.framework.TestCase; - -import org.custommonkey.xmlunit.XMLAssert; -import org.custommonkey.xmlunit.XMLUnit; -import org.springframework.batch.io.oxm.domain.Trade; -import org.springframework.batch.io.xml.StaxEventItemWriter; -import org.springframework.batch.io.xml.oxm.MarshallingEventWriterSerializer; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.core.io.ClassPathResource; -import org.springframework.core.io.FileSystemResource; -import org.springframework.core.io.Resource; -import org.springframework.oxm.Marshaller; - -public abstract class AbstractStaxEventWriterItemWriterTests extends TestCase { - - private StaxEventItemWriter writer = new StaxEventItemWriter(); - - private Resource resource; - - File outputFile; - - protected Resource expected = new ClassPathResource("expected-output.xml", getClass()); - - - protected List objects = new ArrayList() {{ - add(new Trade("isin1", 1, new BigDecimal(1.0), "customer1")); - add(new Trade("isin2", 2, new BigDecimal(2.0), "customer2")); - add(new Trade("isin3", 3, new BigDecimal(3.0), "customer3")); - }}; - - /** - * Write list of domain objects and check the output file. - */ - public void testWrite() throws Exception { - for (Iterator iterator = objects.listIterator(); iterator.hasNext();) { - writer.write(iterator.next()); - } - writer.close(null); - XMLUnit.setIgnoreWhitespace(true); - XMLAssert.assertXMLEqual(new FileReader(expected.getFile()), new FileReader(resource.getFile())); - - } - - - protected void setUp() throws Exception { - //File outputFile = File.createTempFile("AbstractStaxStreamWriterOutputSourceTests", "xml"); - outputFile = File.createTempFile(this.getClass().getSimpleName(), ".xml"); - resource = new FileSystemResource(outputFile); - writer.setResource(resource); - - MarshallingEventWriterSerializer mapper = new MarshallingEventWriterSerializer(getMarshaller()); - writer.setSerializer(mapper); - - writer.open(new ExecutionContext()); - } - - protected void tearDown() throws Exception { - super.tearDown(); - - outputFile.delete(); - } - - /** - * @return Marshaller specific for the OXM technology being used. - */ - protected abstract Marshaller getMarshaller() throws Exception; - -} +package org.springframework.batch.io.oxm; + +import java.io.File; +import java.io.FileReader; +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import junit.framework.TestCase; + +import org.custommonkey.xmlunit.XMLAssert; +import org.custommonkey.xmlunit.XMLUnit; +import org.springframework.batch.io.oxm.domain.Trade; +import org.springframework.batch.io.xml.StaxEventItemWriter; +import org.springframework.batch.io.xml.oxm.MarshallingEventWriterSerializer; +import org.springframework.batch.item.ExecutionContext; +import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.FileSystemResource; +import org.springframework.core.io.Resource; +import org.springframework.oxm.Marshaller; + +public abstract class AbstractStaxEventWriterItemWriterTests extends TestCase { + + private StaxEventItemWriter writer = new StaxEventItemWriter(); + + private Resource resource; + + File outputFile; + + protected Resource expected = new ClassPathResource("expected-output.xml", getClass()); + + + protected List objects = new ArrayList() {{ + add(new Trade("isin1", 1, new BigDecimal(1.0), "customer1")); + add(new Trade("isin2", 2, new BigDecimal(2.0), "customer2")); + add(new Trade("isin3", 3, new BigDecimal(3.0), "customer3")); + }}; + + /** + * Write list of domain objects and check the output file. + */ + public void testWrite() throws Exception { + for (Iterator iterator = objects.listIterator(); iterator.hasNext();) { + writer.write(iterator.next()); + } + writer.close(null); + XMLUnit.setIgnoreWhitespace(true); + XMLAssert.assertXMLEqual(new FileReader(expected.getFile()), new FileReader(resource.getFile())); + + } + + + protected void setUp() throws Exception { + //File outputFile = File.createTempFile("AbstractStaxStreamWriterOutputSourceTests", "xml"); + outputFile = File.createTempFile(this.getClass().getSimpleName(), ".xml"); + resource = new FileSystemResource(outputFile); + writer.setResource(resource); + + MarshallingEventWriterSerializer mapper = new MarshallingEventWriterSerializer(getMarshaller()); + writer.setSerializer(mapper); + + writer.open(new ExecutionContext()); + } + + protected void tearDown() throws Exception { + super.tearDown(); + + outputFile.delete(); + } + + /** + * @return Marshaller specific for the OXM technology being used. + */ + protected abstract Marshaller getMarshaller() throws Exception; + +} diff --git a/spring-batch-integration/src/test/java/org/springframework/batch/io/oxm/CastorMarshallingTests.java b/spring-batch-integration/src/test/java/org/springframework/batch/io/oxm/CastorMarshallingTests.java index f721458f4c..cf306d2730 100644 --- a/spring-batch-integration/src/test/java/org/springframework/batch/io/oxm/CastorMarshallingTests.java +++ b/spring-batch-integration/src/test/java/org/springframework/batch/io/oxm/CastorMarshallingTests.java @@ -1,20 +1,20 @@ -package org.springframework.batch.io.oxm; - -import org.springframework.core.io.ClassPathResource; -import org.springframework.oxm.Marshaller; -import org.springframework.oxm.castor.CastorMarshaller; - -public class CastorMarshallingTests extends AbstractStaxEventWriterItemWriterTests { - - protected Marshaller getMarshaller() throws Exception { - - CastorMarshaller marshaller = new CastorMarshaller(); - // marshaller.setTargetClass(Trade.class); - marshaller.setMappingLocation(new ClassPathResource("mapping-castor.xml", getClass())); - // there is no way to call - // org.exolab.castor.xml.Marshaller.setSupressXMLDeclaration(); - marshaller.afterPropertiesSet(); - return marshaller; - } - -} +package org.springframework.batch.io.oxm; + +import org.springframework.core.io.ClassPathResource; +import org.springframework.oxm.Marshaller; +import org.springframework.oxm.castor.CastorMarshaller; + +public class CastorMarshallingTests extends AbstractStaxEventWriterItemWriterTests { + + protected Marshaller getMarshaller() throws Exception { + + CastorMarshaller marshaller = new CastorMarshaller(); + // marshaller.setTargetClass(Trade.class); + marshaller.setMappingLocation(new ClassPathResource("mapping-castor.xml", getClass())); + // there is no way to call + // org.exolab.castor.xml.Marshaller.setSupressXMLDeclaration(); + marshaller.afterPropertiesSet(); + return marshaller; + } + +} diff --git a/spring-batch-integration/src/test/java/org/springframework/batch/io/oxm/CastorUnmarshallingTests.java b/spring-batch-integration/src/test/java/org/springframework/batch/io/oxm/CastorUnmarshallingTests.java index 30892f8c51..e0083709f5 100644 --- a/spring-batch-integration/src/test/java/org/springframework/batch/io/oxm/CastorUnmarshallingTests.java +++ b/spring-batch-integration/src/test/java/org/springframework/batch/io/oxm/CastorUnmarshallingTests.java @@ -1,18 +1,18 @@ -package org.springframework.batch.io.oxm; - -import org.springframework.core.io.ClassPathResource; -import org.springframework.oxm.Unmarshaller; -import org.springframework.oxm.castor.CastorMarshaller; - -public class CastorUnmarshallingTests extends AbstractStaxEventReaderItemReaderTests { - - protected Unmarshaller getUnmarshaller() throws Exception { - CastorMarshaller unmarshaller = new CastorMarshaller(); - unmarshaller.setMappingLocation(new ClassPathResource("mapping-castor.xml", getClass())); - // alternatively target class can be set - //unmarshaller.setTargetClass(Trade.class); - unmarshaller.afterPropertiesSet(); - return unmarshaller; - } - -} +package org.springframework.batch.io.oxm; + +import org.springframework.core.io.ClassPathResource; +import org.springframework.oxm.Unmarshaller; +import org.springframework.oxm.castor.CastorMarshaller; + +public class CastorUnmarshallingTests extends AbstractStaxEventReaderItemReaderTests { + + protected Unmarshaller getUnmarshaller() throws Exception { + CastorMarshaller unmarshaller = new CastorMarshaller(); + unmarshaller.setMappingLocation(new ClassPathResource("mapping-castor.xml", getClass())); + // alternatively target class can be set + //unmarshaller.setTargetClass(Trade.class); + unmarshaller.afterPropertiesSet(); + return unmarshaller; + } + +} diff --git a/spring-batch-integration/src/test/java/org/springframework/batch/io/oxm/XStreamMarshallingTests.java b/spring-batch-integration/src/test/java/org/springframework/batch/io/oxm/XStreamMarshallingTests.java index fc649cea7e..d8ad409d2c 100644 --- a/spring-batch-integration/src/test/java/org/springframework/batch/io/oxm/XStreamMarshallingTests.java +++ b/spring-batch-integration/src/test/java/org/springframework/batch/io/oxm/XStreamMarshallingTests.java @@ -1,18 +1,18 @@ -package org.springframework.batch.io.oxm; - -import org.springframework.batch.io.oxm.domain.Trade; -import org.springframework.oxm.Marshaller; -import org.springframework.oxm.xstream.XStreamMarshaller; - -public class XStreamMarshallingTests extends - AbstractStaxEventWriterItemWriterTests { - - protected Marshaller getMarshaller() throws Exception { - XStreamMarshaller marshaller = new XStreamMarshaller(); - marshaller.addAlias("trade", Trade.class); - //in XStreamMarshaller.marshalSaxHandlers() method is used SaxWriter, which is configured - //to include enclosing document (SaxWriter.includeEnclosingDocument is always set to TRUE) - return marshaller; - } - -} +package org.springframework.batch.io.oxm; + +import org.springframework.batch.io.oxm.domain.Trade; +import org.springframework.oxm.Marshaller; +import org.springframework.oxm.xstream.XStreamMarshaller; + +public class XStreamMarshallingTests extends + AbstractStaxEventWriterItemWriterTests { + + protected Marshaller getMarshaller() throws Exception { + XStreamMarshaller marshaller = new XStreamMarshaller(); + marshaller.addAlias("trade", Trade.class); + //in XStreamMarshaller.marshalSaxHandlers() method is used SaxWriter, which is configured + //to include enclosing document (SaxWriter.includeEnclosingDocument is always set to TRUE) + return marshaller; + } + +} diff --git a/spring-batch-integration/src/test/java/org/springframework/batch/io/oxm/XStreamUnmarshallingTests.java b/spring-batch-integration/src/test/java/org/springframework/batch/io/oxm/XStreamUnmarshallingTests.java index ee3b498f2a..d08a59e6bc 100644 --- a/spring-batch-integration/src/test/java/org/springframework/batch/io/oxm/XStreamUnmarshallingTests.java +++ b/spring-batch-integration/src/test/java/org/springframework/batch/io/oxm/XStreamUnmarshallingTests.java @@ -1,20 +1,20 @@ -package org.springframework.batch.io.oxm; - -import java.math.BigDecimal; - -import org.springframework.batch.io.oxm.domain.Trade; -import org.springframework.oxm.Unmarshaller; -import org.springframework.oxm.xstream.XStreamMarshaller; - -public class XStreamUnmarshallingTests extends AbstractStaxEventReaderItemReaderTests { - - protected Unmarshaller getUnmarshaller() throws Exception { - XStreamMarshaller unmarshaller = new XStreamMarshaller(); - unmarshaller.addAlias("trade", Trade.class); - unmarshaller.addAlias("isin", String.class); - unmarshaller.addAlias("customer", String.class); - unmarshaller.addAlias("price", BigDecimal.class); - return unmarshaller; - } - -} +package org.springframework.batch.io.oxm; + +import java.math.BigDecimal; + +import org.springframework.batch.io.oxm.domain.Trade; +import org.springframework.oxm.Unmarshaller; +import org.springframework.oxm.xstream.XStreamMarshaller; + +public class XStreamUnmarshallingTests extends AbstractStaxEventReaderItemReaderTests { + + protected Unmarshaller getUnmarshaller() throws Exception { + XStreamMarshaller unmarshaller = new XStreamMarshaller(); + unmarshaller.addAlias("trade", Trade.class); + unmarshaller.addAlias("isin", String.class); + unmarshaller.addAlias("customer", String.class); + unmarshaller.addAlias("price", BigDecimal.class); + return unmarshaller; + } + +} diff --git a/spring-batch-integration/src/test/java/org/springframework/batch/io/oxm/domain/Trade.java b/spring-batch-integration/src/test/java/org/springframework/batch/io/oxm/domain/Trade.java index bc959b60f2..2c1294699a 100644 --- a/spring-batch-integration/src/test/java/org/springframework/batch/io/oxm/domain/Trade.java +++ b/spring-batch-integration/src/test/java/org/springframework/batch/io/oxm/domain/Trade.java @@ -1,72 +1,72 @@ -package org.springframework.batch.io.oxm.domain; - -import java.math.BigDecimal; - -import org.apache.commons.lang.builder.EqualsBuilder; -import org.apache.commons.lang.builder.HashCodeBuilder; - - -/** - * @author Rob Harrop - */ -public class Trade { - private String isin = ""; - private long quantity = 0; - private BigDecimal price = new BigDecimal(0); - private String customer = ""; - - public Trade() { - } - - public Trade(String isin, long quantity, BigDecimal price, String customer){ - this.isin = isin; - this.quantity = quantity; - this.price = price; - this.customer = customer; - } - - public void setCustomer(String customer) { - this.customer = customer; - } - - public void setIsin(String isin) { - this.isin = isin; - } - - public void setPrice(BigDecimal price) { - this.price = price; - } - - public void setQuantity(long quantity) { - this.quantity = quantity; - } - - public String getIsin() { - return isin; - } - - public BigDecimal getPrice() { - return price; - } - - public long getQuantity() { - return quantity; - } - - public String getCustomer() { - return customer; - } - - public String toString() { - return "Trade: [isin=" + this.isin + ",quantity=" + this.quantity + ",price=" - + this.price + ",customer=" + this.customer + "]"; - } - - public boolean equals(Object o) { - return EqualsBuilder.reflectionEquals(this, o); - } - - public int hashCode() { - return HashCodeBuilder.reflectionHashCode(this); - } -} +package org.springframework.batch.io.oxm.domain; + +import java.math.BigDecimal; + +import org.apache.commons.lang.builder.EqualsBuilder; +import org.apache.commons.lang.builder.HashCodeBuilder; + + +/** + * @author Rob Harrop + */ +public class Trade { + private String isin = ""; + private long quantity = 0; + private BigDecimal price = new BigDecimal(0); + private String customer = ""; + + public Trade() { + } + + public Trade(String isin, long quantity, BigDecimal price, String customer){ + this.isin = isin; + this.quantity = quantity; + this.price = price; + this.customer = customer; + } + + public void setCustomer(String customer) { + this.customer = customer; + } + + public void setIsin(String isin) { + this.isin = isin; + } + + public void setPrice(BigDecimal price) { + this.price = price; + } + + public void setQuantity(long quantity) { + this.quantity = quantity; + } + + public String getIsin() { + return isin; + } + + public BigDecimal getPrice() { + return price; + } + + public long getQuantity() { + return quantity; + } + + public String getCustomer() { + return customer; + } + + public String toString() { + return "Trade: [isin=" + this.isin + ",quantity=" + this.quantity + ",price=" + + this.price + ",customer=" + this.customer + "]"; + } + + public boolean equals(Object o) { + return EqualsBuilder.reflectionEquals(this, o); + } + + public int hashCode() { + return HashCodeBuilder.reflectionHashCode(this); + } +} diff --git a/spring-batch-integration/src/test/resources/org/springframework/batch/io/oxm/expected-output.xml b/spring-batch-integration/src/test/resources/org/springframework/batch/io/oxm/expected-output.xml index d0644b0c46..8a267ae5a3 100644 --- a/spring-batch-integration/src/test/resources/org/springframework/batch/io/oxm/expected-output.xml +++ b/spring-batch-integration/src/test/resources/org/springframework/batch/io/oxm/expected-output.xml @@ -1,24 +1,24 @@ - - - - isin1 - 1 - 1 - customer1 - - - - isin2 - 2 - 2 - customer2 - - - - isin3 - 3 - 3 - customer3 - - + + + + isin1 + 1 + 1 + customer1 + + + + isin2 + 2 + 2 + customer2 + + + + isin3 + 3 + 3 + customer3 + + \ No newline at end of file diff --git a/spring-batch-integration/src/test/resources/org/springframework/batch/io/oxm/input.xml b/spring-batch-integration/src/test/resources/org/springframework/batch/io/oxm/input.xml index 0e76751a4d..29f820ef43 100644 --- a/spring-batch-integration/src/test/resources/org/springframework/batch/io/oxm/input.xml +++ b/spring-batch-integration/src/test/resources/org/springframework/batch/io/oxm/input.xml @@ -1,21 +1,21 @@ - - - - XYZ0001 - 5 - 11.39 - Customer1 - - - XYZ0002 - 2 - 72.99 - Customer2 - - - XYZ0003 - 9 - 99.99 - Customer3 - - + + + + XYZ0001 + 5 + 11.39 + Customer1 + + + XYZ0002 + 2 + 72.99 + Customer2 + + + XYZ0003 + 9 + 99.99 + Customer3 + + diff --git a/spring-batch-integration/src/test/resources/org/springframework/batch/io/oxm/mapping-castor.xml b/spring-batch-integration/src/test/resources/org/springframework/batch/io/oxm/mapping-castor.xml index b9306dbee6..52d256275b 100644 --- a/spring-batch-integration/src/test/resources/org/springframework/batch/io/oxm/mapping-castor.xml +++ b/spring-batch-integration/src/test/resources/org/springframework/batch/io/oxm/mapping-castor.xml @@ -1,23 +1,23 @@ - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/spring-batch-samples/.project b/spring-batch-samples/.project index 5b9fc2e46f..eda96ec30e 100644 --- a/spring-batch-samples/.project +++ b/spring-batch-samples/.project @@ -1,32 +1,32 @@ - - - spring-batch-samples - Example batch jobs using Spring Batch Core and Execution. - - spring-batch-infrastructure - spring-batch-core - spring-batch-execution - - - - org.eclipse.jdt.core.javabuilder - - - - - org.springframework.ide.eclipse.core.springbuilder - - - - - org.devzuz.q.maven.jdt.core.mavenIncrementalBuilder - - - - - - org.springframework.ide.eclipse.core.springnature - org.eclipse.jdt.core.javanature - org.devzuz.q.maven.jdt.core.mavenNature - - + + + spring-batch-samples + Example batch jobs using Spring Batch Core and Execution. + + spring-batch-infrastructure + spring-batch-core + spring-batch-execution + + + + org.eclipse.jdt.core.javabuilder + + + + + org.springframework.ide.eclipse.core.springbuilder + + + + + org.devzuz.q.maven.jdt.core.mavenIncrementalBuilder + + + + + + org.springframework.ide.eclipse.core.springnature + org.eclipse.jdt.core.javanature + org.devzuz.q.maven.jdt.core.mavenNature + + diff --git a/spring-batch-samples/.settings/hsql-manager.launch b/spring-batch-samples/.settings/hsql-manager.launch index 530be9f003..c7e390fca8 100644 --- a/spring-batch-samples/.settings/hsql-manager.launch +++ b/spring-batch-samples/.settings/hsql-manager.launch @@ -1,13 +1,13 @@ - - - - - - - - - - - - - + + + + + + + + + + + + + diff --git a/spring-batch-samples/.settings/hsql-server.launch b/spring-batch-samples/.settings/hsql-server.launch index 8cccbba21f..b14506c1ae 100644 --- a/spring-batch-samples/.settings/hsql-server.launch +++ b/spring-batch-samples/.settings/hsql-server.launch @@ -1,13 +1,13 @@ - - - - - - - - - - - - - + + + + + + + + + + + + + diff --git a/spring-batch-samples/.settings/jmxLauncher.launch b/spring-batch-samples/.settings/jmxLauncher.launch index eb79ad06ae..671eaa23cf 100644 --- a/spring-batch-samples/.settings/jmxLauncher.launch +++ b/spring-batch-samples/.settings/jmxLauncher.launch @@ -1,16 +1,16 @@ - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + diff --git a/spring-batch-samples/.settings/jobLauncher.launch b/spring-batch-samples/.settings/jobLauncher.launch index edfe1fe633..c7ad26f933 100644 --- a/spring-batch-samples/.settings/jobLauncher.launch +++ b/spring-batch-samples/.settings/jobLauncher.launch @@ -1,16 +1,16 @@ - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + diff --git a/spring-batch-samples/.settings/org.eclipse.jdt.core.prefs b/spring-batch-samples/.settings/org.eclipse.jdt.core.prefs index c05bcf41e3..e6b568bd4f 100644 --- a/spring-batch-samples/.settings/org.eclipse.jdt.core.prefs +++ b/spring-batch-samples/.settings/org.eclipse.jdt.core.prefs @@ -1,4 +1,4 @@ -#Wed Feb 13 08:39:25 GMT 2008 -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.4 -org.eclipse.jdt.core.compiler.source=1.4 +#Wed Feb 13 08:39:25 GMT 2008 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.4 +org.eclipse.jdt.core.compiler.source=1.4 diff --git a/spring-batch-samples/.settings/org.eclipse.wst.validation.prefs b/spring-batch-samples/.settings/org.eclipse.wst.validation.prefs index 54bf2968c2..3e095edabd 100644 --- a/spring-batch-samples/.settings/org.eclipse.wst.validation.prefs +++ b/spring-batch-samples/.settings/org.eclipse.wst.validation.prefs @@ -1,6 +1,6 @@ -#Mon Aug 20 22:24:22 BST 2007 -DELEGATES_PREFERENCE=delegateValidatorListorg.eclipse.wst.xsd.core.internal.validation.eclipse.XSDDelegatingValidator\=org.eclipse.wst.xsd.core.internal.validation.eclipse.Validator;org.eclipse.wst.wsdl.validation.internal.eclipse.WSDLDelegatingValidator\=org.eclipse.wst.wsdl.validation.internal.eclipse.Validator; -USER_BUILD_PREFERENCE=enabledBuildValidatorListorg.eclipse.jst.jsp.core.internal.validation.JSPContentValidator;org.eclipse.jst.jsf.validation.internal.appconfig.AppConfigValidator;org.eclipse.jst.jsf.validation.internal.JSPSemanticsValidator;org.eclipse.wst.wsi.ui.internal.WSIMessageValidator;org.eclipse.jst.jsp.core.internal.validation.JSPBatchValidator;org.eclipse.wst.common.componentcore.internal.ModuleCoreValidator;org.eclipse.wst.xsd.core.internal.validation.eclipse.XSDDelegatingValidator;org.eclipse.wst.xml.core.internal.validation.eclipse.Validator;org.eclipse.wst.wsdl.validation.internal.eclipse.WSDLDelegatingValidator;org.eclipse.wst.dtd.core.internal.validation.eclipse.Validator; -USER_MANUAL_PREFERENCE=enabledManualValidatorListorg.eclipse.jst.jsp.core.internal.validation.JSPContentValidator;org.eclipse.jst.jsf.validation.internal.appconfig.AppConfigValidator;org.eclipse.wst.html.internal.validation.HTMLValidator;org.eclipse.jst.jsf.validation.internal.JSPSemanticsValidator;org.eclipse.wst.wsi.ui.internal.WSIMessageValidator;org.eclipse.jst.jsp.core.internal.validation.JSPBatchValidator;org.eclipse.wst.common.componentcore.internal.ModuleCoreValidator;org.eclipse.wst.xsd.core.internal.validation.eclipse.XSDDelegatingValidator;org.eclipse.wst.xml.core.internal.validation.eclipse.Validator;org.eclipse.wst.wsdl.validation.internal.eclipse.WSDLDelegatingValidator;org.eclipse.wst.dtd.core.internal.validation.eclipse.Validator; -USER_PREFERENCE=overrideGlobalPreferencesfalse -eclipse.preferences.version=1 +#Mon Aug 20 22:24:22 BST 2007 +DELEGATES_PREFERENCE=delegateValidatorListorg.eclipse.wst.xsd.core.internal.validation.eclipse.XSDDelegatingValidator\=org.eclipse.wst.xsd.core.internal.validation.eclipse.Validator;org.eclipse.wst.wsdl.validation.internal.eclipse.WSDLDelegatingValidator\=org.eclipse.wst.wsdl.validation.internal.eclipse.Validator; +USER_BUILD_PREFERENCE=enabledBuildValidatorListorg.eclipse.jst.jsp.core.internal.validation.JSPContentValidator;org.eclipse.jst.jsf.validation.internal.appconfig.AppConfigValidator;org.eclipse.jst.jsf.validation.internal.JSPSemanticsValidator;org.eclipse.wst.wsi.ui.internal.WSIMessageValidator;org.eclipse.jst.jsp.core.internal.validation.JSPBatchValidator;org.eclipse.wst.common.componentcore.internal.ModuleCoreValidator;org.eclipse.wst.xsd.core.internal.validation.eclipse.XSDDelegatingValidator;org.eclipse.wst.xml.core.internal.validation.eclipse.Validator;org.eclipse.wst.wsdl.validation.internal.eclipse.WSDLDelegatingValidator;org.eclipse.wst.dtd.core.internal.validation.eclipse.Validator; +USER_MANUAL_PREFERENCE=enabledManualValidatorListorg.eclipse.jst.jsp.core.internal.validation.JSPContentValidator;org.eclipse.jst.jsf.validation.internal.appconfig.AppConfigValidator;org.eclipse.wst.html.internal.validation.HTMLValidator;org.eclipse.jst.jsf.validation.internal.JSPSemanticsValidator;org.eclipse.wst.wsi.ui.internal.WSIMessageValidator;org.eclipse.jst.jsp.core.internal.validation.JSPBatchValidator;org.eclipse.wst.common.componentcore.internal.ModuleCoreValidator;org.eclipse.wst.xsd.core.internal.validation.eclipse.XSDDelegatingValidator;org.eclipse.wst.xml.core.internal.validation.eclipse.Validator;org.eclipse.wst.wsdl.validation.internal.eclipse.WSDLDelegatingValidator;org.eclipse.wst.dtd.core.internal.validation.eclipse.Validator; +USER_PREFERENCE=overrideGlobalPreferencesfalse +eclipse.preferences.version=1 diff --git a/spring-batch-samples/.settings/quartzLauncher.launch b/spring-batch-samples/.settings/quartzLauncher.launch index 6be8e0ffbd..bffcd4dbe5 100644 --- a/spring-batch-samples/.settings/quartzLauncher.launch +++ b/spring-batch-samples/.settings/quartzLauncher.launch @@ -1,15 +1,15 @@ - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + diff --git a/spring-batch-samples/.springBeans b/spring-batch-samples/.springBeans index 8f1f25457d..94c1edcd2e 100644 --- a/spring-batch-samples/.springBeans +++ b/spring-batch-samples/.springBeans @@ -1,263 +1,263 @@ - - - 1 - - - - - - - src/main/resources/jobs/fixedLengthImportJob.xml - src/main/resources/jobs/multilineJob.xml - src/main/resources/jobs/multilineOrderInputDescriptors.xml - src/main/resources/jobs/multilineOrderIo.xml - src/main/resources/jobs/multilineOrderJob.xml - src/main/resources/jobs/multilineOrderOutputDescriptors.xml - src/main/resources/jobs/tradeJob.xml - src/main/resources/jobs/tradeJobIo.xml - src/main/resources/jobs/restartSample.xml - src/main/resources/data-source-context.xml - src/main/resources/jobs/beanWrapperMapperSampleJob.xml - src/main/resources/jobs/adhocLoopJob.xml - src/main/resources/jobs/infiniteLoopJob.xml - src/main/resources/data-source-context-init.xml - src/main/resources/jobs/xmlStaxJob.xml - src/main/resources/jobs/hibernateJob.xml - src/main/resources/jobs/ibatisJob.xml - src/main/resources/jobs/compositeProcessorSampleJob.xml - src/main/resources/jobs/footballJob.xml - src/main/resources/beanRefContext.xml - src/main/resources/jobs/delegatingJob.xml - src/main/resources/jobs/parallelJob.xml - src/main/resources/jobs/rollbackJob.xml - src/main/resources/jobs/retrySample.xml - src/main/resources/jobs/simpleJob.xml - src/main/resources/simple-job-launcher-context.xml - src/main/resources/jobs/batchUpdateJob.xml - - - - - true - false - - src/main/resources/data-source-context.xml - - - - - true - false - - src/main/resources/data-source-context.xml - - - - - true - false - - src/main/resources/jobs/adhocLoopJob.xml - src/main/resources/data-source-context.xml - src/main/resources/data-source-context-init.xml - src/main/resources/simple-job-launcher-context.xml - - - - - true - false - - src/main/resources/jobs/beanWrapperMapperSampleJob.xml - src/main/resources/data-source-context.xml - src/main/resources/data-source-context-init.xml - src/main/resources/simple-job-launcher-context.xml - - - - - true - false - - src/main/resources/data-source-context.xml - src/main/resources/data-source-context-init.xml - src/main/resources/jobs/compositeProcessorSampleJob.xml - src/main/resources/simple-job-launcher-context.xml - - - - - true - false - - src/main/resources/data-source-context.xml - src/main/resources/jobs/delegatingJob.xml - src/main/resources/simple-job-launcher-context.xml - - - - - true - false - - src/main/resources/jobs/fixedLengthImportJob.xml - src/main/resources/data-source-context.xml - src/main/resources/data-source-context-init.xml - src/main/resources/simple-job-launcher-context.xml - - - - - true - false - - src/main/resources/data-source-context.xml - src/main/resources/jobs/footballJob.xml - src/main/resources/simple-job-launcher-context.xml - - - - - true - false - - src/main/resources/data-source-context.xml - src/main/resources/jobs/hibernateJob.xml - src/main/resources/simple-job-launcher-context.xml - - - - - true - false - - src/main/resources/data-source-context.xml - src/main/resources/jobs/ibatisJob.xml - src/main/resources/simple-job-launcher-context.xml - - - - - true - false - - src/main/resources/jobs/infiniteLoopJob.xml - src/main/resources/data-source-context.xml - src/main/resources/data-source-context-init.xml - src/main/resources/simple-job-launcher-context.xml - - - - - true - false - - src/main/resources/data-source-context.xml - src/main/resources/data-source-context-init.xml - src/main/resources/jobs/multilineJob.xml - src/main/resources/simple-job-launcher-context.xml - - - - - true - false - - src/main/resources/data-source-context.xml - src/main/resources/data-source-context-init.xml - src/main/resources/jobs/multilineOrderInputDescriptors.xml - src/main/resources/jobs/multilineOrderIo.xml - src/main/resources/jobs/multilineOrderJob.xml - src/main/resources/jobs/multilineOrderOutputDescriptors.xml - src/main/resources/simple-job-launcher-context.xml - - - - - true - false - - src/main/resources/data-source-context.xml - src/main/resources/jobs/parallelJob.xml - src/main/resources/simple-job-launcher-context.xml - - - - - true - false - - src/main/resources/data-source-context.xml - src/main/resources/data-source-context-init.xml - src/main/resources/jobs/restartSample.xml - src/main/resources/simple-job-launcher-context.xml - - - - - true - false - - src/main/resources/jobs/retrySample.xml - src/main/resources/data-source-context.xml - src/main/resources/data-source-context-init.xml - src/main/resources/simple-job-launcher-context.xml - - - - - true - false - - src/main/resources/data-source-context.xml - src/main/resources/jobs/simpleJob.xml - src/main/resources/simple-job-launcher-context.xml - - - - - true - false - - src/main/resources/data-source-context.xml - src/main/resources/data-source-context-init.xml - src/main/resources/jobs/tradeJob.xml - src/main/resources/jobs/tradeJobIo.xml - src/main/resources/simple-job-launcher-context.xml - - - - - true - false - - src/main/resources/data-source-context.xml - src/main/resources/data-source-context-init.xml - src/main/resources/jobs/xmlStaxJob.xml - src/main/resources/simple-job-launcher-context.xml - - - - - true - false - - src/main/resources/data-source-context.xml - src/main/resources/data-source-context-init.xml - src/main/resources/jobs/batchUpdateJob.xml - src/main/resources/simple-job-launcher-context.xml - - - - - true - false - - src/main/resources/data-source-context.xml - src/main/resources/jobs/rollbackJob.xml - src/main/resources/jobs/tradeJobIo.xml - src/main/resources/simple-job-launcher-context.xml - - - - + + + 1 + + + + + + + src/main/resources/jobs/fixedLengthImportJob.xml + src/main/resources/jobs/multilineJob.xml + src/main/resources/jobs/multilineOrderInputDescriptors.xml + src/main/resources/jobs/multilineOrderIo.xml + src/main/resources/jobs/multilineOrderJob.xml + src/main/resources/jobs/multilineOrderOutputDescriptors.xml + src/main/resources/jobs/tradeJob.xml + src/main/resources/jobs/tradeJobIo.xml + src/main/resources/jobs/restartSample.xml + src/main/resources/data-source-context.xml + src/main/resources/jobs/beanWrapperMapperSampleJob.xml + src/main/resources/jobs/adhocLoopJob.xml + src/main/resources/jobs/infiniteLoopJob.xml + src/main/resources/data-source-context-init.xml + src/main/resources/jobs/xmlStaxJob.xml + src/main/resources/jobs/hibernateJob.xml + src/main/resources/jobs/ibatisJob.xml + src/main/resources/jobs/compositeProcessorSampleJob.xml + src/main/resources/jobs/footballJob.xml + src/main/resources/beanRefContext.xml + src/main/resources/jobs/delegatingJob.xml + src/main/resources/jobs/parallelJob.xml + src/main/resources/jobs/rollbackJob.xml + src/main/resources/jobs/retrySample.xml + src/main/resources/jobs/simpleJob.xml + src/main/resources/simple-job-launcher-context.xml + src/main/resources/jobs/batchUpdateJob.xml + + + + + true + false + + src/main/resources/data-source-context.xml + + + + + true + false + + src/main/resources/data-source-context.xml + + + + + true + false + + src/main/resources/jobs/adhocLoopJob.xml + src/main/resources/data-source-context.xml + src/main/resources/data-source-context-init.xml + src/main/resources/simple-job-launcher-context.xml + + + + + true + false + + src/main/resources/jobs/beanWrapperMapperSampleJob.xml + src/main/resources/data-source-context.xml + src/main/resources/data-source-context-init.xml + src/main/resources/simple-job-launcher-context.xml + + + + + true + false + + src/main/resources/data-source-context.xml + src/main/resources/data-source-context-init.xml + src/main/resources/jobs/compositeProcessorSampleJob.xml + src/main/resources/simple-job-launcher-context.xml + + + + + true + false + + src/main/resources/data-source-context.xml + src/main/resources/jobs/delegatingJob.xml + src/main/resources/simple-job-launcher-context.xml + + + + + true + false + + src/main/resources/jobs/fixedLengthImportJob.xml + src/main/resources/data-source-context.xml + src/main/resources/data-source-context-init.xml + src/main/resources/simple-job-launcher-context.xml + + + + + true + false + + src/main/resources/data-source-context.xml + src/main/resources/jobs/footballJob.xml + src/main/resources/simple-job-launcher-context.xml + + + + + true + false + + src/main/resources/data-source-context.xml + src/main/resources/jobs/hibernateJob.xml + src/main/resources/simple-job-launcher-context.xml + + + + + true + false + + src/main/resources/data-source-context.xml + src/main/resources/jobs/ibatisJob.xml + src/main/resources/simple-job-launcher-context.xml + + + + + true + false + + src/main/resources/jobs/infiniteLoopJob.xml + src/main/resources/data-source-context.xml + src/main/resources/data-source-context-init.xml + src/main/resources/simple-job-launcher-context.xml + + + + + true + false + + src/main/resources/data-source-context.xml + src/main/resources/data-source-context-init.xml + src/main/resources/jobs/multilineJob.xml + src/main/resources/simple-job-launcher-context.xml + + + + + true + false + + src/main/resources/data-source-context.xml + src/main/resources/data-source-context-init.xml + src/main/resources/jobs/multilineOrderInputDescriptors.xml + src/main/resources/jobs/multilineOrderIo.xml + src/main/resources/jobs/multilineOrderJob.xml + src/main/resources/jobs/multilineOrderOutputDescriptors.xml + src/main/resources/simple-job-launcher-context.xml + + + + + true + false + + src/main/resources/data-source-context.xml + src/main/resources/jobs/parallelJob.xml + src/main/resources/simple-job-launcher-context.xml + + + + + true + false + + src/main/resources/data-source-context.xml + src/main/resources/data-source-context-init.xml + src/main/resources/jobs/restartSample.xml + src/main/resources/simple-job-launcher-context.xml + + + + + true + false + + src/main/resources/jobs/retrySample.xml + src/main/resources/data-source-context.xml + src/main/resources/data-source-context-init.xml + src/main/resources/simple-job-launcher-context.xml + + + + + true + false + + src/main/resources/data-source-context.xml + src/main/resources/jobs/simpleJob.xml + src/main/resources/simple-job-launcher-context.xml + + + + + true + false + + src/main/resources/data-source-context.xml + src/main/resources/data-source-context-init.xml + src/main/resources/jobs/tradeJob.xml + src/main/resources/jobs/tradeJobIo.xml + src/main/resources/simple-job-launcher-context.xml + + + + + true + false + + src/main/resources/data-source-context.xml + src/main/resources/data-source-context-init.xml + src/main/resources/jobs/xmlStaxJob.xml + src/main/resources/simple-job-launcher-context.xml + + + + + true + false + + src/main/resources/data-source-context.xml + src/main/resources/data-source-context-init.xml + src/main/resources/jobs/batchUpdateJob.xml + src/main/resources/simple-job-launcher-context.xml + + + + + true + false + + src/main/resources/data-source-context.xml + src/main/resources/jobs/rollbackJob.xml + src/main/resources/jobs/tradeJobIo.xml + src/main/resources/simple-job-launcher-context.xml + + + + diff --git a/spring-batch-samples/pom.xml b/spring-batch-samples/pom.xml index d5a9dbcfe4..98982f56f8 100644 --- a/spring-batch-samples/pom.xml +++ b/spring-batch-samples/pom.xml @@ -1,370 +1,370 @@ - - 4.0.0 - spring-batch-samples - jar - Samples - - - - - - - org.springframework.batch - spring-batch - 1.0.0.rc1-SNAPSHOT - .. - - - - - clover - - false - - - - - maven-clover-plugin - - - - - - - maven-clover-plugin - - - - - - - - - org.springframework.batch - spring-batch-execution - ${project.version} - - - aspectj - aspectjrt - - - junit - junit - - - org.springmodules - spring-modules-validation - 0.8 - - - rhino - js - - - commons-validator - commons-validator - - - org.springframework - spring - - - - - quartz - quartz - 1.5.1 - - - asm - asm-all - 2.2.3 - test - - - aspectj - aspectjweaver - test - - - hsqldb - hsqldb - test - - - commons-io - commons-io - test - - - commons-dbcp - commons-dbcp - test - - - org.springframework.ws - spring-oxm - 1.0.0 - true - - - org.springframework - spring-beans - - - org.springframework - spring-core - - - - - geronimo-spec - geronimo-spec-j2ee - 1.4-rc4 - test - - - easymock - easymock - - - - com.thoughtworks.xstream - xstream - test - - - - stax - stax - test - - - xmlunit - xmlunit - test - 1.1 - - - org.hibernate - hibernate - true - - - - org.apache.geronimo.specs - geronimo-jta_1.1_spec - 1.1 - provided - - - - cglib - cglib-nodep - true - - - backport-util-concurrent - backport-util-concurrent - true - - - org.apache.ibatis - ibatis-sqlmap - 2.3.0 - true - - - org.apache.derby - derby - 10.2.1.6 - test - - - - org.springframework - spring-core - - - org.springframework - spring-test - test - - - org.springframework - spring-web - test - - - - - mx4j - mx4j - 3.0.2 - optional - - - - - - - org.apache.maven.plugins - maven-antrun-plugin - - - generate-sql - generate-sources - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - run - - - - - - + + 4.0.0 + spring-batch-samples + jar + Samples + + + + + + + org.springframework.batch + spring-batch + 1.0.0.rc1-SNAPSHOT + .. + + + + + clover + + false + + + + + maven-clover-plugin + + + + + + + maven-clover-plugin + + + + + + + + + org.springframework.batch + spring-batch-execution + ${project.version} + + + aspectj + aspectjrt + + + junit + junit + + + org.springmodules + spring-modules-validation + 0.8 + + + rhino + js + + + commons-validator + commons-validator + + + org.springframework + spring + + + + + quartz + quartz + 1.5.1 + + + asm + asm-all + 2.2.3 + test + + + aspectj + aspectjweaver + test + + + hsqldb + hsqldb + test + + + commons-io + commons-io + test + + + commons-dbcp + commons-dbcp + test + + + org.springframework.ws + spring-oxm + 1.0.0 + true + + + org.springframework + spring-beans + + + org.springframework + spring-core + + + + + geronimo-spec + geronimo-spec-j2ee + 1.4-rc4 + test + + + easymock + easymock + + + + com.thoughtworks.xstream + xstream + test + + + + stax + stax + test + + + xmlunit + xmlunit + test + 1.1 + + + org.hibernate + hibernate + true + + + + org.apache.geronimo.specs + geronimo-jta_1.1_spec + 1.1 + provided + + + + cglib + cglib-nodep + true + + + backport-util-concurrent + backport-util-concurrent + true + + + org.apache.ibatis + ibatis-sqlmap + 2.3.0 + true + + + org.apache.derby + derby + 10.2.1.6 + test + + + + org.springframework + spring-core + + + org.springframework + spring-test + test + + + org.springframework + spring-web + test + + + + + mx4j + mx4j + 3.0.2 + optional + + + + + + + org.apache.maven.plugins + maven-antrun-plugin + + + generate-sql + generate-sources + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + run + + + + + + \ No newline at end of file diff --git a/spring-batch-samples/server.properties b/spring-batch-samples/server.properties index 7397ea159c..f40f3db454 100644 --- a/spring-batch-samples/server.properties +++ b/spring-batch-samples/server.properties @@ -1,5 +1,5 @@ -server.port=9005 -server.trace=true - -server.database.0=file:target/hsqldb-data/samples -server.dbname.0=samples +server.port=9005 +server.trace=true + +server.database.0=file:target/hsqldb-data/samples +server.dbname.0=samples diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/dao/HibernateCreditDao.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/dao/HibernateCreditDao.java index 97839a1cac..0fcbb51240 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/dao/HibernateCreditDao.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/dao/HibernateCreditDao.java @@ -1,112 +1,112 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.sample.dao; - -import java.util.ArrayList; -import java.util.List; - -import org.springframework.batch.repeat.ExitStatus; -import org.springframework.batch.repeat.RepeatContext; -import org.springframework.batch.repeat.RepeatListener; -import org.springframework.batch.sample.domain.CustomerCredit; -import org.springframework.orm.hibernate3.support.HibernateDaoSupport; - -/** - * @author Lucas Ward - * @author Dave Syer - * - */ -public class HibernateCreditDao extends HibernateDaoSupport implements - CustomerCreditDao, RepeatListener { - - private int failOnFlush = -1; - private List errors = new ArrayList(); - - /** - * Public accessor for the errors property. - * - * @return the errors - a list of Throwable instances - */ - public List getErrors() { - return errors; - } - - /* - * (non-Javadoc) - * - * @see org.springframework.batch.sample.dao.CustomerCreditWriter#write(org.springframework.batch.sample.domain.CustomerCredit) - */ - public void writeCredit(CustomerCredit customerCredit) { - if (customerCredit.getId() == failOnFlush) { - // try to insert one with a duplicate ID - CustomerCredit newCredit = new CustomerCredit(); - newCredit.setId(customerCredit.getId()); - newCredit.setName(customerCredit.getName()); - newCredit.setCredit(customerCredit.getCredit()); - getHibernateTemplate().save(newCredit); - } else { - getHibernateTemplate().update(customerCredit); - } - } - - /* - * (non-Javadoc) - * - * @see org.springframework.batch.io.OutputSource#write(java.lang.Object) - */ - public void write(Object output) { - writeCredit((CustomerCredit) output); - } - - /** - * Public setter for the failOnFlush property. - * - * @param failOnFlush - * the ID of the record you want to fail on flush (for testing) - */ - public void setFailOnFlush(int failOnFlush) { - this.failOnFlush = failOnFlush; - } - - public void onError(RepeatContext context, Throwable e) { - errors.add(e); - } - - /* (non-Javadoc) - * @see org.springframework.batch.repeat.RepeatInterceptor#after(org.springframework.batch.repeat.RepeatContext, org.springframework.batch.repeat.ExitStatus) - */ - public void after(RepeatContext context, ExitStatus result) { - } - - /* (non-Javadoc) - * @see org.springframework.batch.repeat.RepeatInterceptor#before(org.springframework.batch.repeat.RepeatContext) - */ - public void before(RepeatContext context) { - } - - /* (non-Javadoc) - * @see org.springframework.batch.repeat.RepeatInterceptor#close(org.springframework.batch.repeat.RepeatContext) - */ - public void close(RepeatContext context) { - } - - /* (non-Javadoc) - * @see org.springframework.batch.repeat.RepeatInterceptor#open(org.springframework.batch.repeat.RepeatContext) - */ - public void open(RepeatContext context) { - } - -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.sample.dao; + +import java.util.ArrayList; +import java.util.List; + +import org.springframework.batch.repeat.ExitStatus; +import org.springframework.batch.repeat.RepeatContext; +import org.springframework.batch.repeat.RepeatListener; +import org.springframework.batch.sample.domain.CustomerCredit; +import org.springframework.orm.hibernate3.support.HibernateDaoSupport; + +/** + * @author Lucas Ward + * @author Dave Syer + * + */ +public class HibernateCreditDao extends HibernateDaoSupport implements + CustomerCreditDao, RepeatListener { + + private int failOnFlush = -1; + private List errors = new ArrayList(); + + /** + * Public accessor for the errors property. + * + * @return the errors - a list of Throwable instances + */ + public List getErrors() { + return errors; + } + + /* + * (non-Javadoc) + * + * @see org.springframework.batch.sample.dao.CustomerCreditWriter#write(org.springframework.batch.sample.domain.CustomerCredit) + */ + public void writeCredit(CustomerCredit customerCredit) { + if (customerCredit.getId() == failOnFlush) { + // try to insert one with a duplicate ID + CustomerCredit newCredit = new CustomerCredit(); + newCredit.setId(customerCredit.getId()); + newCredit.setName(customerCredit.getName()); + newCredit.setCredit(customerCredit.getCredit()); + getHibernateTemplate().save(newCredit); + } else { + getHibernateTemplate().update(customerCredit); + } + } + + /* + * (non-Javadoc) + * + * @see org.springframework.batch.io.OutputSource#write(java.lang.Object) + */ + public void write(Object output) { + writeCredit((CustomerCredit) output); + } + + /** + * Public setter for the failOnFlush property. + * + * @param failOnFlush + * the ID of the record you want to fail on flush (for testing) + */ + public void setFailOnFlush(int failOnFlush) { + this.failOnFlush = failOnFlush; + } + + public void onError(RepeatContext context, Throwable e) { + errors.add(e); + } + + /* (non-Javadoc) + * @see org.springframework.batch.repeat.RepeatInterceptor#after(org.springframework.batch.repeat.RepeatContext, org.springframework.batch.repeat.ExitStatus) + */ + public void after(RepeatContext context, ExitStatus result) { + } + + /* (non-Javadoc) + * @see org.springframework.batch.repeat.RepeatInterceptor#before(org.springframework.batch.repeat.RepeatContext) + */ + public void before(RepeatContext context) { + } + + /* (non-Javadoc) + * @see org.springframework.batch.repeat.RepeatInterceptor#close(org.springframework.batch.repeat.RepeatContext) + */ + public void close(RepeatContext context) { + } + + /* (non-Javadoc) + * @see org.springframework.batch.repeat.RepeatInterceptor#open(org.springframework.batch.repeat.RepeatContext) + */ + public void open(RepeatContext context) { + } + +} diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/dao/IbatisCustomerCreditDao.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/dao/IbatisCustomerCreditDao.java index 0dd6e57a80..510c8edadb 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/dao/IbatisCustomerCreditDao.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/dao/IbatisCustomerCreditDao.java @@ -1,55 +1,55 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.sample.dao; - -import org.springframework.batch.sample.domain.CustomerCredit; -import org.springframework.orm.ibatis.support.SqlMapClientDaoSupport; - -/** - * @author Lucas Ward - * - */ -public class IbatisCustomerCreditDao extends SqlMapClientDaoSupport - implements CustomerCreditDao { - - String statementId; - - /* (non-Javadoc) - * @see org.springframework.batch.sample.dao.CustomerCreditWriter#write(org.springframework.batch.sample.domain.CustomerCredit) - */ - public void writeCredit(CustomerCredit customerCredit) { - - getSqlMapClientTemplate().update(statementId, customerCredit); - } - - /* (non-Javadoc) - * @see org.springframework.batch.item.ResourceLifecycle#close() - */ - public void close() { - } - - /* (non-Javadoc) - * @see org.springframework.batch.item.ResourceLifecycle#open() - */ - public void open() { - } - - - public void setStatementId(String statementId) { - this.statementId = statementId; - } - -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.sample.dao; + +import org.springframework.batch.sample.domain.CustomerCredit; +import org.springframework.orm.ibatis.support.SqlMapClientDaoSupport; + +/** + * @author Lucas Ward + * + */ +public class IbatisCustomerCreditDao extends SqlMapClientDaoSupport + implements CustomerCreditDao { + + String statementId; + + /* (non-Javadoc) + * @see org.springframework.batch.sample.dao.CustomerCreditWriter#write(org.springframework.batch.sample.domain.CustomerCredit) + */ + public void writeCredit(CustomerCredit customerCredit) { + + getSqlMapClientTemplate().update(statementId, customerCredit); + } + + /* (non-Javadoc) + * @see org.springframework.batch.item.ResourceLifecycle#close() + */ + public void close() { + } + + /* (non-Javadoc) + * @see org.springframework.batch.item.ResourceLifecycle#open() + */ + public void open() { + } + + + public void setStatementId(String statementId) { + this.statementId = statementId; + } + +} diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/dao/JdbcGameDao.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/dao/JdbcGameDao.java index 63e0d3ac6e..9a1ef86ff0 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/dao/JdbcGameDao.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/dao/JdbcGameDao.java @@ -1,45 +1,45 @@ -package org.springframework.batch.sample.dao; - -import org.springframework.batch.item.ItemWriter; -import org.springframework.batch.item.exception.ClearFailedException; -import org.springframework.batch.item.exception.FlushFailedException; -import org.springframework.batch.sample.domain.Game; -import org.springframework.jdbc.core.support.JdbcDaoSupport; -import org.springframework.util.Assert; - -public class JdbcGameDao extends JdbcDaoSupport implements ItemWriter { - - private static final String INSERT_GAME = "INSERT into GAMES(player_id,year_no,team,week,opponent," - + "completes,attempts,passing_yards,passing_td,interceptions,rushes,rush_yards," - + "receptions,receptions_yards,total_td) values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"; - - public void write(Object output) { - Assert.isTrue(output instanceof Game, - "Only Game objects can be written out" + "using this Dao"); - - Game game = (Game) output; - - Object[] args = new Object[] { game.getId(), - new Integer(game.getYear()), game.getTeam(), - new Integer(game.getWeek()), game.getOpponent(), - new Integer(game.getCompletes()), - new Integer(game.getAttempts()), - new Integer(game.getPassingYards()), - new Integer(game.getPassingTd()), - new Integer(game.getInterceptions()), - new Integer(game.getRushes()), - new Integer(game.getRushYards()), - new Integer(game.getReceptions()), - new Integer(game.getReceptionYards()), - new Integer(game.getTotalTd()) }; - - this.getJdbcTemplate().update(INSERT_GAME, args); - } - - public void clear() throws ClearFailedException { - } - - public void flush() throws FlushFailedException { - } - -} +package org.springframework.batch.sample.dao; + +import org.springframework.batch.item.ItemWriter; +import org.springframework.batch.item.exception.ClearFailedException; +import org.springframework.batch.item.exception.FlushFailedException; +import org.springframework.batch.sample.domain.Game; +import org.springframework.jdbc.core.support.JdbcDaoSupport; +import org.springframework.util.Assert; + +public class JdbcGameDao extends JdbcDaoSupport implements ItemWriter { + + private static final String INSERT_GAME = "INSERT into GAMES(player_id,year_no,team,week,opponent," + + "completes,attempts,passing_yards,passing_td,interceptions,rushes,rush_yards," + + "receptions,receptions_yards,total_td) values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"; + + public void write(Object output) { + Assert.isTrue(output instanceof Game, + "Only Game objects can be written out" + "using this Dao"); + + Game game = (Game) output; + + Object[] args = new Object[] { game.getId(), + new Integer(game.getYear()), game.getTeam(), + new Integer(game.getWeek()), game.getOpponent(), + new Integer(game.getCompletes()), + new Integer(game.getAttempts()), + new Integer(game.getPassingYards()), + new Integer(game.getPassingTd()), + new Integer(game.getInterceptions()), + new Integer(game.getRushes()), + new Integer(game.getRushYards()), + new Integer(game.getReceptions()), + new Integer(game.getReceptionYards()), + new Integer(game.getTotalTd()) }; + + this.getJdbcTemplate().update(INSERT_GAME, args); + } + + public void clear() throws ClearFailedException { + } + + public void flush() throws FlushFailedException { + } + +} diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/dao/JdbcPlayerDao.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/dao/JdbcPlayerDao.java index 23c208f9c6..d913d0a483 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/dao/JdbcPlayerDao.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/dao/JdbcPlayerDao.java @@ -1,27 +1,27 @@ -/** - * - */ -package org.springframework.batch.sample.dao; - -import org.springframework.batch.sample.domain.Player; -import org.springframework.jdbc.core.support.JdbcDaoSupport; - -/** - * @author Lucas Ward - * - */ -public class JdbcPlayerDao extends JdbcDaoSupport implements PlayerDao { - - public static final String INSERT_PLAYER = "INSERT into players(player_id, " + - "last_name, first_name, pos, year_of_birth, year_drafted)" + - " values (?,?,?,?,?,?)"; - - public void savePlayer(Player player) { - - getJdbcTemplate().update(INSERT_PLAYER, - new Object[]{player.getID(),player.getLastName(), - player.getFirstName(), player.getPosition(), - new Integer(player.getBirthYear()), - new Integer(player.getDebutYear())}); - } -} +/** + * + */ +package org.springframework.batch.sample.dao; + +import org.springframework.batch.sample.domain.Player; +import org.springframework.jdbc.core.support.JdbcDaoSupport; + +/** + * @author Lucas Ward + * + */ +public class JdbcPlayerDao extends JdbcDaoSupport implements PlayerDao { + + public static final String INSERT_PLAYER = "INSERT into players(player_id, " + + "last_name, first_name, pos, year_of_birth, year_drafted)" + + " values (?,?,?,?,?,?)"; + + public void savePlayer(Player player) { + + getJdbcTemplate().update(INSERT_PLAYER, + new Object[]{player.getID(),player.getLastName(), + player.getFirstName(), player.getPosition(), + new Integer(player.getBirthYear()), + new Integer(player.getDebutYear())}); + } +} diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/dao/JdbcPlayerSummaryDao.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/dao/JdbcPlayerSummaryDao.java index 1e9f3b7bbc..7dd77d1466 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/dao/JdbcPlayerSummaryDao.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/dao/JdbcPlayerSummaryDao.java @@ -1,42 +1,42 @@ -package org.springframework.batch.sample.dao; - -import org.springframework.batch.item.ItemWriter; -import org.springframework.batch.item.exception.ClearFailedException; -import org.springframework.batch.item.exception.FlushFailedException; -import org.springframework.batch.sample.domain.PlayerSummary; -import org.springframework.jdbc.core.support.JdbcDaoSupport; -import org.springframework.util.Assert; - -public class JdbcPlayerSummaryDao extends JdbcDaoSupport implements ItemWriter { - - private static final String INSERT_SUMMARY = "INSERT into PLAYER_SUMMARY(ID,YEAR_NO,COMPLETES,ATTEMPTS," + - "PASSING_YARDS,PASSING_TD,INTERCEPTIONS,RUSHES,RUSH_YARDS,RECEPTIONS,RECEPTIONS_YARDS," + - "TOTAL_TD) values(?,?,?,?,?,?,?,?,?,?,?,?)"; - - public void write(Object output) { - - Assert.isInstanceOf(PlayerSummary.class, output, JdbcPlayerSummaryDao.class.getName() + " only " + - "supports outputing " + PlayerSummary.class.getName() + " instances."); - - PlayerSummary summary = (PlayerSummary)output; - - Object[] args = new Object[]{summary.getId(), new Integer(summary.getYear()), - new Integer(summary.getCompletes()), new Integer(summary.getAttempts()), - new Integer(summary.getPassingYards()), new Integer(summary.getPassingTd()), - new Integer(summary.getInterceptions()), new Integer(summary.getRushes()), - new Integer(summary.getRushYards()), new Integer(summary.getReceptions()), - new Integer(summary.getReceptionYards()), new Integer(summary.getTotalTd()) }; - - getJdbcTemplate().update(INSERT_SUMMARY, args); - } - - public void close() throws Exception { - } - - public void clear() throws ClearFailedException { - } - - public void flush() throws FlushFailedException { - } - -} +package org.springframework.batch.sample.dao; + +import org.springframework.batch.item.ItemWriter; +import org.springframework.batch.item.exception.ClearFailedException; +import org.springframework.batch.item.exception.FlushFailedException; +import org.springframework.batch.sample.domain.PlayerSummary; +import org.springframework.jdbc.core.support.JdbcDaoSupport; +import org.springframework.util.Assert; + +public class JdbcPlayerSummaryDao extends JdbcDaoSupport implements ItemWriter { + + private static final String INSERT_SUMMARY = "INSERT into PLAYER_SUMMARY(ID,YEAR_NO,COMPLETES,ATTEMPTS," + + "PASSING_YARDS,PASSING_TD,INTERCEPTIONS,RUSHES,RUSH_YARDS,RECEPTIONS,RECEPTIONS_YARDS," + + "TOTAL_TD) values(?,?,?,?,?,?,?,?,?,?,?,?)"; + + public void write(Object output) { + + Assert.isInstanceOf(PlayerSummary.class, output, JdbcPlayerSummaryDao.class.getName() + " only " + + "supports outputing " + PlayerSummary.class.getName() + " instances."); + + PlayerSummary summary = (PlayerSummary)output; + + Object[] args = new Object[]{summary.getId(), new Integer(summary.getYear()), + new Integer(summary.getCompletes()), new Integer(summary.getAttempts()), + new Integer(summary.getPassingYards()), new Integer(summary.getPassingTd()), + new Integer(summary.getInterceptions()), new Integer(summary.getRushes()), + new Integer(summary.getRushYards()), new Integer(summary.getReceptions()), + new Integer(summary.getReceptionYards()), new Integer(summary.getTotalTd()) }; + + getJdbcTemplate().update(INSERT_SUMMARY, args); + } + + public void close() throws Exception { + } + + public void clear() throws ClearFailedException { + } + + public void flush() throws FlushFailedException { + } + +} diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/dao/PlayerDao.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/dao/PlayerDao.java index 96f005b39e..4784138638 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/dao/PlayerDao.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/dao/PlayerDao.java @@ -1,8 +1,8 @@ -package org.springframework.batch.sample.dao; - -import org.springframework.batch.sample.domain.Player; - -public interface PlayerDao { - - void savePlayer(Player player); -} +package org.springframework.batch.sample.dao; + +import org.springframework.batch.sample.domain.Player; + +public interface PlayerDao { + + void savePlayer(Player player); +} diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/CustomerCredit.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/CustomerCredit.java index 799b92fedc..863fecc2ef 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/CustomerCredit.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/CustomerCredit.java @@ -1,70 +1,70 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.batch.sample.domain; - -import java.math.BigDecimal; - -import org.apache.commons.lang.builder.EqualsBuilder; -import org.apache.commons.lang.builder.HashCodeBuilder; - - -public class CustomerCredit { - private int id; - private String name; - private BigDecimal credit; - - public String toString() { - return "CustomerCredit [id=" + id +",name=" + name + ", credit=" + credit + "]"; - } - - public BigDecimal getCredit() { - return credit; - } - - public int getId() { - return id; - } - - public void setId(int id) { - this.id = id; - } - - public void setCredit(BigDecimal credit) { - this.credit = credit; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public void increaseCreditBy(BigDecimal sum) { - this.credit = this.credit.add(sum); - } - - public boolean equals(Object o) { - return EqualsBuilder.reflectionEquals(this, o); - } - - public int hashCode() { - return HashCodeBuilder.reflectionHashCode(this); - } - -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.batch.sample.domain; + +import java.math.BigDecimal; + +import org.apache.commons.lang.builder.EqualsBuilder; +import org.apache.commons.lang.builder.HashCodeBuilder; + + +public class CustomerCredit { + private int id; + private String name; + private BigDecimal credit; + + public String toString() { + return "CustomerCredit [id=" + id +",name=" + name + ", credit=" + credit + "]"; + } + + public BigDecimal getCredit() { + return credit; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public void setCredit(BigDecimal credit) { + this.credit = credit; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public void increaseCreditBy(BigDecimal sum) { + this.credit = this.credit.add(sum); + } + + public boolean equals(Object o) { + return EqualsBuilder.reflectionEquals(this, o); + } + + public int hashCode() { + return HashCodeBuilder.reflectionHashCode(this); + } + +} diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/Game.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/Game.java index d85d165556..82d8f5ed26 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/Game.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/Game.java @@ -1,215 +1,215 @@ -package org.springframework.batch.sample.domain; - -import java.io.Serializable; - -import org.apache.commons.lang.builder.EqualsBuilder; - -public class Game implements Serializable { - - private String id; - private int year; - private String team; - private int week; - private String opponent; - private int completes; - private int attempts; - private int passingYards; - private int passingTd; - private int interceptions; - private int rushes; - private int rushYards; - private int receptions; - private int receptionYards; - private int totalTd; - /** - * @return the id - */ - public String getId() { - return id; - } - /** - * @return the year - */ - public int getYear() { - return year; - } - /** - * @return the team - */ - public String getTeam() { - return team; - } - /** - * @return the week - */ - public int getWeek() { - return week; - } - /** - * @return the opponent - */ - public String getOpponent() { - return opponent; - } - /** - * @return the completes - */ - public int getCompletes() { - return completes; - } - /** - * @return the attempts - */ - public int getAttempts() { - return attempts; - } - /** - * @return the passingYards - */ - public int getPassingYards() { - return passingYards; - } - /** - * @return the passingTd - */ - public int getPassingTd() { - return passingTd; - } - /** - * @return the interceptions - */ - public int getInterceptions() { - return interceptions; - } - /** - * @return the rushes - */ - public int getRushes() { - return rushes; - } - /** - * @return the rushYards - */ - public int getRushYards() { - return rushYards; - } - /** - * @return the receptions - */ - public int getReceptions() { - return receptions; - } - /** - * @return the receptionYards - */ - public int getReceptionYards() { - return receptionYards; - } - /** - * @return the totalTd - */ - public int getTotalTd() { - return totalTd; - } - /** - * @param id the id to set - */ - public void setId(String id) { - this.id = id; - } - /** - * @param year the year to set - */ - public void setYear(int year) { - this.year = year; - } - /** - * @param team the team to set - */ - public void setTeam(String team) { - this.team = team; - } - /** - * @param week the week to set - */ - public void setWeek(int week) { - this.week = week; - } - /** - * @param opponent the opponent to set - */ - public void setOpponent(String opponent) { - this.opponent = opponent; - } - /** - * @param completes the completes to set - */ - public void setCompletes(int completes) { - this.completes = completes; - } - /** - * @param attempts the attempts to set - */ - public void setAttempts(int attempts) { - this.attempts = attempts; - } - /** - * @param passingYards the passingYards to set - */ - public void setPassingYards(int passingYards) { - this.passingYards = passingYards; - } - /** - * @param passingTd the passingTd to set - */ - public void setPassingTd(int passingTd) { - this.passingTd = passingTd; - } - /** - * @param interceptions the interceptions to set - */ - public void setInterceptions(int interceptions) { - this.interceptions = interceptions; - } - /** - * @param rushes the rushes to set - */ - public void setRushes(int rushes) { - this.rushes = rushes; - } - /** - * @param rushYards the rushYards to set - */ - public void setRushYards(int rushYards) { - this.rushYards = rushYards; - } - /** - * @param receptions the receptions to set - */ - public void setReceptions(int receptions) { - this.receptions = receptions; - } - /** - * @param receptionYards the receptionYards to set - */ - public void setReceptionYards(int receptionYards) { - this.receptionYards = receptionYards; - } - /** - * @param totalTd the totalTd to set - */ - public void setTotalTd(int totalTd) { - this.totalTd = totalTd; - } - - - public String toString() { - - return "Game: ID=" + id + " " + team + " vs. " + opponent + - " - " + year; - } - - public boolean equals(Object obj) { - return EqualsBuilder.reflectionEquals(this, obj); - } -} +package org.springframework.batch.sample.domain; + +import java.io.Serializable; + +import org.apache.commons.lang.builder.EqualsBuilder; + +public class Game implements Serializable { + + private String id; + private int year; + private String team; + private int week; + private String opponent; + private int completes; + private int attempts; + private int passingYards; + private int passingTd; + private int interceptions; + private int rushes; + private int rushYards; + private int receptions; + private int receptionYards; + private int totalTd; + /** + * @return the id + */ + public String getId() { + return id; + } + /** + * @return the year + */ + public int getYear() { + return year; + } + /** + * @return the team + */ + public String getTeam() { + return team; + } + /** + * @return the week + */ + public int getWeek() { + return week; + } + /** + * @return the opponent + */ + public String getOpponent() { + return opponent; + } + /** + * @return the completes + */ + public int getCompletes() { + return completes; + } + /** + * @return the attempts + */ + public int getAttempts() { + return attempts; + } + /** + * @return the passingYards + */ + public int getPassingYards() { + return passingYards; + } + /** + * @return the passingTd + */ + public int getPassingTd() { + return passingTd; + } + /** + * @return the interceptions + */ + public int getInterceptions() { + return interceptions; + } + /** + * @return the rushes + */ + public int getRushes() { + return rushes; + } + /** + * @return the rushYards + */ + public int getRushYards() { + return rushYards; + } + /** + * @return the receptions + */ + public int getReceptions() { + return receptions; + } + /** + * @return the receptionYards + */ + public int getReceptionYards() { + return receptionYards; + } + /** + * @return the totalTd + */ + public int getTotalTd() { + return totalTd; + } + /** + * @param id the id to set + */ + public void setId(String id) { + this.id = id; + } + /** + * @param year the year to set + */ + public void setYear(int year) { + this.year = year; + } + /** + * @param team the team to set + */ + public void setTeam(String team) { + this.team = team; + } + /** + * @param week the week to set + */ + public void setWeek(int week) { + this.week = week; + } + /** + * @param opponent the opponent to set + */ + public void setOpponent(String opponent) { + this.opponent = opponent; + } + /** + * @param completes the completes to set + */ + public void setCompletes(int completes) { + this.completes = completes; + } + /** + * @param attempts the attempts to set + */ + public void setAttempts(int attempts) { + this.attempts = attempts; + } + /** + * @param passingYards the passingYards to set + */ + public void setPassingYards(int passingYards) { + this.passingYards = passingYards; + } + /** + * @param passingTd the passingTd to set + */ + public void setPassingTd(int passingTd) { + this.passingTd = passingTd; + } + /** + * @param interceptions the interceptions to set + */ + public void setInterceptions(int interceptions) { + this.interceptions = interceptions; + } + /** + * @param rushes the rushes to set + */ + public void setRushes(int rushes) { + this.rushes = rushes; + } + /** + * @param rushYards the rushYards to set + */ + public void setRushYards(int rushYards) { + this.rushYards = rushYards; + } + /** + * @param receptions the receptions to set + */ + public void setReceptions(int receptions) { + this.receptions = receptions; + } + /** + * @param receptionYards the receptionYards to set + */ + public void setReceptionYards(int receptionYards) { + this.receptionYards = receptionYards; + } + /** + * @param totalTd the totalTd to set + */ + public void setTotalTd(int totalTd) { + this.totalTd = totalTd; + } + + + public String toString() { + + return "Game: ID=" + id + " " + team + " vs. " + opponent + + " - " + year; + } + + public boolean equals(Object obj) { + return EqualsBuilder.reflectionEquals(this, obj); + } +} diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/PersonService.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/PersonService.java index 9c2220220a..1145eeb0b1 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/PersonService.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/PersonService.java @@ -1,79 +1,79 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.batch.sample.domain; - -import java.util.ArrayList; -import java.util.List; - -import org.springframework.batch.item.ItemReader; -import org.springframework.batch.item.ItemWriter; - -/** - * Custom class that contains logic that would normally be be contained in - * {@link ItemReader} and {@link ItemWriter}. - * - * @author tomas.slanina - * @author Robert Kasanicky - */ -public class PersonService { - - private static final int GENERATION_LIMIT = 10; - - private int generatedCounter = 0; - - private int processedCounter = 0; - - public Person getData() { - if (generatedCounter >= GENERATION_LIMIT) - return null; - - Person person = new Person(); - Address address = new Address(); - Child child = new Child(); - List children = new ArrayList(1); - - children.add(child); - - person.setFirstName("John" + generatedCounter); - person.setAge(20 + generatedCounter); - address.setCity("Johnsville" + generatedCounter); - child.setName("Little Johny" + generatedCounter); - - person.setAddress(address); - person.setChildren(children); - - generatedCounter++; - - return person; - } - - /** - * Badly designed method signature which accepts multiple implicitly related - * arguments instead of a single Person argument. - */ - public void processPerson(String name, String city) { - processedCounter++; - } - - public int getReturnedCount() { - return generatedCounter; - } - - public int getReceivedCount() { - return processedCounter; - } -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.batch.sample.domain; + +import java.util.ArrayList; +import java.util.List; + +import org.springframework.batch.item.ItemReader; +import org.springframework.batch.item.ItemWriter; + +/** + * Custom class that contains logic that would normally be be contained in + * {@link ItemReader} and {@link ItemWriter}. + * + * @author tomas.slanina + * @author Robert Kasanicky + */ +public class PersonService { + + private static final int GENERATION_LIMIT = 10; + + private int generatedCounter = 0; + + private int processedCounter = 0; + + public Person getData() { + if (generatedCounter >= GENERATION_LIMIT) + return null; + + Person person = new Person(); + Address address = new Address(); + Child child = new Child(); + List children = new ArrayList(1); + + children.add(child); + + person.setFirstName("John" + generatedCounter); + person.setAge(20 + generatedCounter); + address.setCity("Johnsville" + generatedCounter); + child.setName("Little Johny" + generatedCounter); + + person.setAddress(address); + person.setChildren(children); + + generatedCounter++; + + return person; + } + + /** + * Badly designed method signature which accepts multiple implicitly related + * arguments instead of a single Person argument. + */ + public void processPerson(String name, String city) { + processedCounter++; + } + + public int getReturnedCount() { + return generatedCounter; + } + + public int getReceivedCount() { + return processedCounter; + } +} diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/Player.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/Player.java index 5a9594913d..f798f41566 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/Player.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/Player.java @@ -1,64 +1,64 @@ -package org.springframework.batch.sample.domain; - -import java.io.Serializable; - -public class Player implements Serializable { - - private String ID; - private String lastName; - private String firstName; - private String position; - private int birthYear; - private int debutYear; - - public String toString() { - - return "PLAYER:ID=" + ID + ",Last Name=" + lastName + - ",First Name=" + firstName + ",Position=" + position + - ",Birth Year=" + birthYear + ",DebutYear=" + - debutYear; - } - - public String getID() { - return ID; - } - public String getLastName() { - return lastName; - } - public String getFirstName() { - return firstName; - } - public String getPosition() { - return position; - } - public int getBirthYear() { - return birthYear; - } - public int getDebutYear() { - return debutYear; - } - public void setID(String id) { - ID = id; - } - public void setLastName(String lastName) { - this.lastName = lastName; - } - public void setFirstName(String firstName) { - this.firstName = firstName; - } - public void setPosition(String position) { - this.position = position; - } - public void setBirthYear(int birthYear) { - this.birthYear = birthYear; - } - public void setDebutYear(int debutYear) { - this.debutYear = debutYear; - } - - - - - - -} +package org.springframework.batch.sample.domain; + +import java.io.Serializable; + +public class Player implements Serializable { + + private String ID; + private String lastName; + private String firstName; + private String position; + private int birthYear; + private int debutYear; + + public String toString() { + + return "PLAYER:ID=" + ID + ",Last Name=" + lastName + + ",First Name=" + firstName + ",Position=" + position + + ",Birth Year=" + birthYear + ",DebutYear=" + + debutYear; + } + + public String getID() { + return ID; + } + public String getLastName() { + return lastName; + } + public String getFirstName() { + return firstName; + } + public String getPosition() { + return position; + } + public int getBirthYear() { + return birthYear; + } + public int getDebutYear() { + return debutYear; + } + public void setID(String id) { + ID = id; + } + public void setLastName(String lastName) { + this.lastName = lastName; + } + public void setFirstName(String firstName) { + this.firstName = firstName; + } + public void setPosition(String position) { + this.position = position; + } + public void setBirthYear(int birthYear) { + this.birthYear = birthYear; + } + public void setDebutYear(int debutYear) { + this.debutYear = debutYear; + } + + + + + + +} diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/PlayerSummary.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/PlayerSummary.java index bbadf93dc9..5fe1caf9dc 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/PlayerSummary.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/PlayerSummary.java @@ -1,108 +1,108 @@ -package org.springframework.batch.sample.domain; - -import org.apache.commons.lang.builder.EqualsBuilder; - -/** - * Domain object representing the summary of a given Player's - * year. - * - * @author Lucas Ward - * - */ -public class PlayerSummary { - - private String id; - private int year; - private int completes; - private int attempts; - private int passingYards; - private int passingTd; - private int interceptions; - private int rushes; - private int rushYards; - private int receptions; - private int receptionYards; - private int totalTd; - - public String getId() { - return id; - } - public void setId(String id) { - this.id = id; - } - public int getYear() { - return year; - } - public void setYear(int year) { - this.year = year; - } - public int getCompletes() { - return completes; - } - public void setCompletes(int completes) { - this.completes = completes; - } - public int getAttempts() { - return attempts; - } - public void setAttempts(int attempts) { - this.attempts = attempts; - } - public int getPassingYards() { - return passingYards; - } - public void setPassingYards(int passingYards) { - this.passingYards = passingYards; - } - public int getPassingTd() { - return passingTd; - } - public void setPassingTd(int passingTd) { - this.passingTd = passingTd; - } - public int getInterceptions() { - return interceptions; - } - public void setInterceptions(int interceptions) { - this.interceptions = interceptions; - } - public int getRushes() { - return rushes; - } - public void setRushes(int rushes) { - this.rushes = rushes; - } - public int getRushYards() { - return rushYards; - } - public void setRushYards(int rushYards) { - this.rushYards = rushYards; - } - public int getReceptions() { - return receptions; - } - public void setReceptions(int receptions) { - this.receptions = receptions; - } - public int getReceptionYards() { - return receptionYards; - } - public void setReceptionYards(int receptionYards) { - this.receptionYards = receptionYards; - } - public int getTotalTd() { - return totalTd; - } - public void setTotalTd(int totalTd) { - this.totalTd = totalTd; - } - - - public String toString() { - return "Player Summary: ID=" + id + " Year=" + year; - } - - public boolean equals(Object obj) { - return EqualsBuilder.reflectionEquals(this, obj); - } -} +package org.springframework.batch.sample.domain; + +import org.apache.commons.lang.builder.EqualsBuilder; + +/** + * Domain object representing the summary of a given Player's + * year. + * + * @author Lucas Ward + * + */ +public class PlayerSummary { + + private String id; + private int year; + private int completes; + private int attempts; + private int passingYards; + private int passingTd; + private int interceptions; + private int rushes; + private int rushYards; + private int receptions; + private int receptionYards; + private int totalTd; + + public String getId() { + return id; + } + public void setId(String id) { + this.id = id; + } + public int getYear() { + return year; + } + public void setYear(int year) { + this.year = year; + } + public int getCompletes() { + return completes; + } + public void setCompletes(int completes) { + this.completes = completes; + } + public int getAttempts() { + return attempts; + } + public void setAttempts(int attempts) { + this.attempts = attempts; + } + public int getPassingYards() { + return passingYards; + } + public void setPassingYards(int passingYards) { + this.passingYards = passingYards; + } + public int getPassingTd() { + return passingTd; + } + public void setPassingTd(int passingTd) { + this.passingTd = passingTd; + } + public int getInterceptions() { + return interceptions; + } + public void setInterceptions(int interceptions) { + this.interceptions = interceptions; + } + public int getRushes() { + return rushes; + } + public void setRushes(int rushes) { + this.rushes = rushes; + } + public int getRushYards() { + return rushYards; + } + public void setRushYards(int rushYards) { + this.rushYards = rushYards; + } + public int getReceptions() { + return receptions; + } + public void setReceptions(int receptions) { + this.receptions = receptions; + } + public int getReceptionYards() { + return receptionYards; + } + public void setReceptionYards(int receptionYards) { + this.receptionYards = receptionYards; + } + public int getTotalTd() { + return totalTd; + } + public void setTotalTd(int totalTd) { + this.totalTd = totalTd; + } + + + public String toString() { + return "Player Summary: ID=" + id + " Year=" + year; + } + + public boolean equals(Object obj) { + return EqualsBuilder.reflectionEquals(this, obj); + } +} diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/exception/handler/FootballExceptionHandler.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/exception/handler/FootballExceptionHandler.java index 7f650254e4..2128c772cd 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/exception/handler/FootballExceptionHandler.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/exception/handler/FootballExceptionHandler.java @@ -1,24 +1,24 @@ -package org.springframework.batch.sample.exception.handler; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.springframework.batch.repeat.RepeatContext; -import org.springframework.batch.repeat.exception.handler.ExceptionHandler; - -public class FootballExceptionHandler implements ExceptionHandler { - - private static final Log logger = LogFactory - .getLog(FootballExceptionHandler.class); - - public void handleException(RepeatContext context, Throwable throwable) - throws RuntimeException { - - if (!(throwable instanceof NumberFormatException)) { - throw new RuntimeException(throwable); - } else { - logger.error("Number Format Exception!", throwable); - } - - } - -} +package org.springframework.batch.sample.exception.handler; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.batch.repeat.RepeatContext; +import org.springframework.batch.repeat.exception.handler.ExceptionHandler; + +public class FootballExceptionHandler implements ExceptionHandler { + + private static final Log logger = LogFactory + .getLog(FootballExceptionHandler.class); + + public void handleException(RepeatContext context, Throwable throwable) + throws RuntimeException { + + if (!(throwable instanceof NumberFormatException)) { + throw new RuntimeException(throwable); + } else { + logger.error("Number Format Exception!", throwable); + } + + } + +} diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/item/reader/GeneratingItemReader.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/item/reader/GeneratingItemReader.java index 36875adc77..e247d67ecb 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/item/reader/GeneratingItemReader.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/item/reader/GeneratingItemReader.java @@ -1,73 +1,73 @@ -package org.springframework.batch.sample.item.reader; - -import java.math.BigDecimal; - -import org.springframework.batch.item.ItemReader; -import org.springframework.batch.item.ItemRecoverer; -import org.springframework.batch.item.exception.MarkFailedException; -import org.springframework.batch.item.exception.ResetFailedException; -import org.springframework.batch.sample.domain.Trade; - -/** - * Generates configurable number of {@link Trade} items. - * - * @author Robert Kasanicky - */ -public class GeneratingItemReader implements ItemReader, ItemRecoverer { - - private int limit = 1; - - private int counter = 0; - - private int marked; - - public Object read() throws Exception { - if (counter < limit) { - counter++; - return new Trade( - "isin" + counter, - counter, - new BigDecimal(counter), - "customer" + counter); - } - return null; - } - - /** - * @param limit number of items that will be generated - * (null returned on consecutive calls). - */ - public void setLimit(int limit) { - this.limit = limit; - } - - public int getCounter() { - return counter; - } - - public int getLimit() { - return limit; - } - - /* (non-Javadoc) - * @see org.springframework.batch.item.ItemRecoverer#recover(java.lang.Object, java.lang.Throwable) - */ - public boolean recover(Object data, Throwable cause) { - return false; - } - - /* (non-Javadoc) - * @see org.springframework.batch.item.ItemStream#mark() - */ - public void mark() throws MarkFailedException { - this.marked = this.counter; - } - - /* (non-Javadoc) - * @see org.springframework.batch.item.ItemStream#reset() - */ - public void reset() throws ResetFailedException { - this.counter = this.marked; - } - -} +package org.springframework.batch.sample.item.reader; + +import java.math.BigDecimal; + +import org.springframework.batch.item.ItemReader; +import org.springframework.batch.item.ItemRecoverer; +import org.springframework.batch.item.exception.MarkFailedException; +import org.springframework.batch.item.exception.ResetFailedException; +import org.springframework.batch.sample.domain.Trade; + +/** + * Generates configurable number of {@link Trade} items. + * + * @author Robert Kasanicky + */ +public class GeneratingItemReader implements ItemReader, ItemRecoverer { + + private int limit = 1; + + private int counter = 0; + + private int marked; + + public Object read() throws Exception { + if (counter < limit) { + counter++; + return new Trade( + "isin" + counter, + counter, + new BigDecimal(counter), + "customer" + counter); + } + return null; + } + + /** + * @param limit number of items that will be generated + * (null returned on consecutive calls). + */ + public void setLimit(int limit) { + this.limit = limit; + } + + public int getCounter() { + return counter; + } + + public int getLimit() { + return limit; + } + + /* (non-Javadoc) + * @see org.springframework.batch.item.ItemRecoverer#recover(java.lang.Object, java.lang.Throwable) + */ + public boolean recover(Object data, Throwable cause) { + return false; + } + + /* (non-Javadoc) + * @see org.springframework.batch.item.ItemStream#mark() + */ + public void mark() throws MarkFailedException { + this.marked = this.counter; + } + + /* (non-Javadoc) + * @see org.springframework.batch.item.ItemStream#reset() + */ + public void reset() throws ResetFailedException { + this.counter = this.marked; + } + +} diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/item/reader/StagingItemReader.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/item/reader/StagingItemReader.java index 7433668b6c..0b96a54ec2 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/item/reader/StagingItemReader.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/item/reader/StagingItemReader.java @@ -1,246 +1,246 @@ -package org.springframework.batch.sample.item.reader; - -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -import org.apache.commons.lang.SerializationUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.springframework.batch.core.domain.StepExecution; -import org.springframework.batch.core.domain.StepListener; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.item.ItemReader; -import org.springframework.batch.item.ItemStream; -import org.springframework.batch.item.exception.StreamException; -import org.springframework.batch.repeat.ExitStatus; -import org.springframework.batch.sample.item.writer.StagingItemWriter; -import org.springframework.dao.OptimisticLockingFailureException; -import org.springframework.jdbc.core.RowMapper; -import org.springframework.jdbc.core.support.JdbcDaoSupport; -import org.springframework.jdbc.support.lob.DefaultLobHandler; -import org.springframework.jdbc.support.lob.LobHandler; -import org.springframework.transaction.support.TransactionSynchronizationManager; -import org.springframework.util.Assert; - -public class StagingItemReader extends JdbcDaoSupport implements ItemStream, ItemReader, StepListener { - - // Key for buffer in transaction synchronization manager - private static final String BUFFER_KEY = StagingItemReader.class.getName() + ".BUFFER"; - - private static Log logger = LogFactory.getLog(StagingItemReader.class); - - private StepExecution stepExecution; - - private LobHandler lobHandler = new DefaultLobHandler(); - - private Object lock = new Object(); - - private volatile boolean initialized = false; - - private volatile Iterator keys; - - /** - * Public setter for the {@link LobHandler}. - * @param lobHandler the {@link LobHandler} to set (defaults to {@link DefaultLobHandler}). - */ - public void setLobHandler(LobHandler lobHandler) { - this.lobHandler = lobHandler; - } - - /** - * - * @see org.springframework.batch.io.driving.DrivingQueryItemReader#close(ExecutionContext) - */ - public void close(ExecutionContext executionContext) { - initialized = false; - keys = null; - if (TransactionSynchronizationManager.hasResource(BUFFER_KEY)) { - TransactionSynchronizationManager.unbindResource(BUFFER_KEY); - } - } - - /** - * - * @see org.springframework.batch.io.driving.DrivingQueryItemReader#open() - */ - public void open(ExecutionContext executionContext) { - // Can be called from multiple threads because of lazy initialisation... - synchronized (lock) { - if (keys == null) { - keys = retrieveKeys().iterator(); - logger.info("Keys obtained for staging."); - initialized = true; - } - } - } - - private List retrieveKeys() { - - synchronized (lock) { - - return getJdbcTemplate().query( - - "SELECT ID FROM BATCH_STAGING WHERE JOB_ID=? AND PROCESSED=? ORDER BY ID", - - new Object[] { stepExecution.getJobExecution().getJobId(), StagingItemWriter.NEW }, - - new RowMapper() { - public Object mapRow(ResultSet rs, int rowNum) throws SQLException { - return new Long(rs.getLong(1)); - } - } - - ); - - } - - } - - public Object read() throws Exception { - Long id = doRead(); - - if (id == null) { - return null; - } - Object result = getJdbcTemplate().queryForObject("SELECT VALUE FROM BATCH_STAGING WHERE ID=?", - new Object[] { id }, new RowMapper() { - public Object mapRow(ResultSet rs, int rowNum) throws SQLException { - byte[] blob = lobHandler.getBlobAsBytes(rs, 1); - return SerializationUtils.deserialize(blob); - } - }); - // Update now - changes will rollback if there is a problem later. - int count = getJdbcTemplate().update("UPDATE BATCH_STAGING SET PROCESSED=? WHERE ID=? AND PROCESSED=?", - new Object[] { StagingItemWriter.DONE, id, StagingItemWriter.NEW }); - if (count != 1) { - throw new OptimisticLockingFailureException("The staging record with ID=" + id - + " was updated concurrently when trying to mark as complete (updated " + count + " records."); - } - return result; - } - - private Long doRead() { - if (!initialized) { - throw new StreamException("ItemStream must be open before it can be read."); - } - - Long key = getBuffer().next(); - if (key == null) { - synchronized (lock) { - if (keys.hasNext()) { - Assert.state(TransactionSynchronizationManager.isActualTransactionActive(), - "Transaction not active for this thread."); - Long next = (Long) keys.next(); - getBuffer().add(next); - key = next; - logger.debug("Retrieved key from list: " + key); - } - } - } - else { - logger.debug("Retrieved key from buffer: " + key); - } - return key; - - } - - private StagingBuffer getBuffer() { - if (!TransactionSynchronizationManager.hasResource(BUFFER_KEY)) { - TransactionSynchronizationManager.bindResource(BUFFER_KEY, new StagingBuffer()); - } - return (StagingBuffer) TransactionSynchronizationManager.getResource(BUFFER_KEY); - } - - public boolean recover(Object data, Throwable cause) { - return false; - } - - private class StagingBuffer { - - private List list = new ArrayList(); - - private Iterator iter = new ArrayList().iterator(); - - public Long next() { - if (iter.hasNext()) { - return (Long) iter.next(); - } - return null; - } - - public void add(Long next) { - list.add(next); - } - - public void rollback() { - logger.debug("Resetting buffer on rollback: " + list); - iter = new ArrayList(list).iterator(); - } - - public void commit() { - logger.debug("Clearing buffer on commit: " + list); - list.clear(); - iter = new ArrayList().iterator(); - } - - public String toString() { - return "list=" + list + "; iter.hasNext()=" + iter.hasNext(); - } - } - - /** - * Mark is supported in a multi- as well as a single-threaded environment. - * The state backing the mark is a buffer, and access is synchronized, so - * multiple threads can be accommodated. Buffers are stored as transaction - * resources (using - * {@link TransactionSynchronizationManager#bindResource(Object, Object)}), - * so they are thread bound. - * - * @see org.springframework.batch.item.ItemReader#mark() - */ - public void mark() { - getBuffer().commit(); - } - - /* - * (non-Javadoc) - * - * @see org.springframework.batch.item.ItemStream#reset(org.springframework.batch.item.ExecutionContext) - */ - public void reset() { - getBuffer().rollback(); - } - - /* - * (non-Javadoc) - * - * @see org.springframework.batch.item.ExecutionContextProvider#getExecutionContext() - */ - public void update(ExecutionContext executionContext) { - } - - /* (non-Javadoc) - * @see org.springframework.batch.core.domain.StepListener#afterStep(StepExecution) - */ - public ExitStatus afterStep(StepExecution stepExecution) { - return null; - } - - /* (non-Javadoc) - * @see org.springframework.batch.core.domain.StepListener#beforeStep(org.springframework.batch.core.domain.StepExecution) - */ - public void beforeStep(StepExecution stepExecution) { - this.stepExecution = stepExecution; - } - - /* (non-Javadoc) - * @see org.springframework.batch.core.domain.StepListener#onErrorInStep(java.lang.Throwable) - */ - public ExitStatus onErrorInStep(StepExecution stepExecution, Throwable e) { - return null; - } - -} +package org.springframework.batch.sample.item.reader; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.apache.commons.lang.SerializationUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.batch.core.domain.StepExecution; +import org.springframework.batch.core.domain.StepListener; +import org.springframework.batch.item.ExecutionContext; +import org.springframework.batch.item.ItemReader; +import org.springframework.batch.item.ItemStream; +import org.springframework.batch.item.exception.StreamException; +import org.springframework.batch.repeat.ExitStatus; +import org.springframework.batch.sample.item.writer.StagingItemWriter; +import org.springframework.dao.OptimisticLockingFailureException; +import org.springframework.jdbc.core.RowMapper; +import org.springframework.jdbc.core.support.JdbcDaoSupport; +import org.springframework.jdbc.support.lob.DefaultLobHandler; +import org.springframework.jdbc.support.lob.LobHandler; +import org.springframework.transaction.support.TransactionSynchronizationManager; +import org.springframework.util.Assert; + +public class StagingItemReader extends JdbcDaoSupport implements ItemStream, ItemReader, StepListener { + + // Key for buffer in transaction synchronization manager + private static final String BUFFER_KEY = StagingItemReader.class.getName() + ".BUFFER"; + + private static Log logger = LogFactory.getLog(StagingItemReader.class); + + private StepExecution stepExecution; + + private LobHandler lobHandler = new DefaultLobHandler(); + + private Object lock = new Object(); + + private volatile boolean initialized = false; + + private volatile Iterator keys; + + /** + * Public setter for the {@link LobHandler}. + * @param lobHandler the {@link LobHandler} to set (defaults to {@link DefaultLobHandler}). + */ + public void setLobHandler(LobHandler lobHandler) { + this.lobHandler = lobHandler; + } + + /** + * + * @see org.springframework.batch.io.driving.DrivingQueryItemReader#close(ExecutionContext) + */ + public void close(ExecutionContext executionContext) { + initialized = false; + keys = null; + if (TransactionSynchronizationManager.hasResource(BUFFER_KEY)) { + TransactionSynchronizationManager.unbindResource(BUFFER_KEY); + } + } + + /** + * + * @see org.springframework.batch.io.driving.DrivingQueryItemReader#open() + */ + public void open(ExecutionContext executionContext) { + // Can be called from multiple threads because of lazy initialisation... + synchronized (lock) { + if (keys == null) { + keys = retrieveKeys().iterator(); + logger.info("Keys obtained for staging."); + initialized = true; + } + } + } + + private List retrieveKeys() { + + synchronized (lock) { + + return getJdbcTemplate().query( + + "SELECT ID FROM BATCH_STAGING WHERE JOB_ID=? AND PROCESSED=? ORDER BY ID", + + new Object[] { stepExecution.getJobExecution().getJobId(), StagingItemWriter.NEW }, + + new RowMapper() { + public Object mapRow(ResultSet rs, int rowNum) throws SQLException { + return new Long(rs.getLong(1)); + } + } + + ); + + } + + } + + public Object read() throws Exception { + Long id = doRead(); + + if (id == null) { + return null; + } + Object result = getJdbcTemplate().queryForObject("SELECT VALUE FROM BATCH_STAGING WHERE ID=?", + new Object[] { id }, new RowMapper() { + public Object mapRow(ResultSet rs, int rowNum) throws SQLException { + byte[] blob = lobHandler.getBlobAsBytes(rs, 1); + return SerializationUtils.deserialize(blob); + } + }); + // Update now - changes will rollback if there is a problem later. + int count = getJdbcTemplate().update("UPDATE BATCH_STAGING SET PROCESSED=? WHERE ID=? AND PROCESSED=?", + new Object[] { StagingItemWriter.DONE, id, StagingItemWriter.NEW }); + if (count != 1) { + throw new OptimisticLockingFailureException("The staging record with ID=" + id + + " was updated concurrently when trying to mark as complete (updated " + count + " records."); + } + return result; + } + + private Long doRead() { + if (!initialized) { + throw new StreamException("ItemStream must be open before it can be read."); + } + + Long key = getBuffer().next(); + if (key == null) { + synchronized (lock) { + if (keys.hasNext()) { + Assert.state(TransactionSynchronizationManager.isActualTransactionActive(), + "Transaction not active for this thread."); + Long next = (Long) keys.next(); + getBuffer().add(next); + key = next; + logger.debug("Retrieved key from list: " + key); + } + } + } + else { + logger.debug("Retrieved key from buffer: " + key); + } + return key; + + } + + private StagingBuffer getBuffer() { + if (!TransactionSynchronizationManager.hasResource(BUFFER_KEY)) { + TransactionSynchronizationManager.bindResource(BUFFER_KEY, new StagingBuffer()); + } + return (StagingBuffer) TransactionSynchronizationManager.getResource(BUFFER_KEY); + } + + public boolean recover(Object data, Throwable cause) { + return false; + } + + private class StagingBuffer { + + private List list = new ArrayList(); + + private Iterator iter = new ArrayList().iterator(); + + public Long next() { + if (iter.hasNext()) { + return (Long) iter.next(); + } + return null; + } + + public void add(Long next) { + list.add(next); + } + + public void rollback() { + logger.debug("Resetting buffer on rollback: " + list); + iter = new ArrayList(list).iterator(); + } + + public void commit() { + logger.debug("Clearing buffer on commit: " + list); + list.clear(); + iter = new ArrayList().iterator(); + } + + public String toString() { + return "list=" + list + "; iter.hasNext()=" + iter.hasNext(); + } + } + + /** + * Mark is supported in a multi- as well as a single-threaded environment. + * The state backing the mark is a buffer, and access is synchronized, so + * multiple threads can be accommodated. Buffers are stored as transaction + * resources (using + * {@link TransactionSynchronizationManager#bindResource(Object, Object)}), + * so they are thread bound. + * + * @see org.springframework.batch.item.ItemReader#mark() + */ + public void mark() { + getBuffer().commit(); + } + + /* + * (non-Javadoc) + * + * @see org.springframework.batch.item.ItemStream#reset(org.springframework.batch.item.ExecutionContext) + */ + public void reset() { + getBuffer().rollback(); + } + + /* + * (non-Javadoc) + * + * @see org.springframework.batch.item.ExecutionContextProvider#getExecutionContext() + */ + public void update(ExecutionContext executionContext) { + } + + /* (non-Javadoc) + * @see org.springframework.batch.core.domain.StepListener#afterStep(StepExecution) + */ + public ExitStatus afterStep(StepExecution stepExecution) { + return null; + } + + /* (non-Javadoc) + * @see org.springframework.batch.core.domain.StepListener#beforeStep(org.springframework.batch.core.domain.StepExecution) + */ + public void beforeStep(StepExecution stepExecution) { + this.stepExecution = stepExecution; + } + + /* (non-Javadoc) + * @see org.springframework.batch.core.domain.StepListener#onErrorInStep(java.lang.Throwable) + */ + public ExitStatus onErrorInStep(StepExecution stepExecution, Throwable e) { + return null; + } + +} diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/item/writer/BatchSqlCustomerCreditIncreaseWriter.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/item/writer/BatchSqlCustomerCreditIncreaseWriter.java index f33abe84e9..bfda0bc822 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/item/writer/BatchSqlCustomerCreditIncreaseWriter.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/item/writer/BatchSqlCustomerCreditIncreaseWriter.java @@ -1,69 +1,69 @@ -package org.springframework.batch.sample.item.writer; - -import java.math.BigDecimal; - -import org.springframework.batch.io.support.BatchSqlUpdateItemWriter; -import org.springframework.batch.item.ItemWriter; -import org.springframework.batch.item.exception.ClearFailedException; -import org.springframework.batch.item.exception.FlushFailedException; -import org.springframework.batch.sample.domain.CustomerCredit; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.util.Assert; - -/** - * Increases customer's credit by fixed amount, delegating to a - * {@link BatchSqlUpdateItemWriter} to push the result out to persistent - * storage. - * - * @author Dave Syer - */ -public class BatchSqlCustomerCreditIncreaseWriter implements ItemWriter, InitializingBean { - - private ItemWriter delegate; - - public static final BigDecimal FIXED_AMOUNT = new BigDecimal(1000); - - /** - * Public setter for the {@link ItemWriter}, which must be an instance of - * {@link BatchSqlUpdateItemWriter}. - * @param delegate the delegate to set - */ - public void setDelegate(ItemWriter delegate) { - this.delegate = delegate; - } - - /* - * (non-Javadoc) - * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet() - */ - public void afterPropertiesSet() throws Exception { - Assert.state(delegate instanceof BatchSqlUpdateItemWriter, "Delegate must be set and must be an instance of BatchSqlUpdateItemWriter"); - } - - /* - * (non-Javadoc) - * @see org.springframework.batch.item.processor.DelegatingItemWriter#doProcess(java.lang.Object) - */ - public void write(Object data) throws Exception { - CustomerCredit customerCredit = (CustomerCredit) data; - customerCredit.increaseCreditBy(FIXED_AMOUNT); - delegate.write(customerCredit); - } - - /** - * @throws ClearFailedException - * @see org.springframework.batch.io.support.BatchSqlUpdateItemWriter#clear() - */ - public void clear() throws ClearFailedException { - delegate.clear(); - } - - /** - * @throws FlushFailedException - * @see org.springframework.batch.io.support.BatchSqlUpdateItemWriter#flush() - */ - public void flush() throws FlushFailedException { - delegate.flush(); - } - -} +package org.springframework.batch.sample.item.writer; + +import java.math.BigDecimal; + +import org.springframework.batch.io.support.BatchSqlUpdateItemWriter; +import org.springframework.batch.item.ItemWriter; +import org.springframework.batch.item.exception.ClearFailedException; +import org.springframework.batch.item.exception.FlushFailedException; +import org.springframework.batch.sample.domain.CustomerCredit; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.util.Assert; + +/** + * Increases customer's credit by fixed amount, delegating to a + * {@link BatchSqlUpdateItemWriter} to push the result out to persistent + * storage. + * + * @author Dave Syer + */ +public class BatchSqlCustomerCreditIncreaseWriter implements ItemWriter, InitializingBean { + + private ItemWriter delegate; + + public static final BigDecimal FIXED_AMOUNT = new BigDecimal(1000); + + /** + * Public setter for the {@link ItemWriter}, which must be an instance of + * {@link BatchSqlUpdateItemWriter}. + * @param delegate the delegate to set + */ + public void setDelegate(ItemWriter delegate) { + this.delegate = delegate; + } + + /* + * (non-Javadoc) + * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet() + */ + public void afterPropertiesSet() throws Exception { + Assert.state(delegate instanceof BatchSqlUpdateItemWriter, "Delegate must be set and must be an instance of BatchSqlUpdateItemWriter"); + } + + /* + * (non-Javadoc) + * @see org.springframework.batch.item.processor.DelegatingItemWriter#doProcess(java.lang.Object) + */ + public void write(Object data) throws Exception { + CustomerCredit customerCredit = (CustomerCredit) data; + customerCredit.increaseCreditBy(FIXED_AMOUNT); + delegate.write(customerCredit); + } + + /** + * @throws ClearFailedException + * @see org.springframework.batch.io.support.BatchSqlUpdateItemWriter#clear() + */ + public void clear() throws ClearFailedException { + delegate.clear(); + } + + /** + * @throws FlushFailedException + * @see org.springframework.batch.io.support.BatchSqlUpdateItemWriter#flush() + */ + public void flush() throws FlushFailedException { + delegate.flush(); + } + +} diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/item/writer/CustomerCreditIncreaseWriter.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/item/writer/CustomerCreditIncreaseWriter.java index fa0d5517fb..0432cb92e3 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/item/writer/CustomerCreditIncreaseWriter.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/item/writer/CustomerCreditIncreaseWriter.java @@ -1,37 +1,37 @@ -package org.springframework.batch.sample.item.writer; - -import java.math.BigDecimal; - -import org.springframework.batch.item.writer.AbstractItemWriter; -import org.springframework.batch.sample.dao.CustomerCreditDao; -import org.springframework.batch.sample.domain.CustomerCredit; - -/** - * Increases customer's credit by fixed amount. - * - * @author Robert Kasanicky - */ -public class CustomerCreditIncreaseWriter extends AbstractItemWriter { - - public static final BigDecimal FIXED_AMOUNT = new BigDecimal(1000); - - private CustomerCreditDao customerCreditDao; - - /** - * Public setter for the {@link CustomerCreditDao}. - * @param customerCreditDao the {@link CustomerCreditDao} to set - */ - public void setCustomerCreditDao(CustomerCreditDao customerCreditDao) { - this.customerCreditDao = customerCreditDao; - } - - /* (non-Javadoc) - * @see org.springframework.batch.item.processor.DelegatingItemWriter#doProcess(java.lang.Object) - */ - public void write(Object data) throws Exception { - CustomerCredit customerCredit = (CustomerCredit) data; - customerCredit.increaseCreditBy(FIXED_AMOUNT); - customerCreditDao.writeCredit(customerCredit); - } - -} +package org.springframework.batch.sample.item.writer; + +import java.math.BigDecimal; + +import org.springframework.batch.item.writer.AbstractItemWriter; +import org.springframework.batch.sample.dao.CustomerCreditDao; +import org.springframework.batch.sample.domain.CustomerCredit; + +/** + * Increases customer's credit by fixed amount. + * + * @author Robert Kasanicky + */ +public class CustomerCreditIncreaseWriter extends AbstractItemWriter { + + public static final BigDecimal FIXED_AMOUNT = new BigDecimal(1000); + + private CustomerCreditDao customerCreditDao; + + /** + * Public setter for the {@link CustomerCreditDao}. + * @param customerCreditDao the {@link CustomerCreditDao} to set + */ + public void setCustomerCreditDao(CustomerCreditDao customerCreditDao) { + this.customerCreditDao = customerCreditDao; + } + + /* (non-Javadoc) + * @see org.springframework.batch.item.processor.DelegatingItemWriter#doProcess(java.lang.Object) + */ + public void write(Object data) throws Exception { + CustomerCredit customerCredit = (CustomerCredit) data; + customerCredit.increaseCreditBy(FIXED_AMOUNT); + customerCreditDao.writeCredit(customerCredit); + } + +} diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/item/writer/PlayerItemWriter.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/item/writer/PlayerItemWriter.java index 721eaa52a9..69756708e5 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/item/writer/PlayerItemWriter.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/item/writer/PlayerItemWriter.java @@ -1,21 +1,21 @@ -package org.springframework.batch.sample.item.writer; - -import org.springframework.batch.item.writer.AbstractItemWriter; -import org.springframework.batch.sample.dao.PlayerDao; -import org.springframework.batch.sample.domain.Player; - -public class PlayerItemWriter extends AbstractItemWriter { - - PlayerDao playerDao; - - public void write(Object data) throws Exception { - playerDao.savePlayer((Player)data); - } - - public void setPlayerDao(PlayerDao playerDao) { - this.playerDao = playerDao; - } - - public void close() throws Exception { - } -} +package org.springframework.batch.sample.item.writer; + +import org.springframework.batch.item.writer.AbstractItemWriter; +import org.springframework.batch.sample.dao.PlayerDao; +import org.springframework.batch.sample.domain.Player; + +public class PlayerItemWriter extends AbstractItemWriter { + + PlayerDao playerDao; + + public void write(Object data) throws Exception { + playerDao.savePlayer((Player)data); + } + + public void setPlayerDao(PlayerDao playerDao) { + this.playerDao = playerDao; + } + + public void close() throws Exception { + } +} diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/item/writer/RetrySampleItemWriter.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/item/writer/RetrySampleItemWriter.java index 8d04a6e708..58c270855c 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/item/writer/RetrySampleItemWriter.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/item/writer/RetrySampleItemWriter.java @@ -1,29 +1,29 @@ -package org.springframework.batch.sample.item.writer; - -import org.springframework.batch.item.writer.AbstractItemWriter; - -/** - * Simulates temporary output trouble - requires to - * retry 3 times to pass successfully. - * - * @author Robert Kasanicky - */ -public class RetrySampleItemWriter extends AbstractItemWriter { - - private int counter = 0; - - public void write(Object data) throws Exception { - counter++; - if (counter == 2 || counter == 3) { - throw new RuntimeException("Temporary error"); - } - } - - /** - * @return number of times {@link #handle(Object)} method was called. - */ - public int getCounter() { - return counter; - } - -} +package org.springframework.batch.sample.item.writer; + +import org.springframework.batch.item.writer.AbstractItemWriter; + +/** + * Simulates temporary output trouble - requires to + * retry 3 times to pass successfully. + * + * @author Robert Kasanicky + */ +public class RetrySampleItemWriter extends AbstractItemWriter { + + private int counter = 0; + + public void write(Object data) throws Exception { + counter++; + if (counter == 2 || counter == 3) { + throw new RuntimeException("Temporary error"); + } + } + + /** + * @return number of times {@link #handle(Object)} method was called. + */ + public int getCounter() { + return counter; + } + +} diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/item/writer/StagingItemWriter.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/item/writer/StagingItemWriter.java index 5be3e90ebd..e54ec89df1 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/item/writer/StagingItemWriter.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/item/writer/StagingItemWriter.java @@ -1,117 +1,117 @@ -package org.springframework.batch.sample.item.writer; - -import java.io.Serializable; -import java.sql.PreparedStatement; -import java.sql.SQLException; - -import org.apache.commons.lang.SerializationUtils; -import org.springframework.batch.core.domain.StepExecution; -import org.springframework.batch.core.domain.StepListener; -import org.springframework.batch.item.ItemWriter; -import org.springframework.batch.item.exception.ClearFailedException; -import org.springframework.batch.item.exception.FlushFailedException; -import org.springframework.batch.repeat.ExitStatus; -import org.springframework.jdbc.core.PreparedStatementSetter; -import org.springframework.jdbc.core.support.JdbcDaoSupport; -import org.springframework.jdbc.support.incrementer.DataFieldMaxValueIncrementer; -import org.springframework.jdbc.support.lob.DefaultLobHandler; -import org.springframework.jdbc.support.lob.LobHandler; -import org.springframework.util.Assert; -import org.springframework.util.ClassUtils; - -public class StagingItemWriter extends JdbcDaoSupport implements StepListener, ItemWriter { - - public static final String NEW = "N"; - - public static final String DONE = "Y"; - - public static final Object WORKING = "W"; - - private DataFieldMaxValueIncrementer incrementer; - - private StepExecution stepExecution; - - private LobHandler lobHandler = new DefaultLobHandler(); - - /** - * Public setter for the {@link LobHandler}. - * @param lobHandler the {@link LobHandler} to set (defaults to - * {@link DefaultLobHandler}). - */ - public void setLobHandler(LobHandler lobHandler) { - this.lobHandler = lobHandler; - } - - /** - * Check mandatory properties. - * - * @see org.springframework.dao.support.DaoSupport#initDao() - */ - protected void initDao() throws Exception { - super.initDao(); - Assert.notNull(incrementer, "DataFieldMaxValueIncrementer is required - set the incrementer property in the " - + ClassUtils.getShortName(StagingItemWriter.class)); - } - - /** - * Setter for the key generator for the staging table. - * - * @param incrementer the {@link DataFieldMaxValueIncrementer} to set - */ - public void setIncrementer(DataFieldMaxValueIncrementer incrementer) { - this.incrementer = incrementer; - } - - /** - * Serialize the item to the staging table, and add a NEW processed flag. - * - * @see ItemWriter#write(java.lang.Object) - */ - public void write(Object data) { - final long id = incrementer.nextLongValue(); - final long jobId = stepExecution.getJobExecution().getJobId().longValue(); - final byte[] blob = SerializationUtils.serialize((Serializable) data); - getJdbcTemplate() - .update("INSERT into BATCH_STAGING (ID, JOB_ID, VALUE, PROCESSED) values (?,?,?,?)", - new PreparedStatementSetter() { - public void setValues(PreparedStatement ps) throws SQLException { - ps.setLong(1, id); - ps.setLong(2, jobId); - lobHandler.getLobCreator().setBlobAsBytes(ps, 3, blob); - ps.setString(4, NEW); - } - - }); - } - - public void close() throws Exception { - } - - public void clear() throws ClearFailedException { - } - - public void flush() throws FlushFailedException { - } - - /* (non-Javadoc) - * @see org.springframework.batch.core.domain.StepListener#afterStep(StepExecution) - */ - public ExitStatus afterStep(StepExecution stepExecution) { - return null; - } - - /* (non-Javadoc) - * @see org.springframework.batch.core.domain.StepListener#beforeStep(org.springframework.batch.core.domain.StepExecution) - */ - public void beforeStep(StepExecution stepExecution) { - this.stepExecution = stepExecution; - } - - /* (non-Javadoc) - * @see org.springframework.batch.core.domain.StepListener#onErrorInStep(java.lang.Throwable) - */ - public ExitStatus onErrorInStep(StepExecution stepExecution, Throwable e) { - return null; - } - -} +package org.springframework.batch.sample.item.writer; + +import java.io.Serializable; +import java.sql.PreparedStatement; +import java.sql.SQLException; + +import org.apache.commons.lang.SerializationUtils; +import org.springframework.batch.core.domain.StepExecution; +import org.springframework.batch.core.domain.StepListener; +import org.springframework.batch.item.ItemWriter; +import org.springframework.batch.item.exception.ClearFailedException; +import org.springframework.batch.item.exception.FlushFailedException; +import org.springframework.batch.repeat.ExitStatus; +import org.springframework.jdbc.core.PreparedStatementSetter; +import org.springframework.jdbc.core.support.JdbcDaoSupport; +import org.springframework.jdbc.support.incrementer.DataFieldMaxValueIncrementer; +import org.springframework.jdbc.support.lob.DefaultLobHandler; +import org.springframework.jdbc.support.lob.LobHandler; +import org.springframework.util.Assert; +import org.springframework.util.ClassUtils; + +public class StagingItemWriter extends JdbcDaoSupport implements StepListener, ItemWriter { + + public static final String NEW = "N"; + + public static final String DONE = "Y"; + + public static final Object WORKING = "W"; + + private DataFieldMaxValueIncrementer incrementer; + + private StepExecution stepExecution; + + private LobHandler lobHandler = new DefaultLobHandler(); + + /** + * Public setter for the {@link LobHandler}. + * @param lobHandler the {@link LobHandler} to set (defaults to + * {@link DefaultLobHandler}). + */ + public void setLobHandler(LobHandler lobHandler) { + this.lobHandler = lobHandler; + } + + /** + * Check mandatory properties. + * + * @see org.springframework.dao.support.DaoSupport#initDao() + */ + protected void initDao() throws Exception { + super.initDao(); + Assert.notNull(incrementer, "DataFieldMaxValueIncrementer is required - set the incrementer property in the " + + ClassUtils.getShortName(StagingItemWriter.class)); + } + + /** + * Setter for the key generator for the staging table. + * + * @param incrementer the {@link DataFieldMaxValueIncrementer} to set + */ + public void setIncrementer(DataFieldMaxValueIncrementer incrementer) { + this.incrementer = incrementer; + } + + /** + * Serialize the item to the staging table, and add a NEW processed flag. + * + * @see ItemWriter#write(java.lang.Object) + */ + public void write(Object data) { + final long id = incrementer.nextLongValue(); + final long jobId = stepExecution.getJobExecution().getJobId().longValue(); + final byte[] blob = SerializationUtils.serialize((Serializable) data); + getJdbcTemplate() + .update("INSERT into BATCH_STAGING (ID, JOB_ID, VALUE, PROCESSED) values (?,?,?,?)", + new PreparedStatementSetter() { + public void setValues(PreparedStatement ps) throws SQLException { + ps.setLong(1, id); + ps.setLong(2, jobId); + lobHandler.getLobCreator().setBlobAsBytes(ps, 3, blob); + ps.setString(4, NEW); + } + + }); + } + + public void close() throws Exception { + } + + public void clear() throws ClearFailedException { + } + + public void flush() throws FlushFailedException { + } + + /* (non-Javadoc) + * @see org.springframework.batch.core.domain.StepListener#afterStep(StepExecution) + */ + public ExitStatus afterStep(StepExecution stepExecution) { + return null; + } + + /* (non-Javadoc) + * @see org.springframework.batch.core.domain.StepListener#beforeStep(org.springframework.batch.core.domain.StepExecution) + */ + public void beforeStep(StepExecution stepExecution) { + this.stepExecution = stepExecution; + } + + /* (non-Javadoc) + * @see org.springframework.batch.core.domain.StepListener#onErrorInStep(java.lang.Throwable) + */ + public ExitStatus onErrorInStep(StepExecution stepExecution, Throwable e) { + return null; + } + +} diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/launch/TaskExecutorLauncher.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/launch/TaskExecutorLauncher.java index 6388a8afc9..83afda4070 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/launch/TaskExecutorLauncher.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/launch/TaskExecutorLauncher.java @@ -1,111 +1,111 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.sample.launch; - -import org.springframework.batch.core.configuration.JobRegistry; -import org.springframework.batch.core.domain.Job; -import org.springframework.batch.core.repository.DuplicateJobException; -import org.springframework.batch.sample.ClassPathXmlApplicationContextJobFactory; -import org.springframework.beans.factory.config.AutowireCapableBeanFactory; -import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; -import org.springframework.beans.factory.xml.XmlBeanFactory; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ResourceLoaderAware; -import org.springframework.context.support.ClassPathXmlApplicationContext; -import org.springframework.core.io.ResourceLoader; - -/** - * @author Dave Syer - * - */ -public class TaskExecutorLauncher implements ResourceLoaderAware { - - private JobRegistry registry; - - private ResourceLoader resourceLoader; - - private ApplicationContext parentContext = null; - - /** - * Public setter for the {@link JobRegistry}. - * @param registry the registry to set - */ - public void setRegistry(JobRegistry registry) { - this.registry = registry; - } - - /* - * (non-Javadoc) - * @see org.springframework.context.ResourceLoaderAware#setResourceLoader(org.springframework.core.io.ResourceLoader) - */ - public void setResourceLoader(ResourceLoader resourceLoader) { - this.resourceLoader = resourceLoader; - } - - private void register(String[] paths) throws DuplicateJobException { - for (int i = 0; i < paths.length; i++) { - String path = paths[i]; - ConfigurableListableBeanFactory beanFactory = new XmlBeanFactory(resourceLoader.getResource(path), - parentContext.getAutowireCapableBeanFactory()); - String[] names = beanFactory.getBeanNamesForType(Job.class); - for (int j = 0; j < names.length; j++) { - registry.register(new ClassPathXmlApplicationContextJobFactory(names[j], path, parentContext)); - } - } - } - - public static void main(String[] args) throws Exception { - - final TaskExecutorLauncher launcher = new TaskExecutorLauncher(); - - new Thread(new Runnable() { - public void run() { - launcher.run(); - }; - }).start(); - - while (launcher.parentContext == null) { - Thread.sleep(100L); - } - - // Paths to individual job configurations. - final String[] paths = new String[] { "jobs/adhocLoopJob.xml", "jobs/footballJob.xml" }; - - launcher.register(paths); - - System.out - .println("Started application. " - + "Please connect using JMX (remember to use -Dcom.sun.management.jmxremote if you can't see anything in Jconsole)."); - System.in.read(); - - } - - private void run() { - - /* - * A simple execution environment with an MBean for the JobLauncher, - * which has an asynchronous TaskExecutor. This will be used as the - * parent context for loading job configurations. - */ - final ApplicationContext parent = new ClassPathXmlApplicationContext("adhoc-job-launcher-context.xml"); - parent.getAutowireCapableBeanFactory().autowireBeanProperties(this, - AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, false); - parent.getAutowireCapableBeanFactory().initializeBean(this, "taskExecutorLauncher"); - this.parentContext = parent; - - } - -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.sample.launch; + +import org.springframework.batch.core.configuration.JobRegistry; +import org.springframework.batch.core.domain.Job; +import org.springframework.batch.core.repository.DuplicateJobException; +import org.springframework.batch.sample.ClassPathXmlApplicationContextJobFactory; +import org.springframework.beans.factory.config.AutowireCapableBeanFactory; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.beans.factory.xml.XmlBeanFactory; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ResourceLoaderAware; +import org.springframework.context.support.ClassPathXmlApplicationContext; +import org.springframework.core.io.ResourceLoader; + +/** + * @author Dave Syer + * + */ +public class TaskExecutorLauncher implements ResourceLoaderAware { + + private JobRegistry registry; + + private ResourceLoader resourceLoader; + + private ApplicationContext parentContext = null; + + /** + * Public setter for the {@link JobRegistry}. + * @param registry the registry to set + */ + public void setRegistry(JobRegistry registry) { + this.registry = registry; + } + + /* + * (non-Javadoc) + * @see org.springframework.context.ResourceLoaderAware#setResourceLoader(org.springframework.core.io.ResourceLoader) + */ + public void setResourceLoader(ResourceLoader resourceLoader) { + this.resourceLoader = resourceLoader; + } + + private void register(String[] paths) throws DuplicateJobException { + for (int i = 0; i < paths.length; i++) { + String path = paths[i]; + ConfigurableListableBeanFactory beanFactory = new XmlBeanFactory(resourceLoader.getResource(path), + parentContext.getAutowireCapableBeanFactory()); + String[] names = beanFactory.getBeanNamesForType(Job.class); + for (int j = 0; j < names.length; j++) { + registry.register(new ClassPathXmlApplicationContextJobFactory(names[j], path, parentContext)); + } + } + } + + public static void main(String[] args) throws Exception { + + final TaskExecutorLauncher launcher = new TaskExecutorLauncher(); + + new Thread(new Runnable() { + public void run() { + launcher.run(); + }; + }).start(); + + while (launcher.parentContext == null) { + Thread.sleep(100L); + } + + // Paths to individual job configurations. + final String[] paths = new String[] { "jobs/adhocLoopJob.xml", "jobs/footballJob.xml" }; + + launcher.register(paths); + + System.out + .println("Started application. " + + "Please connect using JMX (remember to use -Dcom.sun.management.jmxremote if you can't see anything in Jconsole)."); + System.in.read(); + + } + + private void run() { + + /* + * A simple execution environment with an MBean for the JobLauncher, + * which has an asynchronous TaskExecutor. This will be used as the + * parent context for loading job configurations. + */ + final ApplicationContext parent = new ClassPathXmlApplicationContext("adhoc-job-launcher-context.xml"); + parent.getAutowireCapableBeanFactory().autowireBeanProperties(this, + AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, false); + parent.getAutowireCapableBeanFactory().initializeBean(this, "taskExecutorLauncher"); + this.parentContext = parent; + + } + +} diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/mapping/CustomerCreditRowMapper.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/mapping/CustomerCreditRowMapper.java index 33c4eee03e..247fb940d6 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/mapping/CustomerCreditRowMapper.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/mapping/CustomerCreditRowMapper.java @@ -1,25 +1,25 @@ -package org.springframework.batch.sample.mapping; - -import java.sql.ResultSet; -import java.sql.SQLException; - -import org.springframework.batch.sample.domain.CustomerCredit; -import org.springframework.jdbc.core.RowMapper; - -public class CustomerCreditRowMapper implements RowMapper { - - public static final String ID_COLUMN = "id"; - public static final String NAME_COLUMN = "name"; - public static final String CREDIT_COLUMN = "credit"; - - public Object mapRow(ResultSet rs, int rowNum) throws SQLException { - CustomerCredit customerCredit = new CustomerCredit(); - - customerCredit.setId(rs.getInt(ID_COLUMN)); - customerCredit.setName(rs.getString(NAME_COLUMN)); - customerCredit.setCredit(rs.getBigDecimal(CREDIT_COLUMN)); - - return customerCredit; - } - -} +package org.springframework.batch.sample.mapping; + +import java.sql.ResultSet; +import java.sql.SQLException; + +import org.springframework.batch.sample.domain.CustomerCredit; +import org.springframework.jdbc.core.RowMapper; + +public class CustomerCreditRowMapper implements RowMapper { + + public static final String ID_COLUMN = "id"; + public static final String NAME_COLUMN = "name"; + public static final String CREDIT_COLUMN = "credit"; + + public Object mapRow(ResultSet rs, int rowNum) throws SQLException { + CustomerCredit customerCredit = new CustomerCredit(); + + customerCredit.setId(rs.getInt(ID_COLUMN)); + customerCredit.setName(rs.getString(NAME_COLUMN)); + customerCredit.setCredit(rs.getBigDecimal(CREDIT_COLUMN)); + + return customerCredit; + } + +} diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/mapping/GameMapper.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/mapping/GameMapper.java index 1776ebaddf..354f734935 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/mapping/GameMapper.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/mapping/GameMapper.java @@ -1,35 +1,35 @@ -package org.springframework.batch.sample.mapping; - -import org.springframework.batch.io.file.mapping.FieldSetMapper; -import org.springframework.batch.io.file.mapping.FieldSet; -import org.springframework.batch.sample.domain.Game; - -public class GameMapper implements FieldSetMapper { - - public Object mapLine(FieldSet fs) { - - if(fs == null){ - return null; - } - - Game game = new Game(); - game.setId(fs.readString("id")); - game.setYear(fs.readInt("year")); - game.setTeam(fs.readString("team")); - game.setWeek(fs.readInt("week")); - game.setOpponent(fs.readString("opponent")); - game.setCompletes(fs.readInt("completes")); - game.setAttempts(fs.readInt("attempts")); - game.setPassingYards(fs.readInt("passingYards")); - game.setPassingTd(fs.readInt("passingTd")); - game.setInterceptions(fs.readInt("interceptions")); - game.setRushes(fs.readInt("rushes")); - game.setRushYards(fs.readInt("rushYards")); - game.setReceptions(fs.readInt("receptions", 0)); - game.setReceptionYards(fs.readInt("receptionYards")); - game.setTotalTd(fs.readInt("totalTd")); - - return game; - } - -} +package org.springframework.batch.sample.mapping; + +import org.springframework.batch.io.file.mapping.FieldSetMapper; +import org.springframework.batch.io.file.mapping.FieldSet; +import org.springframework.batch.sample.domain.Game; + +public class GameMapper implements FieldSetMapper { + + public Object mapLine(FieldSet fs) { + + if(fs == null){ + return null; + } + + Game game = new Game(); + game.setId(fs.readString("id")); + game.setYear(fs.readInt("year")); + game.setTeam(fs.readString("team")); + game.setWeek(fs.readInt("week")); + game.setOpponent(fs.readString("opponent")); + game.setCompletes(fs.readInt("completes")); + game.setAttempts(fs.readInt("attempts")); + game.setPassingYards(fs.readInt("passingYards")); + game.setPassingTd(fs.readInt("passingTd")); + game.setInterceptions(fs.readInt("interceptions")); + game.setRushes(fs.readInt("rushes")); + game.setRushYards(fs.readInt("rushYards")); + game.setReceptions(fs.readInt("receptions", 0)); + game.setReceptionYards(fs.readInt("receptionYards")); + game.setTotalTd(fs.readInt("totalTd")); + + return game; + } + +} diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/mapping/PlayerMapper.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/mapping/PlayerMapper.java index 0ea87f454f..09f0392e6e 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/mapping/PlayerMapper.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/mapping/PlayerMapper.java @@ -1,27 +1,27 @@ -package org.springframework.batch.sample.mapping; - -import org.springframework.batch.io.file.mapping.FieldSetMapper; -import org.springframework.batch.io.file.mapping.FieldSet; -import org.springframework.batch.sample.domain.Player; - -public class PlayerMapper implements FieldSetMapper { - - public Object mapLine(FieldSet fs) { - - if(fs == null){ - return null; - } - - Player player = new Player(); - player.setID(fs.readString("ID")); - player.setLastName(fs.readString("lastName")); - player.setFirstName(fs.readString("firstName")); - player.setPosition(fs.readString("position")); - player.setDebutYear(fs.readInt("debutYear")); - player.setBirthYear(fs.readInt("birthYear")); - - return player; - } - - -} +package org.springframework.batch.sample.mapping; + +import org.springframework.batch.io.file.mapping.FieldSetMapper; +import org.springframework.batch.io.file.mapping.FieldSet; +import org.springframework.batch.sample.domain.Player; + +public class PlayerMapper implements FieldSetMapper { + + public Object mapLine(FieldSet fs) { + + if(fs == null){ + return null; + } + + Player player = new Player(); + player.setID(fs.readString("ID")); + player.setLastName(fs.readString("lastName")); + player.setFirstName(fs.readString("firstName")); + player.setPosition(fs.readString("position")); + player.setDebutYear(fs.readInt("debutYear")); + player.setBirthYear(fs.readInt("birthYear")); + + return player; + } + + +} diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/mapping/PlayerSummaryMapper.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/mapping/PlayerSummaryMapper.java index 18a7c3a18b..5c62eefbab 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/mapping/PlayerSummaryMapper.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/mapping/PlayerSummaryMapper.java @@ -1,55 +1,55 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.sample.mapping; - -import java.sql.ResultSet; -import java.sql.SQLException; - -import org.springframework.batch.sample.domain.PlayerSummary; -import org.springframework.jdbc.core.RowMapper; - -/** - * RowMapper used to map a ResultSet to a (@link PlayerSummary) - * - * @author Lucas Ward - * - */ -public class PlayerSummaryMapper implements RowMapper { - - /* (non-Javadoc) - * @see org.springframework.jdbc.core.RowMapper#mapRow(java.sql.ResultSet, int) - */ - public Object mapRow(ResultSet rs, int rowNum) throws SQLException { - - PlayerSummary summary = new PlayerSummary(); - - summary.setId(rs.getString(1)); - summary.setYear(rs.getInt(2)); - summary.setCompletes(rs.getInt(3)); - summary.setAttempts(rs.getInt(4)); - summary.setPassingYards(rs.getInt(5)); - summary.setPassingTd(rs.getInt(6)); - summary.setInterceptions(rs.getInt(7)); - summary.setRushes(rs.getInt(8)); - summary.setRushYards(rs.getInt(9)); - summary.setReceptions(rs.getInt(10)); - summary.setReceptionYards(rs.getInt(11)); - summary.setTotalTd(rs.getInt(12)); - - return summary; - } - -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.sample.mapping; + +import java.sql.ResultSet; +import java.sql.SQLException; + +import org.springframework.batch.sample.domain.PlayerSummary; +import org.springframework.jdbc.core.RowMapper; + +/** + * RowMapper used to map a ResultSet to a (@link PlayerSummary) + * + * @author Lucas Ward + * + */ +public class PlayerSummaryMapper implements RowMapper { + + /* (non-Javadoc) + * @see org.springframework.jdbc.core.RowMapper#mapRow(java.sql.ResultSet, int) + */ + public Object mapRow(ResultSet rs, int rowNum) throws SQLException { + + PlayerSummary summary = new PlayerSummary(); + + summary.setId(rs.getString(1)); + summary.setYear(rs.getInt(2)); + summary.setCompletes(rs.getInt(3)); + summary.setAttempts(rs.getInt(4)); + summary.setPassingYards(rs.getInt(5)); + summary.setPassingTd(rs.getInt(6)); + summary.setInterceptions(rs.getInt(7)); + summary.setRushes(rs.getInt(8)); + summary.setRushYards(rs.getInt(9)); + summary.setReceptions(rs.getInt(10)); + summary.setReceptionYards(rs.getInt(11)); + summary.setTotalTd(rs.getInt(12)); + + return summary; + } + +} diff --git a/spring-batch-samples/src/main/resources/CustomerCredit.hbm.xml b/spring-batch-samples/src/main/resources/CustomerCredit.hbm.xml index cdcafd3f1c..900fffb9fa 100644 --- a/spring-batch-samples/src/main/resources/CustomerCredit.hbm.xml +++ b/spring-batch-samples/src/main/resources/CustomerCredit.hbm.xml @@ -1,17 +1,17 @@ - - - - - - - - - - - - - + + + + + + + + + + + + + \ No newline at end of file diff --git a/spring-batch-samples/src/main/resources/data/beanWrapperMapperSampleJob/input/20070122.teststream.ImportPersonDataStep.txt b/spring-batch-samples/src/main/resources/data/beanWrapperMapperSampleJob/input/20070122.teststream.ImportPersonDataStep.txt index f3d669d54d..ce3379132e 100644 --- a/spring-batch-samples/src/main/resources/data/beanWrapperMapperSampleJob/input/20070122.teststream.ImportPersonDataStep.txt +++ b/spring-batch-samples/src/main/resources/data/beanWrapperMapperSampleJob/input/20070122.teststream.ImportPersonDataStep.txt @@ -1,3 +1,3 @@ -123451234567890123451234567890123456789012345123456789012345678901234567890 -Mr Tomas Slanina 29 BratislavaPeter Charles +123451234567890123451234567890123456789012345123456789012345678901234567890 +Mr Tomas Slanina 29 BratislavaPeter Charles Mr George W. Bush 31 Washington \ No newline at end of file diff --git a/spring-batch-samples/src/main/resources/data/beanWrapperMapperSampleJob/input/20070122.teststream.ImportTradeDataStep.txt b/spring-batch-samples/src/main/resources/data/beanWrapperMapperSampleJob/input/20070122.teststream.ImportTradeDataStep.txt index 2b4bbf4440..c48f5c51c9 100644 --- a/spring-batch-samples/src/main/resources/data/beanWrapperMapperSampleJob/input/20070122.teststream.ImportTradeDataStep.txt +++ b/spring-batch-samples/src/main/resources/data/beanWrapperMapperSampleJob/input/20070122.teststream.ImportTradeDataStep.txt @@ -1,5 +1,5 @@ -UK21341EAH4121131.11customer1 -UK21341EAH4221232.11customer2 -UK21341EAH4321333.11customer3 -UK21341EAH4421434.11customer4 +UK21341EAH4121131.11customer1 +UK21341EAH4221232.11customer2 +UK21341EAH4321333.11customer3 +UK21341EAH4421434.11customer4 UK21341EAH4521535.11customer5 \ No newline at end of file diff --git a/spring-batch-samples/src/main/resources/data/fixedLengthImportJob/input/20070122.teststream.ImportTradeDataStep.txt b/spring-batch-samples/src/main/resources/data/fixedLengthImportJob/input/20070122.teststream.ImportTradeDataStep.txt index 2b4bbf4440..c48f5c51c9 100644 --- a/spring-batch-samples/src/main/resources/data/fixedLengthImportJob/input/20070122.teststream.ImportTradeDataStep.txt +++ b/spring-batch-samples/src/main/resources/data/fixedLengthImportJob/input/20070122.teststream.ImportTradeDataStep.txt @@ -1,5 +1,5 @@ -UK21341EAH4121131.11customer1 -UK21341EAH4221232.11customer2 -UK21341EAH4321333.11customer3 -UK21341EAH4421434.11customer4 +UK21341EAH4121131.11customer1 +UK21341EAH4221232.11customer2 +UK21341EAH4321333.11customer3 +UK21341EAH4421434.11customer4 UK21341EAH4521535.11customer5 \ No newline at end of file diff --git a/spring-batch-samples/src/main/resources/data/multilineJob/input/20070122.teststream.multilineStep.txt b/spring-batch-samples/src/main/resources/data/multilineJob/input/20070122.teststream.multilineStep.txt index 70959886dc..94945eb3ff 100644 --- a/spring-batch-samples/src/main/resources/data/multilineJob/input/20070122.teststream.multilineStep.txt +++ b/spring-batch-samples/src/main/resources/data/multilineJob/input/20070122.teststream.multilineStep.txt @@ -1,9 +1,9 @@ -BEGIN -UK21341EAH4597898.34customer1 -UK21341EAH4611218.12customer2 -END -BEGIN -UK21341EAH4724512.78customer2 -UK21341EAH4810809.25customer3 -UK21341EAH4985423.39customer4 -END +BEGIN +UK21341EAH4597898.34customer1 +UK21341EAH4611218.12customer2 +END +BEGIN +UK21341EAH4724512.78customer2 +UK21341EAH4810809.25customer3 +UK21341EAH4985423.39customer4 +END diff --git a/spring-batch-samples/src/main/resources/data/multilineJob/input/problematic.txt b/spring-batch-samples/src/main/resources/data/multilineJob/input/problematic.txt index 5aa61aa931..9a2f42af62 100644 --- a/spring-batch-samples/src/main/resources/data/multilineJob/input/problematic.txt +++ b/spring-batch-samples/src/main/resources/data/multilineJob/input/problematic.txt @@ -1,20 +1,20 @@ -RECORDTYPE1 -a,b,c -d,e -END - -RECORDTYPE2 -1:2:3 -4 -5:6 -END - -PERSON -john, william, smith #name -55 #age -END - -ANIMAL -tiger #spieces -1 #quantity -END +RECORDTYPE1 +a,b,c +d,e +END + +RECORDTYPE2 +1:2:3 +4 +5:6 +END + +PERSON +john, william, smith #name +55 #age +END + +ANIMAL +tiger #spieces +1 #quantity +END diff --git a/spring-batch-samples/src/main/resources/data/multilineOrderJob/input/20070122.teststream.multilineOrderStep.txt b/spring-batch-samples/src/main/resources/data/multilineOrderJob/input/20070122.teststream.multilineOrderStep.txt index 4ae4636652..725f383f3e 100755 --- a/spring-batch-samples/src/main/resources/data/multilineOrderJob/input/20070122.teststream.multilineOrderStep.txt +++ b/spring-batch-samples/src/main/resources/data/multilineOrderJob/input/20070122.teststream.multilineOrderStep.txt @@ -1,22 +1,22 @@ -FHE;20070215-0001;2007-02-15 -HEA;0013100345;2007-02-15 -NCU;Smith;Peter;;T;20014539;F -BAD;;Oak Street 31/A;;Small Town;00235;IL;US -SAD;Smith, Elizabeth;Elm Street 17;;Some City;30011;FL;United States -BIN;VISA;VISA-12345678903 -LIT;1044391041;37.49;0;0;4.99;2.99;1;45.47 -LIT;2134776319;221.99;5;0;7.99;2.99;1;221.87 -SIN;UPS;EXP;DELIVER ONLY ON WEEKDAYS -FOT;2;2;267.34 -HEA;0013100346;2007-02-15 -BCU;Acme Factory of England;72155919;T -BAD;;St. Andrews Road 31;;London;55342;;UK -BIN;AMEX;AMEX-72345678903 -LIT;1044319101;1070.50;5;0;7.99;2.99;12;12335.46 -LIT;2134727219;21.79;5;0;7.99;2.99;12;380.17 -LIT;1044339301;79.95;0;5.5;4.99;2.99;4;329.72 -LIT;2134747319;55.29;10;0;7.99;2.99;6;364.45 -LIT;1044359501;339.99;10;0;7.99;2.99;2;633.94 -SIN;FEDX;AMS; -FOT;5;36;14043.74 -FFT;2;14311.08 +FHE;20070215-0001;2007-02-15 +HEA;0013100345;2007-02-15 +NCU;Smith;Peter;;T;20014539;F +BAD;;Oak Street 31/A;;Small Town;00235;IL;US +SAD;Smith, Elizabeth;Elm Street 17;;Some City;30011;FL;United States +BIN;VISA;VISA-12345678903 +LIT;1044391041;37.49;0;0;4.99;2.99;1;45.47 +LIT;2134776319;221.99;5;0;7.99;2.99;1;221.87 +SIN;UPS;EXP;DELIVER ONLY ON WEEKDAYS +FOT;2;2;267.34 +HEA;0013100346;2007-02-15 +BCU;Acme Factory of England;72155919;T +BAD;;St. Andrews Road 31;;London;55342;;UK +BIN;AMEX;AMEX-72345678903 +LIT;1044319101;1070.50;5;0;7.99;2.99;12;12335.46 +LIT;2134727219;21.79;5;0;7.99;2.99;12;380.17 +LIT;1044339301;79.95;0;5.5;4.99;2.99;4;329.72 +LIT;2134747319;55.29;10;0;7.99;2.99;6;364.45 +LIT;1044359501;339.99;10;0;7.99;2.99;2;633.94 +SIN;FEDX;AMS; +FOT;5;36;14043.74 +FFT;2;14311.08 diff --git a/spring-batch-samples/src/main/resources/data/multilineOrderJob/order_sample.txt b/spring-batch-samples/src/main/resources/data/multilineOrderJob/order_sample.txt index d645e9b45a..23bd6ae6f7 100644 --- a/spring-batch-samples/src/main/resources/data/multilineOrderJob/order_sample.txt +++ b/spring-batch-samples/src/main/resources/data/multilineOrderJob/order_sample.txt @@ -1,51 +1,51 @@ -# FHE;ORDER_BATCH_ID(S8-4);ORDER_BATCH_DATE(YYYY-MM-DD) -# -# HEA;ORDER_ID(N10);ORDER_DATE(YYYY-MM-DD) -# [excl] NCU;LAST_NAME(S35);FIRST_NAME(S35);MIDDLE_NAME(S35);REGISTERED(T/F);REG_ID(N8);VIP(T/F) -# [excl] BCU;COMPANY_NAME(S50);REG_ID(N8);VIP(T/F) -# BAD;ADDRESSEE(S60);ADDR_LINE1(S50);ADDR_LINE2(S50);CITY(S30);ZIP_CODE(S5);STATE(S2);COUNTRY(S50) -# [opt] SAD;ADDRESSEE(S60);ADDR_LINE1(S50);ADDR_LINE2(S50);CITY(S30);ZIP_CODE(S5);STATE(S2);COUNTRY(S50) -# BIN;PAYMENT_TYPE_ID(S4);PAYMENT_DESC(S30); -# LIT;ITEM_ID(N10);PRICE(N8.2);DISCOUNT_PERC(N3.2);DISCOUNT_AMOUNT(N8.2);SHIPPING_PRICE(N8.2);HANDLING_PRICE(N8.2);QUANTITY(N4);TOTAL_PRICE(N8.2) -# ... (1 .. n) ... -# SIN;SHIPPER_ID(S4);SHIPPING_TYPE_ID(S3);ADDITIONAL_SHIPPING_INFO(S100) -# FOT;TOTAL_LINE_ITEMS(N6);TOTAL_ITEMS(N6);TOTAL_PRICE(S8.2) -# -# FFT;TOTAL_ORDERS(N6);TOTAL_PRICE(N10.2) -# -# LINE_ID Description LINE MANDATORY OPTIONAL FIELDS* -# FHE File Header YES NONE -# HEA Record Header YES NONE -# NCU Non-Business Customer EXCL WITH BCU MIDDLE_NAME, REG_ID (if REGISTERED is 'F') -# BCU Business Customer EXCL WITH NCU NONE -# BAD Billing Address YES ADDRESSEE, ADDR_LINE2, STATE (if COUNTRY is not 'United States') -# SAD Shipping Address NO ADDR_LINE2, STATE (if COUNTRY is not 'United States') -# BIN Billing Info YES NONE -# LIT Line Item YES (1 to N lines) DISCOUNT_PERC and DISCOUNT_AMOUNT are mutualy exclusive (only one of them can be non zero) -# SIN Shipping Info YES ADDITIONAL_SHIPPING_INFO -# FOT Record Footer YES NONE -# FFT File Footer YES NONE -# -# * if field is optional at least empty field must be provided (';;') -FHE;20070215-0001;2007-02-15 -HEA;0013100345;2007-02-15 -NCU;Smith;Peter;;T;20014539;F -BAD;;Oak Street 31/A;;Small Town;00235;IL;US -SAD;Smith, Elizabeth;Elm Street 17;;Some City;30011;FL;United States -BIN;VISA;VISA-12345678903 -LIT;1044391041;37.49;0;0;4.99;2.99;1;45.47 -LIT;2134776319;221.99;5;0;7.99;2.99;1;221.87 -SIN;UPS;EXP;DELIVER ONLY ON WEEKDAYS -FOT;2;2;267.34 -HEA;0013100346;2007-02-15 -BCU;Acme Factory of England;72155919;T -BAD;;St. Andrews Road 31;;London;55342;;UK -BIN;AMEX;AMEX-72345678903 -LIT;1044319101;1070.50;5;0;7.99;2.99;12;12335.46 -LIT;2134727619;21.79;5;0;7.99;2.99;12;380.17 -LIT;1044339101;79.95;0;5.5;4.99;2.99;4;329.72 -LIT;2134747619;55.29;10;0;7.99;2.99;6;364.45 -LIT;1044359101;339.99;10;0;7.99;2.99;2;633.94 -SIN;FEDX;AMS; -FOT;5;36;14043.74 -FFT;2;14311.08 +# FHE;ORDER_BATCH_ID(S8-4);ORDER_BATCH_DATE(YYYY-MM-DD) +# +# HEA;ORDER_ID(N10);ORDER_DATE(YYYY-MM-DD) +# [excl] NCU;LAST_NAME(S35);FIRST_NAME(S35);MIDDLE_NAME(S35);REGISTERED(T/F);REG_ID(N8);VIP(T/F) +# [excl] BCU;COMPANY_NAME(S50);REG_ID(N8);VIP(T/F) +# BAD;ADDRESSEE(S60);ADDR_LINE1(S50);ADDR_LINE2(S50);CITY(S30);ZIP_CODE(S5);STATE(S2);COUNTRY(S50) +# [opt] SAD;ADDRESSEE(S60);ADDR_LINE1(S50);ADDR_LINE2(S50);CITY(S30);ZIP_CODE(S5);STATE(S2);COUNTRY(S50) +# BIN;PAYMENT_TYPE_ID(S4);PAYMENT_DESC(S30); +# LIT;ITEM_ID(N10);PRICE(N8.2);DISCOUNT_PERC(N3.2);DISCOUNT_AMOUNT(N8.2);SHIPPING_PRICE(N8.2);HANDLING_PRICE(N8.2);QUANTITY(N4);TOTAL_PRICE(N8.2) +# ... (1 .. n) ... +# SIN;SHIPPER_ID(S4);SHIPPING_TYPE_ID(S3);ADDITIONAL_SHIPPING_INFO(S100) +# FOT;TOTAL_LINE_ITEMS(N6);TOTAL_ITEMS(N6);TOTAL_PRICE(S8.2) +# +# FFT;TOTAL_ORDERS(N6);TOTAL_PRICE(N10.2) +# +# LINE_ID Description LINE MANDATORY OPTIONAL FIELDS* +# FHE File Header YES NONE +# HEA Record Header YES NONE +# NCU Non-Business Customer EXCL WITH BCU MIDDLE_NAME, REG_ID (if REGISTERED is 'F') +# BCU Business Customer EXCL WITH NCU NONE +# BAD Billing Address YES ADDRESSEE, ADDR_LINE2, STATE (if COUNTRY is not 'United States') +# SAD Shipping Address NO ADDR_LINE2, STATE (if COUNTRY is not 'United States') +# BIN Billing Info YES NONE +# LIT Line Item YES (1 to N lines) DISCOUNT_PERC and DISCOUNT_AMOUNT are mutualy exclusive (only one of them can be non zero) +# SIN Shipping Info YES ADDITIONAL_SHIPPING_INFO +# FOT Record Footer YES NONE +# FFT File Footer YES NONE +# +# * if field is optional at least empty field must be provided (';;') +FHE;20070215-0001;2007-02-15 +HEA;0013100345;2007-02-15 +NCU;Smith;Peter;;T;20014539;F +BAD;;Oak Street 31/A;;Small Town;00235;IL;US +SAD;Smith, Elizabeth;Elm Street 17;;Some City;30011;FL;United States +BIN;VISA;VISA-12345678903 +LIT;1044391041;37.49;0;0;4.99;2.99;1;45.47 +LIT;2134776319;221.99;5;0;7.99;2.99;1;221.87 +SIN;UPS;EXP;DELIVER ONLY ON WEEKDAYS +FOT;2;2;267.34 +HEA;0013100346;2007-02-15 +BCU;Acme Factory of England;72155919;T +BAD;;St. Andrews Road 31;;London;55342;;UK +BIN;AMEX;AMEX-72345678903 +LIT;1044319101;1070.50;5;0;7.99;2.99;12;12335.46 +LIT;2134727619;21.79;5;0;7.99;2.99;12;380.17 +LIT;1044339101;79.95;0;5.5;4.99;2.99;4;329.72 +LIT;2134747619;55.29;10;0;7.99;2.99;6;364.45 +LIT;1044359101;339.99;10;0;7.99;2.99;2;633.94 +SIN;FEDX;AMS; +FOT;5;36;14043.74 +FFT;2;14311.08 diff --git a/spring-batch-samples/src/main/resources/data/restartSample/input/20070122.teststream.ImportTradeDataStep.txt b/spring-batch-samples/src/main/resources/data/restartSample/input/20070122.teststream.ImportTradeDataStep.txt index ea8953b3de..a65f1d3c8b 100644 --- a/spring-batch-samples/src/main/resources/data/restartSample/input/20070122.teststream.ImportTradeDataStep.txt +++ b/spring-batch-samples/src/main/resources/data/restartSample/input/20070122.teststream.ImportTradeDataStep.txt @@ -1,5 +1,5 @@ -UK21341EAH4597898.34customer1 -UK21341EAH4611218.12customer2 -UK21341EAH4724512.78customer2 -UK21341EAH4810819.25customer3 -UK21341EAH4985423.39customer4 +UK21341EAH4597898.34customer1 +UK21341EAH4611218.12customer2 +UK21341EAH4724512.78customer2 +UK21341EAH4810819.25customer3 +UK21341EAH4985423.39customer4 diff --git a/spring-batch-samples/src/main/resources/data/simpleSkipSample/input/20070122.teststream.ImportTradeDataStep.txt b/spring-batch-samples/src/main/resources/data/simpleSkipSample/input/20070122.teststream.ImportTradeDataStep.txt index 3b7bc7ba5c..7908e95a3c 100644 --- a/spring-batch-samples/src/main/resources/data/simpleSkipSample/input/20070122.teststream.ImportTradeDataStep.txt +++ b/spring-batch-samples/src/main/resources/data/simpleSkipSample/input/20070122.teststream.ImportTradeDataStep.txt @@ -1,5 +1,5 @@ -UK21341EAH4597898.34customer1 -UK21341EAH4611218.12customer2 -UK21341EAH4724512.78customer2 -UK21341EAH48108109.25customer3 +UK21341EAH4597898.34customer1 +UK21341EAH4611218.12customer2 +UK21341EAH4724512.78customer2 +UK21341EAH48108109.25customer3 UK21341EAH49854123.39customer4 \ No newline at end of file diff --git a/spring-batch-samples/src/main/resources/data/simpleTaskletJob/input/20070122.teststream.ImportTradeDataStep.txt b/spring-batch-samples/src/main/resources/data/simpleTaskletJob/input/20070122.teststream.ImportTradeDataStep.txt index 2b4bbf4440..c48f5c51c9 100644 --- a/spring-batch-samples/src/main/resources/data/simpleTaskletJob/input/20070122.teststream.ImportTradeDataStep.txt +++ b/spring-batch-samples/src/main/resources/data/simpleTaskletJob/input/20070122.teststream.ImportTradeDataStep.txt @@ -1,5 +1,5 @@ -UK21341EAH4121131.11customer1 -UK21341EAH4221232.11customer2 -UK21341EAH4321333.11customer3 -UK21341EAH4421434.11customer4 +UK21341EAH4121131.11customer1 +UK21341EAH4221232.11customer2 +UK21341EAH4321333.11customer3 +UK21341EAH4421434.11customer4 UK21341EAH4521535.11customer5 \ No newline at end of file diff --git a/spring-batch-samples/src/main/resources/data/simpleTaskletJob/input/20070207.testStream.ImportTradeDataStep.txt b/spring-batch-samples/src/main/resources/data/simpleTaskletJob/input/20070207.testStream.ImportTradeDataStep.txt index ed9c7eac1c..3a8951788a 100644 --- a/spring-batch-samples/src/main/resources/data/simpleTaskletJob/input/20070207.testStream.ImportTradeDataStep.txt +++ b/spring-batch-samples/src/main/resources/data/simpleTaskletJob/input/20070207.testStream.ImportTradeDataStep.txt @@ -1,5 +1,5 @@ -UK21341EAH4597898.34customer1 -UK21341EAH4611218.12customer2 -UK21341EAH4724512.78customer2 -UK21341EAH48108109.25customer3 -UK21341EAH49854123.39customer4 +UK21341EAH4597898.34customer1 +UK21341EAH4611218.12customer2 +UK21341EAH4724512.78customer2 +UK21341EAH48108109.25customer3 +UK21341EAH49854123.39customer4 diff --git a/spring-batch-samples/src/main/resources/data/staxJob/input/20070918.testStream.xmlFileStep.xml b/spring-batch-samples/src/main/resources/data/staxJob/input/20070918.testStream.xmlFileStep.xml index 1e4169bf25..4bc10a913e 100644 --- a/spring-batch-samples/src/main/resources/data/staxJob/input/20070918.testStream.xmlFileStep.xml +++ b/spring-batch-samples/src/main/resources/data/staxJob/input/20070918.testStream.xmlFileStep.xml @@ -1,57 +1,57 @@ - - - - XYZ0001 - 5 - 11.39 - Customer1 - - - XYZ0002 - 2 - 72.99 - Customer2c - - - XYZ0003 - 9 - 99.99 - Customer3 - - - XYZ0001 - 5 - 11.39 - Customer1 - - - XYZ0002 - 2 - 72.99 - Customer2c - - - XYZ0003 - 9 - 99.99 - Customer3 - - - XYZ0001 - 5 - 11.39 - Customer1 - - - XYZ0002 - 2 - 72.99 - Customer2c - - - XYZ0003 - 9 - 99.99 - Customer3 - - + + + + XYZ0001 + 5 + 11.39 + Customer1 + + + XYZ0002 + 2 + 72.99 + Customer2c + + + XYZ0003 + 9 + 99.99 + Customer3 + + + XYZ0001 + 5 + 11.39 + Customer1 + + + XYZ0002 + 2 + 72.99 + Customer2c + + + XYZ0003 + 9 + 99.99 + Customer3 + + + XYZ0001 + 5 + 11.39 + Customer1 + + + XYZ0002 + 2 + 72.99 + Customer2c + + + XYZ0003 + 9 + 99.99 + Customer3 + + diff --git a/spring-batch-samples/src/main/resources/data/staxJob/input/trade.xsd b/spring-batch-samples/src/main/resources/data/staxJob/input/trade.xsd index f4f9b08c6d..debcb15266 100644 --- a/spring-batch-samples/src/main/resources/data/staxJob/input/trade.xsd +++ b/spring-batch-samples/src/main/resources/data/staxJob/input/trade.xsd @@ -1,17 +1,17 @@ - - - - - - - - - - - - - + + + + + + + + + + + + + diff --git a/spring-batch-samples/src/main/resources/data/staxJob/output/expected-output.xml b/spring-batch-samples/src/main/resources/data/staxJob/output/expected-output.xml index d36896f188..e776a9aceb 100644 --- a/spring-batch-samples/src/main/resources/data/staxJob/output/expected-output.xml +++ b/spring-batch-samples/src/main/resources/data/staxJob/output/expected-output.xml @@ -1,57 +1,57 @@ - - - - XYZ0001 - 5 - 11.39 - Customer1 - - - XYZ0002 - 2 - 72.99 - Customer2c - - - XYZ0003 - 9 - 99.99 - Customer3 - - - XYZ0001 - 5 - 11.39 - Customer1 - - - XYZ0002 - 2 - 72.99 - Customer2c - - - XYZ0003 - 9 - 99.99 - Customer3 - - - XYZ0001 - 5 - 11.39 - Customer1 - - - XYZ0002 - 2 - 72.99 - Customer2c - - - XYZ0003 - 9 - 99.99 - Customer3 - + + + + XYZ0001 + 5 + 11.39 + Customer1 + + + XYZ0002 + 2 + 72.99 + Customer2c + + + XYZ0003 + 9 + 99.99 + Customer3 + + + XYZ0001 + 5 + 11.39 + Customer1 + + + XYZ0002 + 2 + 72.99 + Customer2c + + + XYZ0003 + 9 + 99.99 + Customer3 + + + XYZ0001 + 5 + 11.39 + Customer1 + + + XYZ0002 + 2 + 72.99 + Customer2c + + + XYZ0003 + 9 + 99.99 + Customer3 + \ No newline at end of file diff --git a/spring-batch-samples/src/main/resources/data/tradeJob/input/20070122.teststream.ImportTradeDataStep.txt b/spring-batch-samples/src/main/resources/data/tradeJob/input/20070122.teststream.ImportTradeDataStep.txt index 94c81c5bfb..bf1dcc795e 100644 --- a/spring-batch-samples/src/main/resources/data/tradeJob/input/20070122.teststream.ImportTradeDataStep.txt +++ b/spring-batch-samples/src/main/resources/data/tradeJob/input/20070122.teststream.ImportTradeDataStep.txt @@ -1,5 +1,5 @@ -UK21341EAH45,978,98.34,customer1 -UK21341EAH46,112,18.12,customer2 -UK21341EAH47,245,12.78,customer2 -UK21341EAH48,108,109.25,customer3 +UK21341EAH45,978,98.34,customer1 +UK21341EAH46,112,18.12,customer2 +UK21341EAH47,245,12.78,customer2 +UK21341EAH48,108,109.25,customer3 UK21341EAH49,854,123.39,customer4 \ No newline at end of file diff --git a/spring-batch-samples/src/main/resources/ibatis-config.xml b/spring-batch-samples/src/main/resources/ibatis-config.xml index 158fd60bf7..9d2f4e8c32 100644 --- a/spring-batch-samples/src/main/resources/ibatis-config.xml +++ b/spring-batch-samples/src/main/resources/ibatis-config.xml @@ -1,9 +1,9 @@ - - - - - - - + + + + + + + \ No newline at end of file diff --git a/spring-batch-samples/src/main/resources/ibatis-customer-credit.xml b/spring-batch-samples/src/main/resources/ibatis-customer-credit.xml index 98f7d26b8d..14c8ae0960 100644 --- a/spring-batch-samples/src/main/resources/ibatis-customer-credit.xml +++ b/spring-batch-samples/src/main/resources/ibatis-customer-credit.xml @@ -1,24 +1,24 @@ - - - - - - - - - - - - - - - - update CUSTOMER set CREDIT = #credit# where NAME = #name# - - + + + + + + + + + + + + + + + + update CUSTOMER set CREDIT = #credit# where NAME = #name# + + \ No newline at end of file diff --git a/spring-batch-samples/src/main/resources/jobs/multilineOrderInputDescriptors.xml b/spring-batch-samples/src/main/resources/jobs/multilineOrderInputDescriptors.xml index d3d9a1a00f..5341c79675 100644 --- a/spring-batch-samples/src/main/resources/jobs/multilineOrderInputDescriptors.xml +++ b/spring-batch-samples/src/main/resources/jobs/multilineOrderInputDescriptors.xml @@ -1,71 +1,71 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/spring-batch-samples/src/main/resources/jobs/multilineOrderJob.xml b/spring-batch-samples/src/main/resources/jobs/multilineOrderJob.xml index 664501ffdc..40f8e8876a 100644 --- a/spring-batch-samples/src/main/resources/jobs/multilineOrderJob.xml +++ b/spring-batch-samples/src/main/resources/jobs/multilineOrderJob.xml @@ -1,176 +1,176 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 AND ? <= 9999999999 : 'Incorrect order ID' : 'error.order.id' } - { orderDate : isFutureDate(?) = FALSE : 'Future date is not allowed' : 'error.order.date.future' } - { totalLines : ? = size(lineItems) : 'Bad count of order lines' : 'error.order.lines.badcount'} - - { customer.registered : customer.businessCustomer = FALSE OR ? = TRUE : 'Business customer must be registered' : 'error.customer.registration'} - { customer.companyName : customer.businessCustomer = FALSE OR ? HAS TEXT : 'Company name for business customer is mandatory' : 'error.customer.companyname'} - { customer.firstName : customer.businessCustomer = TRUE OR ? HAS TEXT : 'Firstname for non-business customer is mandatory' : 'error.customer.firstname'} - { customer.lastName : customer.businessCustomer = TRUE OR ? HAS TEXT : 'Lastname name for non-business customer is mandatory' : 'error.customer.lastname'} - { customer.registrationId : customer.registered = FALSE OR (? > 0 AND ? < 99999999) : 'Incorrect registration ID' : 'error.customer.registrationid'} - - { billingAddress.addressee : ? HAS NO TEXT OR length(?) <= 60 : 'Maximum length for Addressee is 60 characters' : 'error.baddress.addresse.length'} - { billingAddress.addrLine1 : ? HAS TEXT AND length(?) <= 50 : 'Address line1 is mandatory and maximum length for address line1 is 50 characters' : 'error.baddress.addrline1.length'} - { billingAddress.addrLine2 : ? HAS NO TEXT OR length(?) <= 50 : 'Maximum length for address line2 is 50 characters' : 'error.baddress.addrline2.length'} - { billingAddress.city : ? HAS TEXT AND length(?) <= 30 : 'City is mandatory and maximum length for city is 30 characters' : 'error.baddress.city.length'} - { billingAddress.zipCode : ? HAS TEXT AND length(?) <= 50 : 'Zipcode is mandatory and maximum length for zipcode is 5 characters' : 'error.baddress.zipcode.length'} - { billingAddress.zipCode : match('[0-9]{5}',?) = TRUE : 'ZipCode must contain exactly 5 digits' : 'error.baddress.zipcode.format'} - { billingAddress.state : (? HAS NO TEXT AND billingAddress.country != 'United States') OR (? HAS TEXT AND length(?) <= 2) : 'Maximum length for state is 2 characters' : 'error.baddress.state.length'} - { billingAddress.country : ? HAS TEXT AND length(?) <= 50 : 'Country is mandatory and maximum length for country is 50 characters' : 'error.baddress.country.length'} - - { shippingAddress.addressee : shippingAddress IS NULL OR (? HAS TEXT AND length(?) <= 60) : 'Addressee is mandatory and maximum length for addressee is 60 characters' : 'error.saddress.addresse.length'} - { shippingAddress.addrLine1 : shippingAddress IS NULL OR (? HAS TEXT AND length(?) <= 50) : 'Address line1 is mandatory and maximum length for address line1 is 50 characters' : 'error.baddress.addrline1.length'} - { shippingAddress.addrLine2 : shippingAddress IS NULL OR (? HAS NO TEXT OR length(?) <= 50) : 'Maximum length for address line2 is 50 characters' : 'error.baddress.addrline2.length'} - { shippingAddress.city : shippingAddress IS NULL OR (? HAS TEXT AND length(?) <= 30) : 'City is mandatory and maximum length for city is 30 characters' : 'error.baddress.city.length'} - { shippingAddress.zipCode : shippingAddress IS NULL OR (? HAS TEXT AND length(?) <= 50) : 'Zipcode is mandatory and maximum length for zipcode is 5 characters' : 'error.baddress.zipcode.length'} - { shippingAddress.zipCode : shippingAddress IS NULL OR (match('[0-9]{5}',?) = TRUE) : 'Zipcode must contain exactly 5 digits' : 'error.baddress.zipcode.format'} - { shippingAddress.state : shippingAddress IS NULL OR ((? HAS NO TEXT AND billingAddress.country != 'United States') OR (? HAS TEXT AND length(?) <= 2)) : 'Maximum length for state is 2 characters' : 'error.baddress.state.length'} - { shippingAddress.country : shippingAddress IS NULL OR (? HAS TEXT AND length(?) <= 50) : 'Country is mandatory and maximum length for country is 50 characters' : 'error.baddress.country.length'} - - { billing.paymentId : ? IN 'VISA','AMEX','ECMC','DCIN','PAYP' : 'Invalid payment type' : 'error.billing.type' } - { billing.paymentDesc : match('[A-Z]{4}-[0-9]{10,11}',?) = TRUE : 'Invalid format of payment description' : 'error.billing.desc' } - - { shipping.shipperId : ? IN 'FEDX', 'UPS', 'DHL', 'DPD' : 'Invalid shipper ID' : 'error.shipping.shipper'} - { shipping.shippingTypeId : ? IN 'STD', 'EXP', 'AMS', 'AME' : 'Invalid shipping type' : 'error.shipping.type' } - { shipping.shippingInfo : ? HAS NO TEXT OR length(?) <= 100 : 'Maximum length for additional shipping info is 100 characters' } - - { lineItems : validateTotalItemsCount(totalItems,?) = TRUE : 'Bad count of total line items' : 'error.lineitems.badcount' } - { lineItems : validateIds(?) = TRUE : 'One or more invalid item IDs' : 'error.lineitems.id' } - { lineItems : validatePrices(?) = TRUE : 'One or more invalid item prices' : 'error.lineitems.price' } - { lineItems : validateDiscounts(?) = TRUE : 'One or more invalid item discounts' : 'error.lineitems.discount' } - { lineItems : validateShippingPrices(?) = TRUE : 'One or more invalid item shipping prices' : 'error.lineitems.shipping' } - { lineItems : validateHandlingPrices(?) = TRUE : 'One or more invalid item handling prices' : 'error.lineitems.handling' } - { lineItems : validateQuantities(?) = TRUE : 'One or more invalid item quantities' : 'error.lineitems.quantity' } - { lineItems : validateTotalPrices(?) = TRUE : 'One or more invalid item total prices' : 'error.lineitems.totalprice' } - ]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 AND ? <= 9999999999 : 'Incorrect order ID' : 'error.order.id' } + { orderDate : isFutureDate(?) = FALSE : 'Future date is not allowed' : 'error.order.date.future' } + { totalLines : ? = size(lineItems) : 'Bad count of order lines' : 'error.order.lines.badcount'} + + { customer.registered : customer.businessCustomer = FALSE OR ? = TRUE : 'Business customer must be registered' : 'error.customer.registration'} + { customer.companyName : customer.businessCustomer = FALSE OR ? HAS TEXT : 'Company name for business customer is mandatory' : 'error.customer.companyname'} + { customer.firstName : customer.businessCustomer = TRUE OR ? HAS TEXT : 'Firstname for non-business customer is mandatory' : 'error.customer.firstname'} + { customer.lastName : customer.businessCustomer = TRUE OR ? HAS TEXT : 'Lastname name for non-business customer is mandatory' : 'error.customer.lastname'} + { customer.registrationId : customer.registered = FALSE OR (? > 0 AND ? < 99999999) : 'Incorrect registration ID' : 'error.customer.registrationid'} + + { billingAddress.addressee : ? HAS NO TEXT OR length(?) <= 60 : 'Maximum length for Addressee is 60 characters' : 'error.baddress.addresse.length'} + { billingAddress.addrLine1 : ? HAS TEXT AND length(?) <= 50 : 'Address line1 is mandatory and maximum length for address line1 is 50 characters' : 'error.baddress.addrline1.length'} + { billingAddress.addrLine2 : ? HAS NO TEXT OR length(?) <= 50 : 'Maximum length for address line2 is 50 characters' : 'error.baddress.addrline2.length'} + { billingAddress.city : ? HAS TEXT AND length(?) <= 30 : 'City is mandatory and maximum length for city is 30 characters' : 'error.baddress.city.length'} + { billingAddress.zipCode : ? HAS TEXT AND length(?) <= 50 : 'Zipcode is mandatory and maximum length for zipcode is 5 characters' : 'error.baddress.zipcode.length'} + { billingAddress.zipCode : match('[0-9]{5}',?) = TRUE : 'ZipCode must contain exactly 5 digits' : 'error.baddress.zipcode.format'} + { billingAddress.state : (? HAS NO TEXT AND billingAddress.country != 'United States') OR (? HAS TEXT AND length(?) <= 2) : 'Maximum length for state is 2 characters' : 'error.baddress.state.length'} + { billingAddress.country : ? HAS TEXT AND length(?) <= 50 : 'Country is mandatory and maximum length for country is 50 characters' : 'error.baddress.country.length'} + + { shippingAddress.addressee : shippingAddress IS NULL OR (? HAS TEXT AND length(?) <= 60) : 'Addressee is mandatory and maximum length for addressee is 60 characters' : 'error.saddress.addresse.length'} + { shippingAddress.addrLine1 : shippingAddress IS NULL OR (? HAS TEXT AND length(?) <= 50) : 'Address line1 is mandatory and maximum length for address line1 is 50 characters' : 'error.baddress.addrline1.length'} + { shippingAddress.addrLine2 : shippingAddress IS NULL OR (? HAS NO TEXT OR length(?) <= 50) : 'Maximum length for address line2 is 50 characters' : 'error.baddress.addrline2.length'} + { shippingAddress.city : shippingAddress IS NULL OR (? HAS TEXT AND length(?) <= 30) : 'City is mandatory and maximum length for city is 30 characters' : 'error.baddress.city.length'} + { shippingAddress.zipCode : shippingAddress IS NULL OR (? HAS TEXT AND length(?) <= 50) : 'Zipcode is mandatory and maximum length for zipcode is 5 characters' : 'error.baddress.zipcode.length'} + { shippingAddress.zipCode : shippingAddress IS NULL OR (match('[0-9]{5}',?) = TRUE) : 'Zipcode must contain exactly 5 digits' : 'error.baddress.zipcode.format'} + { shippingAddress.state : shippingAddress IS NULL OR ((? HAS NO TEXT AND billingAddress.country != 'United States') OR (? HAS TEXT AND length(?) <= 2)) : 'Maximum length for state is 2 characters' : 'error.baddress.state.length'} + { shippingAddress.country : shippingAddress IS NULL OR (? HAS TEXT AND length(?) <= 50) : 'Country is mandatory and maximum length for country is 50 characters' : 'error.baddress.country.length'} + + { billing.paymentId : ? IN 'VISA','AMEX','ECMC','DCIN','PAYP' : 'Invalid payment type' : 'error.billing.type' } + { billing.paymentDesc : match('[A-Z]{4}-[0-9]{10,11}',?) = TRUE : 'Invalid format of payment description' : 'error.billing.desc' } + + { shipping.shipperId : ? IN 'FEDX', 'UPS', 'DHL', 'DPD' : 'Invalid shipper ID' : 'error.shipping.shipper'} + { shipping.shippingTypeId : ? IN 'STD', 'EXP', 'AMS', 'AME' : 'Invalid shipping type' : 'error.shipping.type' } + { shipping.shippingInfo : ? HAS NO TEXT OR length(?) <= 100 : 'Maximum length for additional shipping info is 100 characters' } + + { lineItems : validateTotalItemsCount(totalItems,?) = TRUE : 'Bad count of total line items' : 'error.lineitems.badcount' } + { lineItems : validateIds(?) = TRUE : 'One or more invalid item IDs' : 'error.lineitems.id' } + { lineItems : validatePrices(?) = TRUE : 'One or more invalid item prices' : 'error.lineitems.price' } + { lineItems : validateDiscounts(?) = TRUE : 'One or more invalid item discounts' : 'error.lineitems.discount' } + { lineItems : validateShippingPrices(?) = TRUE : 'One or more invalid item shipping prices' : 'error.lineitems.shipping' } + { lineItems : validateHandlingPrices(?) = TRUE : 'One or more invalid item handling prices' : 'error.lineitems.handling' } + { lineItems : validateQuantities(?) = TRUE : 'One or more invalid item quantities' : 'error.lineitems.quantity' } + { lineItems : validateTotalPrices(?) = TRUE : 'One or more invalid item total prices' : 'error.lineitems.totalprice' } + ]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/spring-batch-samples/src/main/resources/jobs/multilineOrderOutputDescriptors.xml b/spring-batch-samples/src/main/resources/jobs/multilineOrderOutputDescriptors.xml index 45799d1936..1a1e813ad3 100644 --- a/spring-batch-samples/src/main/resources/jobs/multilineOrderOutputDescriptors.xml +++ b/spring-batch-samples/src/main/resources/jobs/multilineOrderOutputDescriptors.xml @@ -1,39 +1,39 @@ - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/spring-batch-samples/src/main/sql/business-schema.sql.vpp b/spring-batch-samples/src/main/sql/business-schema.sql.vpp index 4f47abacdd..d0bdede8e0 100644 --- a/spring-batch-samples/src/main/sql/business-schema.sql.vpp +++ b/spring-batch-samples/src/main/sql/business-schema.sql.vpp @@ -1,3 +1,3 @@ -#parse("${includes}/destroy.sql.vpp") - +#parse("${includes}/destroy.sql.vpp") + #parse("${includes}/init.sql.vpp") \ No newline at end of file diff --git a/spring-batch-samples/src/main/sql/db2.properties b/spring-batch-samples/src/main/sql/db2.properties index 9aecf2661e..9e03eee38e 100644 --- a/spring-batch-samples/src/main/sql/db2.properties +++ b/spring-batch-samples/src/main/sql/db2.properties @@ -1,7 +1,7 @@ -platform=db2 -# SQL language oddities -BIGINT = BIGINT -IDENTITY = -BLOB = BLOB -# for generating drop statements... -SEQUENCE = SEQUENCE +platform=db2 +# SQL language oddities +BIGINT = BIGINT +IDENTITY = +BLOB = BLOB +# for generating drop statements... +SEQUENCE = SEQUENCE diff --git a/spring-batch-samples/src/main/sql/db2.vpp b/spring-batch-samples/src/main/sql/db2.vpp index 3713aa6f5d..56bd1c6e38 100644 --- a/spring-batch-samples/src/main/sql/db2.vpp +++ b/spring-batch-samples/src/main/sql/db2.vpp @@ -1,2 +1,2 @@ -#macro (sequence $name)CREATE SEQUENCE ${name}; -#end +#macro (sequence $name)CREATE SEQUENCE ${name}; +#end diff --git a/spring-batch-samples/src/main/sql/derby.properties b/spring-batch-samples/src/main/sql/derby.properties index e880dbcc0f..89d610dbfd 100644 --- a/spring-batch-samples/src/main/sql/derby.properties +++ b/spring-batch-samples/src/main/sql/derby.properties @@ -1,8 +1,8 @@ -platform=db2 -# SQL language oddities -BIGINT = BIGINT -IDENTITY = -GENERATED = GENERATED BY DEFAULT AS IDENTITY -BLOB = BLOB -# for generating drop statements... -SEQUENCE = TABLE +platform=db2 +# SQL language oddities +BIGINT = BIGINT +IDENTITY = +GENERATED = GENERATED BY DEFAULT AS IDENTITY +BLOB = BLOB +# for generating drop statements... +SEQUENCE = TABLE diff --git a/spring-batch-samples/src/main/sql/derby.vpp b/spring-batch-samples/src/main/sql/derby.vpp index 00645d2a75..95d9c397ac 100644 --- a/spring-batch-samples/src/main/sql/derby.vpp +++ b/spring-batch-samples/src/main/sql/derby.vpp @@ -1,2 +1,2 @@ -#macro (sequence $name)CREATE TABLE ${name} (ID BIGINT PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY, DUMMY VARCHAR(1)); -#end +#macro (sequence $name)CREATE TABLE ${name} (ID BIGINT PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY, DUMMY VARCHAR(1)); +#end diff --git a/spring-batch-samples/src/main/sql/hsqldb.properties b/spring-batch-samples/src/main/sql/hsqldb.properties index 4a853dc4e0..1b6ceb2f04 100644 --- a/spring-batch-samples/src/main/sql/hsqldb.properties +++ b/spring-batch-samples/src/main/sql/hsqldb.properties @@ -1,8 +1,8 @@ -platform=hsqldb -# SQL language oddities -BIGINT = BIGINT -IDENTITY = IDENTITY -IFEXISTS = IF EXISTS -BLOB = LONGVARBINARY -# for generating drop statements... -SEQUENCE = TABLE +platform=hsqldb +# SQL language oddities +BIGINT = BIGINT +IDENTITY = IDENTITY +IFEXISTS = IF EXISTS +BLOB = LONGVARBINARY +# for generating drop statements... +SEQUENCE = TABLE diff --git a/spring-batch-samples/src/main/sql/hsqldb.vpp b/spring-batch-samples/src/main/sql/hsqldb.vpp index 6259ee1244..9fbc68564f 100644 --- a/spring-batch-samples/src/main/sql/hsqldb.vpp +++ b/spring-batch-samples/src/main/sql/hsqldb.vpp @@ -1,4 +1,4 @@ -#macro (sequence $name)CREATE TABLE ${name} ( - ID BIGINT IDENTITY -); -#end +#macro (sequence $name)CREATE TABLE ${name} ( + ID BIGINT IDENTITY +); +#end diff --git a/spring-batch-samples/src/main/sql/mysql.properties b/spring-batch-samples/src/main/sql/mysql.properties index 71b7b72ef9..b86c7b6fe4 100644 --- a/spring-batch-samples/src/main/sql/mysql.properties +++ b/spring-batch-samples/src/main/sql/mysql.properties @@ -1,9 +1,9 @@ -platform=oracle10g -# SQL language oddities -BIGINT = BIGINT -IDENTITY = unsigned -GENERATED = -IFEXISTSBEFORE = IF EXISTS -BLOB = BLOB -# for generating drop statements... -SEQUENCE = TABLE +platform=oracle10g +# SQL language oddities +BIGINT = BIGINT +IDENTITY = unsigned +GENERATED = +IFEXISTSBEFORE = IF EXISTS +BLOB = BLOB +# for generating drop statements... +SEQUENCE = TABLE diff --git a/spring-batch-samples/src/main/sql/mysql.vpp b/spring-batch-samples/src/main/sql/mysql.vpp index 5e4dd6446a..1812fa9776 100644 --- a/spring-batch-samples/src/main/sql/mysql.vpp +++ b/spring-batch-samples/src/main/sql/mysql.vpp @@ -1,3 +1,3 @@ -#macro (sequence $name)CREATE TABLE ${name} (ID BIGINT NOT NULL) type=MYISAM; -INSERT INTO ${name} values(0); -#end +#macro (sequence $name)CREATE TABLE ${name} (ID BIGINT NOT NULL) type=MYISAM; +INSERT INTO ${name} values(0); +#end diff --git a/spring-batch-samples/src/main/sql/oracle10g.properties b/spring-batch-samples/src/main/sql/oracle10g.properties index cfe99eeb32..86bf7ec5b0 100644 --- a/spring-batch-samples/src/main/sql/oracle10g.properties +++ b/spring-batch-samples/src/main/sql/oracle10g.properties @@ -1,8 +1,8 @@ -platform=oracle10g -# SQL language oddities -BIGINT = NUMBER(38) -IDENTITY = -GENERATED = -BLOB = BLOB -# for generating drop statements... -SEQUENCE = SEQUENCE +platform=oracle10g +# SQL language oddities +BIGINT = NUMBER(38) +IDENTITY = +GENERATED = +BLOB = BLOB +# for generating drop statements... +SEQUENCE = SEQUENCE diff --git a/spring-batch-samples/src/main/sql/oracle10g.vpp b/spring-batch-samples/src/main/sql/oracle10g.vpp index 3713aa6f5d..56bd1c6e38 100644 --- a/spring-batch-samples/src/main/sql/oracle10g.vpp +++ b/spring-batch-samples/src/main/sql/oracle10g.vpp @@ -1,2 +1,2 @@ -#macro (sequence $name)CREATE SEQUENCE ${name}; -#end +#macro (sequence $name)CREATE SEQUENCE ${name}; +#end diff --git a/spring-batch-samples/src/main/sql/postgresql.properties b/spring-batch-samples/src/main/sql/postgresql.properties index 00b9007b4b..3cd8f8ce36 100644 --- a/spring-batch-samples/src/main/sql/postgresql.properties +++ b/spring-batch-samples/src/main/sql/postgresql.properties @@ -1,8 +1,8 @@ -platform=postgresql -# SQL language oddities -BIGINT = BIGINT -IDENTITY = -GENERATED = -BLOB = BYTEA -# for generating drop statements... -SEQUENCE = SEQUENCE +platform=postgresql +# SQL language oddities +BIGINT = BIGINT +IDENTITY = +GENERATED = +BLOB = BYTEA +# for generating drop statements... +SEQUENCE = SEQUENCE diff --git a/spring-batch-samples/src/main/sql/postgresql.vpp b/spring-batch-samples/src/main/sql/postgresql.vpp index 3713aa6f5d..56bd1c6e38 100644 --- a/spring-batch-samples/src/main/sql/postgresql.vpp +++ b/spring-batch-samples/src/main/sql/postgresql.vpp @@ -1,2 +1,2 @@ -#macro (sequence $name)CREATE SEQUENCE ${name}; -#end +#macro (sequence $name)CREATE SEQUENCE ${name}; +#end diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/AbstractCustomerCreditIncreaseTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/AbstractCustomerCreditIncreaseTests.java index 1c2fd6ef53..84107122a9 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/AbstractCustomerCreditIncreaseTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/AbstractCustomerCreditIncreaseTests.java @@ -1,141 +1,141 @@ -package org.springframework.batch.sample; - -import java.math.BigDecimal; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.List; - -import org.springframework.batch.sample.item.writer.CustomerCreditIncreaseWriter; -import org.springframework.jdbc.core.JdbcOperations; -import org.springframework.jdbc.core.RowMapper; -import org.springframework.transaction.PlatformTransactionManager; -import org.springframework.transaction.TransactionStatus; -import org.springframework.transaction.support.TransactionCallback; -import org.springframework.transaction.support.TransactionTemplate; - -/** - * Test case for jobs that are expected to update customer credit value by fixed - * amount. - * - * @author Robert Kasanicky - * @author Dave Syer - */ -public abstract class AbstractCustomerCreditIncreaseTests extends AbstractValidatingBatchLauncherTests { - - protected JdbcOperations jdbcTemplate; - - protected PlatformTransactionManager transactionManager; - - private static final BigDecimal CREDIT_INCREASE = CustomerCreditIncreaseWriter.FIXED_AMOUNT; - - private static String[] customers = { "INSERT INTO customer (id, version, name, credit) VALUES (1, 0, 'customer1', 100000)", - "INSERT INTO customer (id, version, name, credit) VALUES (2, 0, 'customer2', 100000)", - "INSERT INTO customer (id, version, name, credit) VALUES (3, 0, 'customer3', 100000)", - "INSERT INTO customer (id, version, name, credit) VALUES (4, 0, 'customer4', 100000)"}; - - private static String DELETE_CUSTOMERS = "DELETE FROM customer"; - - private static final String ALL_CUSTOMERS = "select * from CUSTOMER order by ID"; - - private static final String CREDIT_COLUMN = "CREDIT"; - - protected static final String ID_COLUMN = "ID"; - - private List creditsBeforeUpdate; - - /** - * @param jdbcTemplate - */ - public void setJdbcTemplate(JdbcOperations jdbcTemplate) { - this.jdbcTemplate = jdbcTemplate; - } - - /** - * Public setter for the PlatformTransactionManager. - * @param transactionManager the transactionManager to set - */ - public void setTransactionManager(PlatformTransactionManager transactionManager) { - this.transactionManager = transactionManager; - } - - /** - * All customers have the same credit - */ - protected void validatePreConditions() throws Exception { - super.validatePreConditions(); - ensureState(); - creditsBeforeUpdate = (List) new TransactionTemplate(transactionManager).execute(new TransactionCallback() { - public Object doInTransaction(TransactionStatus status) { - - return jdbcTemplate.query(ALL_CUSTOMERS, new RowMapper() { - public Object mapRow(ResultSet rs, int rowNum) throws SQLException { - return rs.getBigDecimal(CREDIT_COLUMN); - } - }); - } - }); - } - - /* - * Ensure the state of the database is accurate by delete all the contents of the - * customer table and reading the expected defaults. - */ - private void ensureState(){ - new TransactionTemplate(transactionManager).execute(new TransactionCallback(){ - - public Object doInTransaction(TransactionStatus status) { - jdbcTemplate.update(DELETE_CUSTOMERS); - for(int i = 0; i < customers.length;i++){ - jdbcTemplate.update(customers[i]); - } - return null; - } - }); - - } - - /** - * Credit was increased by CREDIT_INCREASE - */ - protected void validatePostConditions() throws Exception { - - final List matches = new ArrayList(); - - new TransactionTemplate(transactionManager).execute(new TransactionCallback() { - public Object doInTransaction(TransactionStatus status) { - jdbcTemplate.query(ALL_CUSTOMERS, new RowMapper() { - - public Object mapRow(ResultSet rs, int rowNum) throws SQLException { - final BigDecimal creditBeforeUpdate = (BigDecimal) creditsBeforeUpdate.get(rowNum); - final BigDecimal expectedCredit = creditBeforeUpdate.add(CREDIT_INCREASE); - if (expectedCredit.equals(rs.getBigDecimal(CREDIT_COLUMN))) { - matches.add(rs.getBigDecimal(ID_COLUMN)); - } - return null; - } - - }); - return null; - } - }); - - assertEquals(getExpectedMatches(), matches.size()); - checkMatches(matches); - } - - /** - * @param matches - */ - protected void checkMatches(List matches) { - // no-op... - } - - /** - * @return the expected number of matches in the updated credits. - */ - protected int getExpectedMatches() { - return creditsBeforeUpdate.size(); - } - -} +package org.springframework.batch.sample; + +import java.math.BigDecimal; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; + +import org.springframework.batch.sample.item.writer.CustomerCreditIncreaseWriter; +import org.springframework.jdbc.core.JdbcOperations; +import org.springframework.jdbc.core.RowMapper; +import org.springframework.transaction.PlatformTransactionManager; +import org.springframework.transaction.TransactionStatus; +import org.springframework.transaction.support.TransactionCallback; +import org.springframework.transaction.support.TransactionTemplate; + +/** + * Test case for jobs that are expected to update customer credit value by fixed + * amount. + * + * @author Robert Kasanicky + * @author Dave Syer + */ +public abstract class AbstractCustomerCreditIncreaseTests extends AbstractValidatingBatchLauncherTests { + + protected JdbcOperations jdbcTemplate; + + protected PlatformTransactionManager transactionManager; + + private static final BigDecimal CREDIT_INCREASE = CustomerCreditIncreaseWriter.FIXED_AMOUNT; + + private static String[] customers = { "INSERT INTO customer (id, version, name, credit) VALUES (1, 0, 'customer1', 100000)", + "INSERT INTO customer (id, version, name, credit) VALUES (2, 0, 'customer2', 100000)", + "INSERT INTO customer (id, version, name, credit) VALUES (3, 0, 'customer3', 100000)", + "INSERT INTO customer (id, version, name, credit) VALUES (4, 0, 'customer4', 100000)"}; + + private static String DELETE_CUSTOMERS = "DELETE FROM customer"; + + private static final String ALL_CUSTOMERS = "select * from CUSTOMER order by ID"; + + private static final String CREDIT_COLUMN = "CREDIT"; + + protected static final String ID_COLUMN = "ID"; + + private List creditsBeforeUpdate; + + /** + * @param jdbcTemplate + */ + public void setJdbcTemplate(JdbcOperations jdbcTemplate) { + this.jdbcTemplate = jdbcTemplate; + } + + /** + * Public setter for the PlatformTransactionManager. + * @param transactionManager the transactionManager to set + */ + public void setTransactionManager(PlatformTransactionManager transactionManager) { + this.transactionManager = transactionManager; + } + + /** + * All customers have the same credit + */ + protected void validatePreConditions() throws Exception { + super.validatePreConditions(); + ensureState(); + creditsBeforeUpdate = (List) new TransactionTemplate(transactionManager).execute(new TransactionCallback() { + public Object doInTransaction(TransactionStatus status) { + + return jdbcTemplate.query(ALL_CUSTOMERS, new RowMapper() { + public Object mapRow(ResultSet rs, int rowNum) throws SQLException { + return rs.getBigDecimal(CREDIT_COLUMN); + } + }); + } + }); + } + + /* + * Ensure the state of the database is accurate by delete all the contents of the + * customer table and reading the expected defaults. + */ + private void ensureState(){ + new TransactionTemplate(transactionManager).execute(new TransactionCallback(){ + + public Object doInTransaction(TransactionStatus status) { + jdbcTemplate.update(DELETE_CUSTOMERS); + for(int i = 0; i < customers.length;i++){ + jdbcTemplate.update(customers[i]); + } + return null; + } + }); + + } + + /** + * Credit was increased by CREDIT_INCREASE + */ + protected void validatePostConditions() throws Exception { + + final List matches = new ArrayList(); + + new TransactionTemplate(transactionManager).execute(new TransactionCallback() { + public Object doInTransaction(TransactionStatus status) { + jdbcTemplate.query(ALL_CUSTOMERS, new RowMapper() { + + public Object mapRow(ResultSet rs, int rowNum) throws SQLException { + final BigDecimal creditBeforeUpdate = (BigDecimal) creditsBeforeUpdate.get(rowNum); + final BigDecimal expectedCredit = creditBeforeUpdate.add(CREDIT_INCREASE); + if (expectedCredit.equals(rs.getBigDecimal(CREDIT_COLUMN))) { + matches.add(rs.getBigDecimal(ID_COLUMN)); + } + return null; + } + + }); + return null; + } + }); + + assertEquals(getExpectedMatches(), matches.size()); + checkMatches(matches); + } + + /** + * @param matches + */ + protected void checkMatches(List matches) { + // no-op... + } + + /** + * @return the expected number of matches in the updated credits. + */ + protected int getExpectedMatches() { + return creditsBeforeUpdate.size(); + } + +} diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/BatchSqlUpdateJobFunctionalTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/BatchSqlUpdateJobFunctionalTests.java index 3fcbcd07f0..d5052eaf20 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/BatchSqlUpdateJobFunctionalTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/BatchSqlUpdateJobFunctionalTests.java @@ -1,10 +1,10 @@ -package org.springframework.batch.sample; - -/** - * Test for BatchSqlUpdateJob - checks that customer credit has been updated to expected value. - * - * @author Robert Kasanicky - */ -public class BatchSqlUpdateJobFunctionalTests extends AbstractCustomerCreditIncreaseTests { - -} +package org.springframework.batch.sample; + +/** + * Test for BatchSqlUpdateJob - checks that customer credit has been updated to expected value. + * + * @author Robert Kasanicky + */ +public class BatchSqlUpdateJobFunctionalTests extends AbstractCustomerCreditIncreaseTests { + +} diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/CompositeProcessorSampleFunctionalTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/CompositeProcessorSampleFunctionalTests.java index 03c7b326c7..1fc6a5b02e 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/CompositeProcessorSampleFunctionalTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/CompositeProcessorSampleFunctionalTests.java @@ -1,91 +1,91 @@ -package org.springframework.batch.sample; - -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.math.BigDecimal; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -import org.apache.commons.io.IOUtils; -import org.springframework.batch.sample.domain.Trade; -import org.springframework.jdbc.core.JdbcOperations; -import org.springframework.jdbc.core.RowCallbackHandler; - - -public class CompositeProcessorSampleFunctionalTests extends AbstractValidatingBatchLauncherTests { - - private static final String GET_TRADES = "SELECT isin, quantity, price, customer FROM trade order by isin"; - - private static final String EXPECTED_OUTPUT_FILE = - "Trade: [isin=UK21341EAH41,quantity=211,price=31.11,customer=customer1]" + - "Trade: [isin=UK21341EAH42,quantity=212,price=32.11,customer=customer2]" + - "Trade: [isin=UK21341EAH43,quantity=213,price=33.11,customer=customer3]" + - "Trade: [isin=UK21341EAH44,quantity=214,price=34.11,customer=customer4]" + - "Trade: [isin=UK21341EAH45,quantity=215,price=35.11,customer=customer5]"; - - private JdbcOperations jdbcTemplate; - - private int activeRow = 0; - - private int before; - - /* (non-Javadoc) - * @see org.springframework.batch.sample.AbstractLifecycleSpringContextTests#validatePreConditions() - */ - protected void validatePreConditions() throws Exception { - jdbcTemplate.update("DELETE from TRADE"); - before = jdbcTemplate.queryForInt("SELECT COUNT(*) from TRADE"); - } - - protected void validatePostConditions() throws Exception { - checkOutputFile(); - checkOutputTable(); - } - - private void checkOutputTable() { - final List trades = new ArrayList() {{ - add(new Trade("UK21341EAH41", 211, new BigDecimal("31.11"), "customer1")); - add(new Trade("UK21341EAH42", 212, new BigDecimal("32.11"), "customer2")); - add(new Trade("UK21341EAH43", 213, new BigDecimal("33.11"), "customer3")); - add(new Trade("UK21341EAH44", 214, new BigDecimal("34.11"), "customer4")); - add(new Trade("UK21341EAH45", 215, new BigDecimal("35.11"), "customer5")); - }}; - - int after = jdbcTemplate.queryForInt("SELECT COUNT(*) from TRADE"); - - assertEquals(before+5, after); - - jdbcTemplate.query(GET_TRADES, new RowCallbackHandler() { - public void processRow(ResultSet rs) throws SQLException { - Trade trade = (Trade)trades.get(activeRow++); - - assertEquals(trade.getIsin(), rs.getString(1)); - assertEquals(trade.getQuantity(), rs.getLong(2)); - assertEquals(trade.getPrice(), rs.getBigDecimal(3)); - assertEquals(trade.getCustomer(), rs.getString(4)); - } - }); - - } - - private void checkOutputFile() throws FileNotFoundException, IOException { - List outputLines = IOUtils.readLines( - new FileInputStream("target/test-outputs/20070122.testStream.ParallelCustomerReportStep.TEMP.txt")); - - String output = ""; - for (Iterator iterator = outputLines.listIterator(); iterator.hasNext();) { - String line = (String) iterator.next(); - output += line; - } - - assertEquals(EXPECTED_OUTPUT_FILE, output); - } - - public void setJdbcTemplate(JdbcOperations jdbcTemplate) { - this.jdbcTemplate = jdbcTemplate; - } -} +package org.springframework.batch.sample; + +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.math.BigDecimal; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.apache.commons.io.IOUtils; +import org.springframework.batch.sample.domain.Trade; +import org.springframework.jdbc.core.JdbcOperations; +import org.springframework.jdbc.core.RowCallbackHandler; + + +public class CompositeProcessorSampleFunctionalTests extends AbstractValidatingBatchLauncherTests { + + private static final String GET_TRADES = "SELECT isin, quantity, price, customer FROM trade order by isin"; + + private static final String EXPECTED_OUTPUT_FILE = + "Trade: [isin=UK21341EAH41,quantity=211,price=31.11,customer=customer1]" + + "Trade: [isin=UK21341EAH42,quantity=212,price=32.11,customer=customer2]" + + "Trade: [isin=UK21341EAH43,quantity=213,price=33.11,customer=customer3]" + + "Trade: [isin=UK21341EAH44,quantity=214,price=34.11,customer=customer4]" + + "Trade: [isin=UK21341EAH45,quantity=215,price=35.11,customer=customer5]"; + + private JdbcOperations jdbcTemplate; + + private int activeRow = 0; + + private int before; + + /* (non-Javadoc) + * @see org.springframework.batch.sample.AbstractLifecycleSpringContextTests#validatePreConditions() + */ + protected void validatePreConditions() throws Exception { + jdbcTemplate.update("DELETE from TRADE"); + before = jdbcTemplate.queryForInt("SELECT COUNT(*) from TRADE"); + } + + protected void validatePostConditions() throws Exception { + checkOutputFile(); + checkOutputTable(); + } + + private void checkOutputTable() { + final List trades = new ArrayList() {{ + add(new Trade("UK21341EAH41", 211, new BigDecimal("31.11"), "customer1")); + add(new Trade("UK21341EAH42", 212, new BigDecimal("32.11"), "customer2")); + add(new Trade("UK21341EAH43", 213, new BigDecimal("33.11"), "customer3")); + add(new Trade("UK21341EAH44", 214, new BigDecimal("34.11"), "customer4")); + add(new Trade("UK21341EAH45", 215, new BigDecimal("35.11"), "customer5")); + }}; + + int after = jdbcTemplate.queryForInt("SELECT COUNT(*) from TRADE"); + + assertEquals(before+5, after); + + jdbcTemplate.query(GET_TRADES, new RowCallbackHandler() { + public void processRow(ResultSet rs) throws SQLException { + Trade trade = (Trade)trades.get(activeRow++); + + assertEquals(trade.getIsin(), rs.getString(1)); + assertEquals(trade.getQuantity(), rs.getLong(2)); + assertEquals(trade.getPrice(), rs.getBigDecimal(3)); + assertEquals(trade.getCustomer(), rs.getString(4)); + } + }); + + } + + private void checkOutputFile() throws FileNotFoundException, IOException { + List outputLines = IOUtils.readLines( + new FileInputStream("target/test-outputs/20070122.testStream.ParallelCustomerReportStep.TEMP.txt")); + + String output = ""; + for (Iterator iterator = outputLines.listIterator(); iterator.hasNext();) { + String line = (String) iterator.next(); + output += line; + } + + assertEquals(EXPECTED_OUTPUT_FILE, output); + } + + public void setJdbcTemplate(JdbcOperations jdbcTemplate) { + this.jdbcTemplate = jdbcTemplate; + } +} diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/DefaultJobLoader.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/DefaultJobLoader.java index df2e1c42ec..b36653dd9b 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/DefaultJobLoader.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/DefaultJobLoader.java @@ -1,96 +1,96 @@ -/** - * - */ -package org.springframework.batch.sample; - -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; - -import org.springframework.batch.core.configuration.ListableJobRegistry; -import org.springframework.batch.core.domain.Job; -import org.springframework.batch.core.repository.NoSuchJobException; -import org.springframework.beans.BeanWrapperImpl; -import org.springframework.beans.BeansException; -import org.springframework.beans.PropertyAccessorUtils; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationContextAware; -import org.springframework.context.support.ClassPathXmlApplicationContext; -import org.springframework.util.Assert; - -public class DefaultJobLoader implements JobLoader, - ApplicationContextAware { - - private ListableJobRegistry registry; - private ApplicationContext applicationContext; - private Map configurations = new HashMap(); - - public void setApplicationContext(ApplicationContext applicationContext) - throws BeansException { - this.applicationContext = applicationContext; - } - - public void setRegistry(ListableJobRegistry registry) { - this.registry = registry; - } - - public Map getConfigurations() { - Map result = new HashMap(configurations); - for (Iterator iterator = registry.getJobNames().iterator(); iterator - .hasNext();) { - try { - Job configuration = (Job) registry.getJob((String) iterator.next()); - String name = configuration.getName(); - if (!configurations.containsKey(name)) { - result.put(name, ": " + configuration); - } - } - catch (NoSuchJobException e) { - throw new IllegalStateException("Registry could not locate its own job (NoSuchJobException)."); - } - } - return result; - } - - public void loadResource(String path) { - ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext( - new String[] { path }, applicationContext); - String[] names = context.getBeanNamesForType(Job.class); - for (int i = 0; i < names.length; i++) { - String name = names[i]; - configurations.put(name, path); - } - } - - public Object getJobConfiguration(String name) { - try { - return registry.getJob(name); - } catch (NoSuchJobException e) { - return null; - } - } - - public Object getProperty(String path) { - int index = PropertyAccessorUtils.getFirstNestedPropertySeparatorIndex(path); - BeanWrapperImpl wrapper = createBeanWrapper(path, index); - String key = path.substring(index+1); - return wrapper.getPropertyValue(key); - } - - public void setProperty(String path, String value) { - int index = PropertyAccessorUtils.getFirstNestedPropertySeparatorIndex(path); - BeanWrapperImpl wrapper = createBeanWrapper(path, index); - String key = path.substring(index+1); - wrapper.setPropertyValue(key, value); - } - - private BeanWrapperImpl createBeanWrapper(String path, int index) { - Assert.state(index>0, "Path must be nested, e.g. bean.value"); - String name = path.substring(0,index); - Object bean = getJobConfiguration(name); - Assert.notNull(bean, "No JobConfiguration exists with name="+name); - BeanWrapperImpl wrapper = new BeanWrapperImpl(bean); - return wrapper; - } - -} +/** + * + */ +package org.springframework.batch.sample; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import org.springframework.batch.core.configuration.ListableJobRegistry; +import org.springframework.batch.core.domain.Job; +import org.springframework.batch.core.repository.NoSuchJobException; +import org.springframework.beans.BeanWrapperImpl; +import org.springframework.beans.BeansException; +import org.springframework.beans.PropertyAccessorUtils; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.context.support.ClassPathXmlApplicationContext; +import org.springframework.util.Assert; + +public class DefaultJobLoader implements JobLoader, + ApplicationContextAware { + + private ListableJobRegistry registry; + private ApplicationContext applicationContext; + private Map configurations = new HashMap(); + + public void setApplicationContext(ApplicationContext applicationContext) + throws BeansException { + this.applicationContext = applicationContext; + } + + public void setRegistry(ListableJobRegistry registry) { + this.registry = registry; + } + + public Map getConfigurations() { + Map result = new HashMap(configurations); + for (Iterator iterator = registry.getJobNames().iterator(); iterator + .hasNext();) { + try { + Job configuration = (Job) registry.getJob((String) iterator.next()); + String name = configuration.getName(); + if (!configurations.containsKey(name)) { + result.put(name, ": " + configuration); + } + } + catch (NoSuchJobException e) { + throw new IllegalStateException("Registry could not locate its own job (NoSuchJobException)."); + } + } + return result; + } + + public void loadResource(String path) { + ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext( + new String[] { path }, applicationContext); + String[] names = context.getBeanNamesForType(Job.class); + for (int i = 0; i < names.length; i++) { + String name = names[i]; + configurations.put(name, path); + } + } + + public Object getJobConfiguration(String name) { + try { + return registry.getJob(name); + } catch (NoSuchJobException e) { + return null; + } + } + + public Object getProperty(String path) { + int index = PropertyAccessorUtils.getFirstNestedPropertySeparatorIndex(path); + BeanWrapperImpl wrapper = createBeanWrapper(path, index); + String key = path.substring(index+1); + return wrapper.getPropertyValue(key); + } + + public void setProperty(String path, String value) { + int index = PropertyAccessorUtils.getFirstNestedPropertySeparatorIndex(path); + BeanWrapperImpl wrapper = createBeanWrapper(path, index); + String key = path.substring(index+1); + wrapper.setPropertyValue(key, value); + } + + private BeanWrapperImpl createBeanWrapper(String path, int index) { + Assert.state(index>0, "Path must be nested, e.g. bean.value"); + String name = path.substring(0,index); + Object bean = getJobConfiguration(name); + Assert.notNull(bean, "No JobConfiguration exists with name="+name); + BeanWrapperImpl wrapper = new BeanWrapperImpl(bean); + return wrapper; + } + +} diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/DelegatingJobFunctionalTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/DelegatingJobFunctionalTests.java index 437181abd9..b05a2ec4de 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/DelegatingJobFunctionalTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/DelegatingJobFunctionalTests.java @@ -1,21 +1,21 @@ -package org.springframework.batch.sample; - -import org.springframework.batch.sample.domain.PersonService; - -public class DelegatingJobFunctionalTests extends AbstractValidatingBatchLauncherTests { - - private PersonService personService; - - protected void validatePostConditions() throws Exception { - assertTrue(personService.getReturnedCount() > 0); - assertEquals(personService.getReturnedCount(), personService.getReceivedCount()); - - } - - // setter for auto-injection - public void setPersonService(PersonService personService) { - this.personService = personService; - } - - -} +package org.springframework.batch.sample; + +import org.springframework.batch.sample.domain.PersonService; + +public class DelegatingJobFunctionalTests extends AbstractValidatingBatchLauncherTests { + + private PersonService personService; + + protected void validatePostConditions() throws Exception { + assertTrue(personService.getReturnedCount() > 0); + assertEquals(personService.getReturnedCount(), personService.getReceivedCount()); + + } + + // setter for auto-injection + public void setPersonService(PersonService personService) { + this.personService = personService; + } + + +} diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/ExportedJobLoader.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/ExportedJobLoader.java index 5397f51d41..a0ce2d57fe 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/ExportedJobLoader.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/ExportedJobLoader.java @@ -1,37 +1,37 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.sample; - -import java.util.Map; - - -/** - * @author Dave Syer - * - */ -public interface ExportedJobLoader { - - void loadResource(String path); - - Map getConfigurations(); - - String getJob(String path); - - String getProperty(String path); - - void setProperty(String path, String value); - -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.sample; + +import java.util.Map; + + +/** + * @author Dave Syer + * + */ +public interface ExportedJobLoader { + + void loadResource(String path); + + Map getConfigurations(); + + String getJob(String path); + + String getProperty(String path); + + void setProperty(String path, String value); + +} diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/FootballJobFunctionalTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/FootballJobFunctionalTests.java index c46d6a94cc..fdd9b9d60c 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/FootballJobFunctionalTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/FootballJobFunctionalTests.java @@ -1,22 +1,22 @@ -package org.springframework.batch.sample; - -import javax.sql.DataSource; - -import org.springframework.jdbc.core.JdbcOperations; -import org.springframework.jdbc.core.JdbcTemplate; - -public class FootballJobFunctionalTests extends - AbstractValidatingBatchLauncherTests { - - private JdbcOperations jdbcTemplate; - - public void setDataSource(DataSource dataSource) { - this.jdbcTemplate = new JdbcTemplate(dataSource); - } - - protected void validatePostConditions() throws Exception { - int count = jdbcTemplate.queryForInt("SELECT COUNT(*) from PLAYER_SUMMARY"); - assertTrue(count>0); - } - -} +package org.springframework.batch.sample; + +import javax.sql.DataSource; + +import org.springframework.jdbc.core.JdbcOperations; +import org.springframework.jdbc.core.JdbcTemplate; + +public class FootballJobFunctionalTests extends + AbstractValidatingBatchLauncherTests { + + private JdbcOperations jdbcTemplate; + + public void setDataSource(DataSource dataSource) { + this.jdbcTemplate = new JdbcTemplate(dataSource); + } + + protected void validatePostConditions() throws Exception { + int count = jdbcTemplate.queryForInt("SELECT COUNT(*) from PLAYER_SUMMARY"); + assertTrue(count>0); + } + +} diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/HibernateFailureJobFunctionalTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/HibernateFailureJobFunctionalTests.java index 7217c3c9a2..234967bb0f 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/HibernateFailureJobFunctionalTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/HibernateFailureJobFunctionalTests.java @@ -1,89 +1,89 @@ -package org.springframework.batch.sample; - -import java.math.BigDecimal; -import java.util.List; - -import org.springframework.batch.core.domain.JobParameters; -import org.springframework.batch.core.domain.JobParametersBuilder; -import org.springframework.batch.sample.dao.HibernateCreditDao; -import org.springframework.jdbc.UncategorizedSQLException; -import org.springframework.orm.hibernate3.HibernateJdbcException; - -/** - * Test for HibernateJob - checks that customer credit has been updated to - * expected value. - * - * @author Dave Syer - */ -public class HibernateFailureJobFunctionalTests extends - HibernateJobFunctionalTests { - - private HibernateCreditDao writer; - - /** - * Public setter for the {@link HibernateCreditDao} property. - * - * @param writer - * the writer to set - */ - public void setWriter(HibernateCreditDao writer) { - this.writer = writer; - } - - /* - * (non-Javadoc) - * - * @see org.springframework.test.AbstractSingleSpringContextTests#onTearDown() - */ - protected void onTearDown() throws Exception { - super.onTearDown(); - writer.setFailOnFlush(-1); - } - - /* - * (non-Javadoc) - * - * @see org.springframework.batch.sample.AbstractValidatingBatchLauncherTests#testLaunchJob() - */ - public void testLaunchJob() throws Exception { - JobParameters params = new JobParametersBuilder().addString("key", "failureJob").toJobParameters(); - setJobParameters(params); - writer.setFailOnFlush(2); - - int before = jdbcTemplate.queryForInt("SELECT COUNT(*) from CUSTOMER"); - assertTrue(before > 0); - try { - super.testLaunchJob(); - } catch (HibernateJdbcException e) { - // This is what would happen if the flush happened outside the - // RepeatContext: - throw e; - } catch (UncategorizedSQLException e) { - // This is what would happen if the job wasn't configured to skip - // exceptions at the step level. - // assertEquals(1, writer.getErrors().size()); - throw e; - } - int after = jdbcTemplate.queryForInt("SELECT COUNT(*) from CUSTOMER"); - assertEquals(before, after); - } - - /* - * (non-Javadoc) - * - * @see org.springframework.batch.sample.AbstractCustomerCreditIncreaseTests#checkMatches(java.util.List) - */ - protected void checkMatches(List matches) { - assertFalse(matches.contains(new BigDecimal(2))); - } - - /* - * (non-Javadoc) - * - * @see org.springframework.batch.sample.AbstractCustomerCreditIncreaseTests#getExpectedMatches() - */ - protected int getExpectedMatches() { - // One record was skipped, so it won't be processed in the final state. - return super.getExpectedMatches() - 1; - } -} +package org.springframework.batch.sample; + +import java.math.BigDecimal; +import java.util.List; + +import org.springframework.batch.core.domain.JobParameters; +import org.springframework.batch.core.domain.JobParametersBuilder; +import org.springframework.batch.sample.dao.HibernateCreditDao; +import org.springframework.jdbc.UncategorizedSQLException; +import org.springframework.orm.hibernate3.HibernateJdbcException; + +/** + * Test for HibernateJob - checks that customer credit has been updated to + * expected value. + * + * @author Dave Syer + */ +public class HibernateFailureJobFunctionalTests extends + HibernateJobFunctionalTests { + + private HibernateCreditDao writer; + + /** + * Public setter for the {@link HibernateCreditDao} property. + * + * @param writer + * the writer to set + */ + public void setWriter(HibernateCreditDao writer) { + this.writer = writer; + } + + /* + * (non-Javadoc) + * + * @see org.springframework.test.AbstractSingleSpringContextTests#onTearDown() + */ + protected void onTearDown() throws Exception { + super.onTearDown(); + writer.setFailOnFlush(-1); + } + + /* + * (non-Javadoc) + * + * @see org.springframework.batch.sample.AbstractValidatingBatchLauncherTests#testLaunchJob() + */ + public void testLaunchJob() throws Exception { + JobParameters params = new JobParametersBuilder().addString("key", "failureJob").toJobParameters(); + setJobParameters(params); + writer.setFailOnFlush(2); + + int before = jdbcTemplate.queryForInt("SELECT COUNT(*) from CUSTOMER"); + assertTrue(before > 0); + try { + super.testLaunchJob(); + } catch (HibernateJdbcException e) { + // This is what would happen if the flush happened outside the + // RepeatContext: + throw e; + } catch (UncategorizedSQLException e) { + // This is what would happen if the job wasn't configured to skip + // exceptions at the step level. + // assertEquals(1, writer.getErrors().size()); + throw e; + } + int after = jdbcTemplate.queryForInt("SELECT COUNT(*) from CUSTOMER"); + assertEquals(before, after); + } + + /* + * (non-Javadoc) + * + * @see org.springframework.batch.sample.AbstractCustomerCreditIncreaseTests#checkMatches(java.util.List) + */ + protected void checkMatches(List matches) { + assertFalse(matches.contains(new BigDecimal(2))); + } + + /* + * (non-Javadoc) + * + * @see org.springframework.batch.sample.AbstractCustomerCreditIncreaseTests#getExpectedMatches() + */ + protected int getExpectedMatches() { + // One record was skipped, so it won't be processed in the final state. + return super.getExpectedMatches() - 1; + } +} diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/HibernateJobFunctionalTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/HibernateJobFunctionalTests.java index 517dfd5170..e40c0a16a7 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/HibernateJobFunctionalTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/HibernateJobFunctionalTests.java @@ -1,10 +1,10 @@ -package org.springframework.batch.sample; - -/** - * Test for HibernateJob - checks that customer credit has been updated to expected value. - * - * @author Robert Kasanicky - */ -public class HibernateJobFunctionalTests extends AbstractCustomerCreditIncreaseTests { - -} +package org.springframework.batch.sample; + +/** + * Test for HibernateJob - checks that customer credit has been updated to expected value. + * + * @author Robert Kasanicky + */ +public class HibernateJobFunctionalTests extends AbstractCustomerCreditIncreaseTests { + +} diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/IbatisJobFunctionalTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/IbatisJobFunctionalTests.java index 6c58318268..48dffb61fb 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/IbatisJobFunctionalTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/IbatisJobFunctionalTests.java @@ -1,11 +1,11 @@ -package org.springframework.batch.sample; - - -/** - * Test for IbatisJob - checks that customer credit has been updated to expected value. - * - * @author Robert Kasanicky - */ -public class IbatisJobFunctionalTests extends AbstractCustomerCreditIncreaseTests{ - -} +package org.springframework.batch.sample; + + +/** + * Test for IbatisJob - checks that customer credit has been updated to expected value. + * + * @author Robert Kasanicky + */ +public class IbatisJobFunctionalTests extends AbstractCustomerCreditIncreaseTests{ + +} diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/JobLoader.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/JobLoader.java index 4e9d0c84f8..4321530bc5 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/JobLoader.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/JobLoader.java @@ -1,37 +1,37 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.sample; - -import java.util.Map; - - -/** - * @author Dave Syer - * - */ -public interface JobLoader { - - void loadResource(String path); - - Map getConfigurations(); - - Object getJobConfiguration(String path); - - Object getProperty(String path); - - void setProperty(String path, String value); - -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.sample; + +import java.util.Map; + + +/** + * @author Dave Syer + * + */ +public interface JobLoader { + + void loadResource(String path); + + Map getConfigurations(); + + Object getJobConfiguration(String path); + + Object getProperty(String path); + + void setProperty(String path, String value); + +} diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/MultilineJobFunctionalTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/MultilineJobFunctionalTests.java index f7f24846b3..5a69cce727 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/MultilineJobFunctionalTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/MultilineJobFunctionalTests.java @@ -1,37 +1,37 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.batch.sample; - -import org.apache.commons.io.IOUtils; -import org.springframework.core.io.FileSystemResource; -import org.springframework.core.io.Resource; -import org.springframework.util.StringUtils; - -public class MultilineJobFunctionalTests extends AbstractValidatingBatchLauncherTests { - - // The output is grouped together in two lines, instead of all the - // trades coming out on a single line. - private static final String EXPECTED_RESULT = "[Trade: [isin=UK21341EAH45,quantity=978,price=98.34,customer=customer1], Trade: [isin=UK21341EAH46,quantity=112,price=18.12,customer=customer2]]" - + "[Trade: [isin=UK21341EAH47,quantity=245,price=12.78,customer=customer2], Trade: [isin=UK21341EAH48,quantity=108,price=9.25,customer=customer3], Trade: [isin=UK21341EAH49,quantity=854,price=23.39,customer=customer4]]"; - - private Resource output = new FileSystemResource("target/test-outputs/20070122.testStream.multilineStep.txt"); - - protected void validatePostConditions() throws Exception { - assertEquals(EXPECTED_RESULT, StringUtils.replace(IOUtils.toString(output.getInputStream()), System - .getProperty("line.separator"), "")); - } -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.batch.sample; + +import org.apache.commons.io.IOUtils; +import org.springframework.core.io.FileSystemResource; +import org.springframework.core.io.Resource; +import org.springframework.util.StringUtils; + +public class MultilineJobFunctionalTests extends AbstractValidatingBatchLauncherTests { + + // The output is grouped together in two lines, instead of all the + // trades coming out on a single line. + private static final String EXPECTED_RESULT = "[Trade: [isin=UK21341EAH45,quantity=978,price=98.34,customer=customer1], Trade: [isin=UK21341EAH46,quantity=112,price=18.12,customer=customer2]]" + + "[Trade: [isin=UK21341EAH47,quantity=245,price=12.78,customer=customer2], Trade: [isin=UK21341EAH48,quantity=108,price=9.25,customer=customer3], Trade: [isin=UK21341EAH49,quantity=854,price=23.39,customer=customer4]]"; + + private Resource output = new FileSystemResource("target/test-outputs/20070122.testStream.multilineStep.txt"); + + protected void validatePostConditions() throws Exception { + assertEquals(EXPECTED_RESULT, StringUtils.replace(IOUtils.toString(output.getInputStream()), System + .getProperty("line.separator"), "")); + } +} diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/ParallelJobFunctionalTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/ParallelJobFunctionalTests.java index 68e4b7509c..959519fd8e 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/ParallelJobFunctionalTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/ParallelJobFunctionalTests.java @@ -1,32 +1,32 @@ -package org.springframework.batch.sample; - -import javax.sql.DataSource; - -import org.springframework.batch.sample.item.writer.StagingItemWriter; -import org.springframework.jdbc.core.JdbcOperations; -import org.springframework.jdbc.core.JdbcTemplate; - -public class ParallelJobFunctionalTests extends - AbstractValidatingBatchLauncherTests { - - private JdbcOperations jdbcTemplate; - - public void setDataSource(DataSource dataSource) { - this.jdbcTemplate = new JdbcTemplate(dataSource); - } - - protected void validatePostConditions() throws Exception { - int count; - count = jdbcTemplate.queryForInt( - "SELECT COUNT(*) from BATCH_STAGING where PROCESSED=?", - new Object[] {StagingItemWriter.NEW}); - assertEquals(0, count); - int total = jdbcTemplate.queryForInt( - "SELECT COUNT(*) from BATCH_STAGING"); - count = jdbcTemplate.queryForInt( - "SELECT COUNT(*) from BATCH_STAGING where PROCESSED=?", - new Object[] {StagingItemWriter.DONE}); - assertEquals(total, count); - } - -} +package org.springframework.batch.sample; + +import javax.sql.DataSource; + +import org.springframework.batch.sample.item.writer.StagingItemWriter; +import org.springframework.jdbc.core.JdbcOperations; +import org.springframework.jdbc.core.JdbcTemplate; + +public class ParallelJobFunctionalTests extends + AbstractValidatingBatchLauncherTests { + + private JdbcOperations jdbcTemplate; + + public void setDataSource(DataSource dataSource) { + this.jdbcTemplate = new JdbcTemplate(dataSource); + } + + protected void validatePostConditions() throws Exception { + int count; + count = jdbcTemplate.queryForInt( + "SELECT COUNT(*) from BATCH_STAGING where PROCESSED=?", + new Object[] {StagingItemWriter.NEW}); + assertEquals(0, count); + int total = jdbcTemplate.queryForInt( + "SELECT COUNT(*) from BATCH_STAGING"); + count = jdbcTemplate.queryForInt( + "SELECT COUNT(*) from BATCH_STAGING where PROCESSED=?", + new Object[] {StagingItemWriter.DONE}); + assertEquals(total, count); + } + +} diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/RetrySampleFunctionalTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/RetrySampleFunctionalTests.java index 61c68b53f0..ae033677e2 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/RetrySampleFunctionalTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/RetrySampleFunctionalTests.java @@ -1,30 +1,30 @@ -package org.springframework.batch.sample; - -import org.springframework.batch.sample.item.reader.GeneratingItemReader; -import org.springframework.batch.sample.item.writer.RetrySampleItemWriter; - -/** - * Checks that expected number of items have been processed. - * - * @author Robert Kasanicky - */ -public class RetrySampleFunctionalTests extends AbstractValidatingBatchLauncherTests { - - private GeneratingItemReader itemGenerator; - - private RetrySampleItemWriter itemProcessor; - - protected void validatePostConditions() throws Exception { - //items processed = items read + 2 exceptions - assertEquals(itemGenerator.getLimit()+2, itemProcessor.getCounter()); - } - - public void setItemGenerator(GeneratingItemReader itemGenerator) { - this.itemGenerator = itemGenerator; - } - - public void setItemProcessor(RetrySampleItemWriter itemProcessor) { - this.itemProcessor = itemProcessor; - } - -} +package org.springframework.batch.sample; + +import org.springframework.batch.sample.item.reader.GeneratingItemReader; +import org.springframework.batch.sample.item.writer.RetrySampleItemWriter; + +/** + * Checks that expected number of items have been processed. + * + * @author Robert Kasanicky + */ +public class RetrySampleFunctionalTests extends AbstractValidatingBatchLauncherTests { + + private GeneratingItemReader itemGenerator; + + private RetrySampleItemWriter itemProcessor; + + protected void validatePostConditions() throws Exception { + //items processed = items read + 2 exceptions + assertEquals(itemGenerator.getLimit()+2, itemProcessor.getCounter()); + } + + public void setItemGenerator(GeneratingItemReader itemGenerator) { + this.itemGenerator = itemGenerator; + } + + public void setItemProcessor(RetrySampleItemWriter itemProcessor) { + this.itemProcessor = itemProcessor; + } + +} diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/RollbackJobFunctionalTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/RollbackJobFunctionalTests.java index 3b874c419e..0d696b7142 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/RollbackJobFunctionalTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/RollbackJobFunctionalTests.java @@ -1,32 +1,32 @@ -package org.springframework.batch.sample; - -import javax.sql.DataSource; - -import org.springframework.jdbc.core.JdbcTemplate; - -/** - * Test for job that rolls back a trade that is processed. - * - * @author Robert Kasanicky - */ -public class RollbackJobFunctionalTests extends AbstractValidatingBatchLauncherTests { - - int before = -1; - - JdbcTemplate jdbcTemplate; - - public void setDataSource(DataSource dataSource) { - jdbcTemplate = new JdbcTemplate(dataSource); - } - - protected void onSetUp() throws Exception { - before = jdbcTemplate.queryForInt("SELECT COUNT(*) from TRADE"); - } - - protected void validatePostConditions() throws Exception { - int after = jdbcTemplate.queryForInt("SELECT COUNT(*) from TRADE"); - assertEquals(before+5, after); - } - - -} +package org.springframework.batch.sample; + +import javax.sql.DataSource; + +import org.springframework.jdbc.core.JdbcTemplate; + +/** + * Test for job that rolls back a trade that is processed. + * + * @author Robert Kasanicky + */ +public class RollbackJobFunctionalTests extends AbstractValidatingBatchLauncherTests { + + int before = -1; + + JdbcTemplate jdbcTemplate; + + public void setDataSource(DataSource dataSource) { + jdbcTemplate = new JdbcTemplate(dataSource); + } + + protected void onSetUp() throws Exception { + before = jdbcTemplate.queryForInt("SELECT COUNT(*) from TRADE"); + } + + protected void validatePostConditions() throws Exception { + int after = jdbcTemplate.queryForInt("SELECT COUNT(*) from TRADE"); + assertEquals(before+5, after); + } + + +} diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/TradeJobFunctionalTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/TradeJobFunctionalTests.java index fe18c8aa39..003558a169 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/TradeJobFunctionalTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/TradeJobFunctionalTests.java @@ -1,201 +1,201 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.batch.sample; - -import java.math.BigDecimal; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -import org.springframework.batch.sample.domain.Trade; -import org.springframework.core.io.FileSystemResource; -import org.springframework.core.io.Resource; -import org.springframework.jdbc.core.JdbcOperations; -import org.springframework.jdbc.core.RowCallbackHandler; - - - -public class TradeJobFunctionalTests extends AbstractValidatingBatchLauncherTests { - - private static final String GET_TRADES = "SELECT isin, quantity, price, customer FROM trade"; - private static final String GET_CUSTOMERS = "SELECT name, credit FROM customer"; - - private List customers; - private List trades; - private int activeRow = 0; - - private JdbcOperations jdbcTemplate; - private Map credits = new HashMap(); - - /** - * @param jdbcTemplate the jdbcTemplate to set - */ - public void setJdbcTemplate(JdbcOperations jdbcTemplate) { - this.jdbcTemplate = jdbcTemplate; - } - - /* (non-Javadoc) - * @see org.springframework.test.AbstractSingleSpringContextTests#onSetUp() - */ - protected void onSetUp() throws Exception { - super.onSetUp(); - jdbcTemplate.update("delete from TRADE"); - List list = jdbcTemplate.queryForList("select name, CREDIT from customer"); - for (Iterator iterator = list.iterator(); iterator.hasNext();) { - Map map = (Map) iterator.next(); - credits.put(map.get("NAME"), map.get("CREDIT")); - } - } - - public void testLaunchJob() throws Exception{ - super.testLaunchJob(); - } - - protected void validatePostConditions() { - - // assertTrue(((Resource)applicationContext.getBean("customerFileLocator")).exists()); - - customers = new ArrayList() {{add(new Customer("customer1", (((Double)credits.get("customer1")).doubleValue() - 98.34))); - add(new Customer("customer2", (((Double)credits.get("customer2")).doubleValue() - 18.12 - 12.78))); - add(new Customer("customer3", (((Double)credits.get("customer3")).doubleValue() - 109.25))); - add(new Customer("customer4", (((Double)credits.get("customer4")).doubleValue() - 123.39)));}}; - - trades = new ArrayList() {{add(new Trade("UK21341EAH45", 978, new BigDecimal("98.34"), "customer1")); - add(new Trade("UK21341EAH46", 112, new BigDecimal("18.12"), "customer2")); - add(new Trade("UK21341EAH47", 245, new BigDecimal("12.78"), "customer2")); - add(new Trade("UK21341EAH48", 108, new BigDecimal("109.25"), "customer3")); - add(new Trade("UK21341EAH49", 854, new BigDecimal("123.39"), "customer4"));}}; - - // check content of the trade table - jdbcTemplate.query(GET_TRADES, new RowCallbackHandler() { - - public void processRow(ResultSet rs) throws SQLException { - Trade trade = (Trade)trades.get(activeRow++); - - assertTrue(trade.getIsin().equals(rs.getString(1))); - assertTrue(trade.getQuantity() == rs.getLong(2)); - assertTrue(trade.getPrice().equals(rs.getBigDecimal(3))); - assertTrue(trade.getCustomer().equals(rs.getString(4))); - } - }); - - assertTrue(trades.size() == activeRow); - - // check content of the customer table - activeRow = 0; - jdbcTemplate.query(GET_CUSTOMERS, new RowCallbackHandler() { - - public void processRow(ResultSet rs) throws SQLException { - Customer customer = (Customer)customers.get(activeRow++); - - assertEquals(customer.getName(),rs.getString(1)); - assertEquals(customer.getCredit(), rs.getDouble(2), .01); - } - }); - - assertEquals(customers.size(), activeRow); - - // check content of the output file - -// Clean up - ((FileSystemResource)applicationContext.getBean("customerFileLocator")).getFile().delete(); - } - - protected void validatePreConditions() { - assertTrue(((Resource)applicationContext.getBean("fileLocator")).exists()); - } - - private static class Customer { - private String name; - private double credit; - - public Customer(String name, double credit) { - this.name = name; - this.credit = credit; - } - - public Customer(){ - } - - /** - * @return the credit - */ - public double getCredit() { - return credit; - } - /** - * @param credit the credit to set - */ - public void setCredit(double credit) { - this.credit = credit; - } - /** - * @return the name - */ - public String getName() { - return name; - } - /** - * @param name the name to set - */ - public void setName(String name) { - this.name = name; - } - - /* (non-Javadoc) - * @see java.lang.Object#hashCode() - */ - public int hashCode() { - final int PRIME = 31; - int result = 1; - long temp; - temp = Double.doubleToLongBits(credit); - result = PRIME * result + (int) (temp ^ (temp >>> 32)); - result = PRIME * result + ((name == null) ? 0 : name.hashCode()); - return result; - } - - /* (non-Javadoc) - * @see java.lang.Object#equals(java.lang.Object) - */ - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - final Customer other = (Customer) obj; - if (Double.doubleToLongBits(credit) != Double.doubleToLongBits(other.credit)) - return false; - if (name == null) { - if (other.name != null) - return false; - } else if (!name.equals(other.name)) - return false; - return true; - } - - - } - - -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.batch.sample; + +import java.math.BigDecimal; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.springframework.batch.sample.domain.Trade; +import org.springframework.core.io.FileSystemResource; +import org.springframework.core.io.Resource; +import org.springframework.jdbc.core.JdbcOperations; +import org.springframework.jdbc.core.RowCallbackHandler; + + + +public class TradeJobFunctionalTests extends AbstractValidatingBatchLauncherTests { + + private static final String GET_TRADES = "SELECT isin, quantity, price, customer FROM trade"; + private static final String GET_CUSTOMERS = "SELECT name, credit FROM customer"; + + private List customers; + private List trades; + private int activeRow = 0; + + private JdbcOperations jdbcTemplate; + private Map credits = new HashMap(); + + /** + * @param jdbcTemplate the jdbcTemplate to set + */ + public void setJdbcTemplate(JdbcOperations jdbcTemplate) { + this.jdbcTemplate = jdbcTemplate; + } + + /* (non-Javadoc) + * @see org.springframework.test.AbstractSingleSpringContextTests#onSetUp() + */ + protected void onSetUp() throws Exception { + super.onSetUp(); + jdbcTemplate.update("delete from TRADE"); + List list = jdbcTemplate.queryForList("select name, CREDIT from customer"); + for (Iterator iterator = list.iterator(); iterator.hasNext();) { + Map map = (Map) iterator.next(); + credits.put(map.get("NAME"), map.get("CREDIT")); + } + } + + public void testLaunchJob() throws Exception{ + super.testLaunchJob(); + } + + protected void validatePostConditions() { + + // assertTrue(((Resource)applicationContext.getBean("customerFileLocator")).exists()); + + customers = new ArrayList() {{add(new Customer("customer1", (((Double)credits.get("customer1")).doubleValue() - 98.34))); + add(new Customer("customer2", (((Double)credits.get("customer2")).doubleValue() - 18.12 - 12.78))); + add(new Customer("customer3", (((Double)credits.get("customer3")).doubleValue() - 109.25))); + add(new Customer("customer4", (((Double)credits.get("customer4")).doubleValue() - 123.39)));}}; + + trades = new ArrayList() {{add(new Trade("UK21341EAH45", 978, new BigDecimal("98.34"), "customer1")); + add(new Trade("UK21341EAH46", 112, new BigDecimal("18.12"), "customer2")); + add(new Trade("UK21341EAH47", 245, new BigDecimal("12.78"), "customer2")); + add(new Trade("UK21341EAH48", 108, new BigDecimal("109.25"), "customer3")); + add(new Trade("UK21341EAH49", 854, new BigDecimal("123.39"), "customer4"));}}; + + // check content of the trade table + jdbcTemplate.query(GET_TRADES, new RowCallbackHandler() { + + public void processRow(ResultSet rs) throws SQLException { + Trade trade = (Trade)trades.get(activeRow++); + + assertTrue(trade.getIsin().equals(rs.getString(1))); + assertTrue(trade.getQuantity() == rs.getLong(2)); + assertTrue(trade.getPrice().equals(rs.getBigDecimal(3))); + assertTrue(trade.getCustomer().equals(rs.getString(4))); + } + }); + + assertTrue(trades.size() == activeRow); + + // check content of the customer table + activeRow = 0; + jdbcTemplate.query(GET_CUSTOMERS, new RowCallbackHandler() { + + public void processRow(ResultSet rs) throws SQLException { + Customer customer = (Customer)customers.get(activeRow++); + + assertEquals(customer.getName(),rs.getString(1)); + assertEquals(customer.getCredit(), rs.getDouble(2), .01); + } + }); + + assertEquals(customers.size(), activeRow); + + // check content of the output file + +// Clean up + ((FileSystemResource)applicationContext.getBean("customerFileLocator")).getFile().delete(); + } + + protected void validatePreConditions() { + assertTrue(((Resource)applicationContext.getBean("fileLocator")).exists()); + } + + private static class Customer { + private String name; + private double credit; + + public Customer(String name, double credit) { + this.name = name; + this.credit = credit; + } + + public Customer(){ + } + + /** + * @return the credit + */ + public double getCredit() { + return credit; + } + /** + * @param credit the credit to set + */ + public void setCredit(double credit) { + this.credit = credit; + } + /** + * @return the name + */ + public String getName() { + return name; + } + /** + * @param name the name to set + */ + public void setName(String name) { + this.name = name; + } + + /* (non-Javadoc) + * @see java.lang.Object#hashCode() + */ + public int hashCode() { + final int PRIME = 31; + int result = 1; + long temp; + temp = Double.doubleToLongBits(credit); + result = PRIME * result + (int) (temp ^ (temp >>> 32)); + result = PRIME * result + ((name == null) ? 0 : name.hashCode()); + return result; + } + + /* (non-Javadoc) + * @see java.lang.Object#equals(java.lang.Object) + */ + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + final Customer other = (Customer) obj; + if (Double.doubleToLongBits(credit) != Double.doubleToLongBits(other.credit)) + return false; + if (name == null) { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; + return true; + } + + + } + + +} diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/XmlStaxJobFunctionalTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/XmlStaxJobFunctionalTests.java index 71869d4f79..0b38435e81 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/XmlStaxJobFunctionalTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/XmlStaxJobFunctionalTests.java @@ -1,38 +1,38 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.batch.sample; - -import java.io.FileReader; - -import org.custommonkey.xmlunit.XMLAssert; -import org.custommonkey.xmlunit.XMLUnit; - - -public class XmlStaxJobFunctionalTests extends AbstractValidatingBatchLauncherTests { - - private static final String OUTPUT_FILE = "target/test-outputs/20070918.testStream.xmlFileStep.output.xml"; - private static final String EXPECTED_OUTPUT_FILE = "src/main/resources/data/staxJob/output/expected-output.xml"; - - /** - * Output should be the same as input - */ - protected void validatePostConditions() throws Exception { - XMLUnit.setIgnoreWhitespace(true); - XMLAssert.assertXMLEqual(new FileReader(EXPECTED_OUTPUT_FILE), new FileReader(OUTPUT_FILE)); - } - -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.batch.sample; + +import java.io.FileReader; + +import org.custommonkey.xmlunit.XMLAssert; +import org.custommonkey.xmlunit.XMLUnit; + + +public class XmlStaxJobFunctionalTests extends AbstractValidatingBatchLauncherTests { + + private static final String OUTPUT_FILE = "target/test-outputs/20070918.testStream.xmlFileStep.output.xml"; + private static final String EXPECTED_OUTPUT_FILE = "src/main/resources/data/staxJob/output/expected-output.xml"; + + /** + * Output should be the same as input + */ + protected void validatePostConditions() throws Exception { + XMLUnit.setIgnoreWhitespace(true); + XMLAssert.assertXMLEqual(new FileReader(EXPECTED_OUTPUT_FILE), new FileReader(OUTPUT_FILE)); + } + +} diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/advice/JobExecutionNotificationPublisherTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/advice/JobExecutionNotificationPublisherTests.java index 6b37b91d59..6c5eec5448 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/advice/JobExecutionNotificationPublisherTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/advice/JobExecutionNotificationPublisherTests.java @@ -1,49 +1,49 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.sample.advice; - -import java.util.ArrayList; -import java.util.List; - -import javax.management.Notification; - -import junit.framework.TestCase; - -import org.springframework.jmx.export.notification.NotificationPublisher; -import org.springframework.jmx.export.notification.UnableToSendNotificationException; - -/** - * @author Dave Syer - * - */ -public class JobExecutionNotificationPublisherTests extends TestCase { - - JobExecutionNotificationPublisher publisher = new JobExecutionNotificationPublisher(); - - public void testRepeatOperationsOpenUsed() throws Exception { - final List list = new ArrayList(); - publisher.setNotificationPublisher(new NotificationPublisher() { - public void sendNotification(Notification notification) throws UnableToSendNotificationException { - list.add(notification); - } - }); - publisher.onApplicationEvent(new SimpleMessageApplicationEvent(this, "foo")); - assertEquals(1, list.size()); - String message = ((Notification) list.get(0)).getMessage(); - assertTrue("Message does not contain 'foo': ", message.indexOf("foo") > 0); - } - -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.sample.advice; + +import java.util.ArrayList; +import java.util.List; + +import javax.management.Notification; + +import junit.framework.TestCase; + +import org.springframework.jmx.export.notification.NotificationPublisher; +import org.springframework.jmx.export.notification.UnableToSendNotificationException; + +/** + * @author Dave Syer + * + */ +public class JobExecutionNotificationPublisherTests extends TestCase { + + JobExecutionNotificationPublisher publisher = new JobExecutionNotificationPublisher(); + + public void testRepeatOperationsOpenUsed() throws Exception { + final List list = new ArrayList(); + publisher.setNotificationPublisher(new NotificationPublisher() { + public void sendNotification(Notification notification) throws UnableToSendNotificationException { + list.add(notification); + } + }); + publisher.onApplicationEvent(new SimpleMessageApplicationEvent(this, "foo")); + assertEquals(1, list.size()); + String message = ((Notification) list.get(0)).getMessage(); + assertTrue("Message does not contain 'foo': ", message.indexOf("foo") > 0); + } + +} diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/dao/FlatFileCustomerCreditDaoTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/dao/FlatFileCustomerCreditDaoTests.java index 8f30de6773..6dcf52d2d7 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/dao/FlatFileCustomerCreditDaoTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/dao/FlatFileCustomerCreditDaoTests.java @@ -1,82 +1,82 @@ -package org.springframework.batch.sample.dao; - -import java.math.BigDecimal; - -import junit.framework.TestCase; - -import org.easymock.MockControl; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.item.ItemStream; -import org.springframework.batch.item.ItemWriter; -import org.springframework.batch.sample.domain.CustomerCredit; - -public class FlatFileCustomerCreditDaoTests extends TestCase { - - private MockControl outputControl; - private ResourceLifecycleItemWriter output; - private FlatFileCustomerCreditDao writer; - - public void setUp() throws Exception { - super.setUp(); - - //create mock for OutputSource - outputControl = MockControl.createControl(ResourceLifecycleItemWriter.class); - output = (ResourceLifecycleItemWriter)outputControl.getMock(); - - //create new writer - writer = new FlatFileCustomerCreditDao(); - writer.setOutputSource(output); - } - - public void testOpen() throws Exception { - ExecutionContext executionContext = new ExecutionContext(); - //set-up outputSource mock - output.open(executionContext); - outputControl.replay(); - - //call tested method - writer.open(executionContext); - - //verify method calls - outputControl.verify(); - } - - public void testClose() throws Exception{ - - //set-up outputSource mock - output.close(null); - outputControl.replay(); - - //call tested method - writer.close(); - - //verify method calls - outputControl.verify(); - } - - public void testWrite() throws Exception { - - //Create and set-up CustomerCredit - CustomerCredit credit = new CustomerCredit(); - credit.setCredit(new BigDecimal(1)); - credit.setName("testName"); - - //set separator - writer.setSeparator(";"); - - //set-up OutputSource mock - output.write("testName;1"); - output.open(new ExecutionContext()); - outputControl.replay(); - - //call tested method - writer.writeCredit(credit); - - //verify method calls - outputControl.verify(); - } - - private interface ResourceLifecycleItemWriter extends ItemWriter, ItemStream{ - - } -} +package org.springframework.batch.sample.dao; + +import java.math.BigDecimal; + +import junit.framework.TestCase; + +import org.easymock.MockControl; +import org.springframework.batch.item.ExecutionContext; +import org.springframework.batch.item.ItemStream; +import org.springframework.batch.item.ItemWriter; +import org.springframework.batch.sample.domain.CustomerCredit; + +public class FlatFileCustomerCreditDaoTests extends TestCase { + + private MockControl outputControl; + private ResourceLifecycleItemWriter output; + private FlatFileCustomerCreditDao writer; + + public void setUp() throws Exception { + super.setUp(); + + //create mock for OutputSource + outputControl = MockControl.createControl(ResourceLifecycleItemWriter.class); + output = (ResourceLifecycleItemWriter)outputControl.getMock(); + + //create new writer + writer = new FlatFileCustomerCreditDao(); + writer.setOutputSource(output); + } + + public void testOpen() throws Exception { + ExecutionContext executionContext = new ExecutionContext(); + //set-up outputSource mock + output.open(executionContext); + outputControl.replay(); + + //call tested method + writer.open(executionContext); + + //verify method calls + outputControl.verify(); + } + + public void testClose() throws Exception{ + + //set-up outputSource mock + output.close(null); + outputControl.replay(); + + //call tested method + writer.close(); + + //verify method calls + outputControl.verify(); + } + + public void testWrite() throws Exception { + + //Create and set-up CustomerCredit + CustomerCredit credit = new CustomerCredit(); + credit.setCredit(new BigDecimal(1)); + credit.setName("testName"); + + //set separator + writer.setSeparator(";"); + + //set-up OutputSource mock + output.write("testName;1"); + output.open(new ExecutionContext()); + outputControl.replay(); + + //call tested method + writer.writeCredit(credit); + + //verify method calls + outputControl.verify(); + } + + private interface ResourceLifecycleItemWriter extends ItemWriter, ItemStream{ + + } +} diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/dao/FlatFileOrderWriterTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/dao/FlatFileOrderWriterTests.java index c78f3cb25d..dd6bc38e94 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/dao/FlatFileOrderWriterTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/dao/FlatFileOrderWriterTests.java @@ -1,84 +1,84 @@ -package org.springframework.batch.sample.dao; - -import java.math.BigDecimal; -import java.util.ArrayList; -import java.util.GregorianCalendar; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import junit.framework.TestCase; - -import org.springframework.batch.io.file.transform.LineAggregator; -import org.springframework.batch.item.ItemWriter; -import org.springframework.batch.item.writer.AbstractItemWriter; -import org.springframework.batch.sample.StubLineAggregator; -import org.springframework.batch.sample.domain.Address; -import org.springframework.batch.sample.domain.BillingInfo; -import org.springframework.batch.sample.domain.Customer; -import org.springframework.batch.sample.domain.LineItem; -import org.springframework.batch.sample.domain.Order; - -public class FlatFileOrderWriterTests extends TestCase { - - List list = new ArrayList(); - - private ItemWriter output = new AbstractItemWriter() { - public void write(Object output) { - list.add(output); - } - }; - - private FlatFileOrderWriter writer; - - public void setUp() throws Exception { - super.setUp(); - //create new writer - writer = new FlatFileOrderWriter(); - writer.setDelegate(output); - } - - public void testWrite() throws Exception { - - //Create and set-up Order - Order order = new Order(); - - order.setOrderDate(new GregorianCalendar(2007, GregorianCalendar.JUNE, 1).getTime()); - order.setCustomer(new Customer()); - order.setBilling(new BillingInfo()); - order.setBillingAddress(new Address()); - List lineItems = new ArrayList(); - LineItem item = new LineItem(); - item.setPrice(BigDecimal.valueOf(0)); - lineItems.add(item); - lineItems.add(item); - order.setLineItems(lineItems); - order.setTotalPrice(BigDecimal.valueOf(0)); - - //create aggregator stub - LineAggregator aggregator = new StubLineAggregator(); - - //create map of aggregators and set it to writer - Map aggregators = new HashMap(); - - OrderTransformer converter = new OrderTransformer(); - aggregators.put("header", aggregator); - aggregators.put("customer", aggregator); - aggregators.put("address", aggregator); - aggregators.put("billing", aggregator); - aggregators.put("item", aggregator); - aggregators.put("footer", aggregator); - converter.setAggregators(aggregators); - writer.setTransformer(converter); - - //call tested method - writer.write(order); - - //verify method calls - assertEquals(1, list.size()); - assertTrue(list.get(0) instanceof List); - assertEquals("02007/06/01", ((List) list.get(0)).get(0)); - - } - -} +package org.springframework.batch.sample.dao; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.GregorianCalendar; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import junit.framework.TestCase; + +import org.springframework.batch.io.file.transform.LineAggregator; +import org.springframework.batch.item.ItemWriter; +import org.springframework.batch.item.writer.AbstractItemWriter; +import org.springframework.batch.sample.StubLineAggregator; +import org.springframework.batch.sample.domain.Address; +import org.springframework.batch.sample.domain.BillingInfo; +import org.springframework.batch.sample.domain.Customer; +import org.springframework.batch.sample.domain.LineItem; +import org.springframework.batch.sample.domain.Order; + +public class FlatFileOrderWriterTests extends TestCase { + + List list = new ArrayList(); + + private ItemWriter output = new AbstractItemWriter() { + public void write(Object output) { + list.add(output); + } + }; + + private FlatFileOrderWriter writer; + + public void setUp() throws Exception { + super.setUp(); + //create new writer + writer = new FlatFileOrderWriter(); + writer.setDelegate(output); + } + + public void testWrite() throws Exception { + + //Create and set-up Order + Order order = new Order(); + + order.setOrderDate(new GregorianCalendar(2007, GregorianCalendar.JUNE, 1).getTime()); + order.setCustomer(new Customer()); + order.setBilling(new BillingInfo()); + order.setBillingAddress(new Address()); + List lineItems = new ArrayList(); + LineItem item = new LineItem(); + item.setPrice(BigDecimal.valueOf(0)); + lineItems.add(item); + lineItems.add(item); + order.setLineItems(lineItems); + order.setTotalPrice(BigDecimal.valueOf(0)); + + //create aggregator stub + LineAggregator aggregator = new StubLineAggregator(); + + //create map of aggregators and set it to writer + Map aggregators = new HashMap(); + + OrderTransformer converter = new OrderTransformer(); + aggregators.put("header", aggregator); + aggregators.put("customer", aggregator); + aggregators.put("address", aggregator); + aggregators.put("billing", aggregator); + aggregators.put("item", aggregator); + aggregators.put("footer", aggregator); + converter.setAggregators(aggregators); + writer.setTransformer(converter); + + //call tested method + writer.write(order); + + //verify method calls + assertEquals(1, list.size()); + assertTrue(list.get(0) instanceof List); + assertEquals("02007/06/01", ((List) list.get(0)).get(0)); + + } + +} diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/dao/JdbcCustomerDebitDaoTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/dao/JdbcCustomerDebitDaoTests.java index 2a8a78a39b..16a2900b53 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/dao/JdbcCustomerDebitDaoTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/dao/JdbcCustomerDebitDaoTests.java @@ -1,42 +1,42 @@ -package org.springframework.batch.sample.dao; - -import java.math.BigDecimal; -import java.sql.ResultSet; -import java.sql.SQLException; - -import org.springframework.batch.sample.domain.CustomerDebit; -import org.springframework.jdbc.core.RowCallbackHandler; -import org.springframework.test.AbstractTransactionalDataSourceSpringContextTests; - -public class JdbcCustomerDebitDaoTests extends AbstractTransactionalDataSourceSpringContextTests { - - protected String[] getConfigLocations() { - return new String[] { "data-source-context.xml" }; - } - - public void testWrite() { - - //insert customer credit - jdbcTemplate.execute("INSERT INTO customer VALUES (99, 0, 'testName', 100)"); - - //create writer and set jdbcTemplate - JdbcCustomerDebitDao writer = new JdbcCustomerDebitDao(); - writer.setJdbcTemplate(jdbcTemplate); - - //create customer debit - CustomerDebit customerDebit = new CustomerDebit(); - customerDebit.setName("testName"); - customerDebit.setDebit(BigDecimal.valueOf(5)); - - //call writer - writer.write(customerDebit); - - //verify customer credit - jdbcTemplate.query("SELECT name, credit FROM customer WHERE name = 'testName'", new RowCallbackHandler() { - public void processRow(ResultSet rs) throws SQLException { - assertEquals(95, rs.getLong("credit")); - } - }); - - } -} +package org.springframework.batch.sample.dao; + +import java.math.BigDecimal; +import java.sql.ResultSet; +import java.sql.SQLException; + +import org.springframework.batch.sample.domain.CustomerDebit; +import org.springframework.jdbc.core.RowCallbackHandler; +import org.springframework.test.AbstractTransactionalDataSourceSpringContextTests; + +public class JdbcCustomerDebitDaoTests extends AbstractTransactionalDataSourceSpringContextTests { + + protected String[] getConfigLocations() { + return new String[] { "data-source-context.xml" }; + } + + public void testWrite() { + + //insert customer credit + jdbcTemplate.execute("INSERT INTO customer VALUES (99, 0, 'testName', 100)"); + + //create writer and set jdbcTemplate + JdbcCustomerDebitDao writer = new JdbcCustomerDebitDao(); + writer.setJdbcTemplate(jdbcTemplate); + + //create customer debit + CustomerDebit customerDebit = new CustomerDebit(); + customerDebit.setName("testName"); + customerDebit.setDebit(BigDecimal.valueOf(5)); + + //call writer + writer.write(customerDebit); + + //verify customer credit + jdbcTemplate.query("SELECT name, credit FROM customer WHERE name = 'testName'", new RowCallbackHandler() { + public void processRow(ResultSet rs) throws SQLException { + assertEquals(95, rs.getLong("credit")); + } + }); + + } +} diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/dao/JdbcGameDaoIntegrationTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/dao/JdbcGameDaoIntegrationTests.java index b75e2a6abb..30724c0382 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/dao/JdbcGameDaoIntegrationTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/dao/JdbcGameDaoIntegrationTests.java @@ -1,99 +1,99 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.sample.dao; - -import java.sql.ResultSet; -import java.sql.SQLException; - -import org.springframework.batch.sample.domain.Game; -import org.springframework.jdbc.core.RowMapper; -import org.springframework.test.AbstractTransactionalDataSourceSpringContextTests; - -/** - * @author Lucas Ward - * - */ -public class JdbcGameDaoIntegrationTests extends AbstractTransactionalDataSourceSpringContextTests { - - private JdbcGameDao gameDao; - - private Game game = new Game(); - - protected String[] getConfigLocations() { - return new String[] { "data-source-context.xml" }; - } - - protected void onSetUpBeforeTransaction() throws Exception { - super.onSetUpBeforeTransaction(); - - gameDao = new JdbcGameDao(); - gameDao.setJdbcTemplate(getJdbcTemplate()); - - game.setId("XXXXX00"); - game.setYear(1996); - game.setTeam("mia"); - game.setWeek(10); - game.setOpponent("nwe"); - game.setAttempts(0); - game.setCompletes(0); - game.setPassingYards(0); - game.setPassingTd(0); - game.setInterceptions(0); - game.setRushes(29); - game.setRushYards(109); - game.setReceptions(1); - game.setReceptionYards(16); - game.setTotalTd(2); - } - - public void testWrite() { - - gameDao.write(game); - - Game tempGame = (Game) getJdbcTemplate().queryForObject("SELECT * FROM GAMES where PLAYER_ID=? AND YEAR_NO=?", - new Object[] { game.getId(), new Integer(game.getYear()) }, new GameRowMapper()); - assertEquals(tempGame, game); - } - - public static class GameRowMapper implements RowMapper { - - public Object mapRow(ResultSet rs, int arg1) throws SQLException { - - if (rs == null) { - return null; - } - - Game game = new Game(); - game.setId(rs.getString("PLAYER_ID").trim()); - game.setYear(rs.getInt("year_no")); - game.setTeam(rs.getString("team")); - game.setWeek(rs.getInt("week")); - game.setOpponent(rs.getString("opponent")); - game.setCompletes(rs.getInt("completes")); - game.setAttempts(rs.getInt("attempts")); - game.setPassingYards(rs.getInt("passing_Yards")); - game.setPassingTd(rs.getInt("passing_Td")); - game.setInterceptions(rs.getInt("interceptions")); - game.setRushes(rs.getInt("rushes")); - game.setRushYards(rs.getInt("rush_Yards")); - game.setReceptions(rs.getInt("receptions")); - game.setReceptionYards(rs.getInt("receptions_Yards")); - game.setTotalTd(rs.getInt("total_Td")); - - return game; - } - } -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.sample.dao; + +import java.sql.ResultSet; +import java.sql.SQLException; + +import org.springframework.batch.sample.domain.Game; +import org.springframework.jdbc.core.RowMapper; +import org.springframework.test.AbstractTransactionalDataSourceSpringContextTests; + +/** + * @author Lucas Ward + * + */ +public class JdbcGameDaoIntegrationTests extends AbstractTransactionalDataSourceSpringContextTests { + + private JdbcGameDao gameDao; + + private Game game = new Game(); + + protected String[] getConfigLocations() { + return new String[] { "data-source-context.xml" }; + } + + protected void onSetUpBeforeTransaction() throws Exception { + super.onSetUpBeforeTransaction(); + + gameDao = new JdbcGameDao(); + gameDao.setJdbcTemplate(getJdbcTemplate()); + + game.setId("XXXXX00"); + game.setYear(1996); + game.setTeam("mia"); + game.setWeek(10); + game.setOpponent("nwe"); + game.setAttempts(0); + game.setCompletes(0); + game.setPassingYards(0); + game.setPassingTd(0); + game.setInterceptions(0); + game.setRushes(29); + game.setRushYards(109); + game.setReceptions(1); + game.setReceptionYards(16); + game.setTotalTd(2); + } + + public void testWrite() { + + gameDao.write(game); + + Game tempGame = (Game) getJdbcTemplate().queryForObject("SELECT * FROM GAMES where PLAYER_ID=? AND YEAR_NO=?", + new Object[] { game.getId(), new Integer(game.getYear()) }, new GameRowMapper()); + assertEquals(tempGame, game); + } + + public static class GameRowMapper implements RowMapper { + + public Object mapRow(ResultSet rs, int arg1) throws SQLException { + + if (rs == null) { + return null; + } + + Game game = new Game(); + game.setId(rs.getString("PLAYER_ID").trim()); + game.setYear(rs.getInt("year_no")); + game.setTeam(rs.getString("team")); + game.setWeek(rs.getInt("week")); + game.setOpponent(rs.getString("opponent")); + game.setCompletes(rs.getInt("completes")); + game.setAttempts(rs.getInt("attempts")); + game.setPassingYards(rs.getInt("passing_Yards")); + game.setPassingTd(rs.getInt("passing_Td")); + game.setInterceptions(rs.getInt("interceptions")); + game.setRushes(rs.getInt("rushes")); + game.setRushYards(rs.getInt("rush_Yards")); + game.setReceptions(rs.getInt("receptions")); + game.setReceptionYards(rs.getInt("receptions_Yards")); + game.setTotalTd(rs.getInt("total_Td")); + + return game; + } + } +} diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/dao/JdbcJobRepositoryTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/dao/JdbcJobRepositoryTests.java index cefa22778e..c57d4f2a25 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/dao/JdbcJobRepositoryTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/dao/JdbcJobRepositoryTests.java @@ -1,204 +1,204 @@ -package org.springframework.batch.sample.dao; - -import java.sql.Timestamp; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Set; - -import org.springframework.batch.core.domain.BatchStatus; -import org.springframework.batch.core.domain.JobExecution; -import org.springframework.batch.core.domain.JobParameters; -import org.springframework.batch.core.repository.JobExecutionAlreadyRunningException; -import org.springframework.batch.core.repository.JobRepository; -import org.springframework.batch.sample.tasklet.JobSupport; -import org.springframework.test.AbstractTransactionalDataSourceSpringContextTests; -import org.springframework.transaction.support.TransactionCallback; -import org.springframework.transaction.support.TransactionTemplate; - -public class JdbcJobRepositoryTests extends AbstractTransactionalDataSourceSpringContextTests { - - private JobRepository repository; - - private JobSupport jobConfiguration; - - private Set jobExecutionIds = new HashSet(); - - private Set jobIds = new HashSet(); - - private List list = new ArrayList(); - - public void setRepository(JobRepository repository) { - this.repository = repository; - } - - protected String[] getConfigLocations() { - return new String[] { "simple-job-launcher-context.xml" }; - } - - protected void onSetUpInTransaction() throws Exception { - jobConfiguration = new JobSupport("test-job"); - jobConfiguration.setRestartable(true); - } - - protected void onSetUpBeforeTransaction() throws Exception { - startNewTransaction(); - getJdbcTemplate().update("DELETE FROM BATCH_STEP_EXECUTION_CONTEXT"); - getJdbcTemplate().update("DELETE FROM BATCH_STEP_EXECUTION"); - getJdbcTemplate().update("DELETE FROM BATCH_JOB_EXECUTION"); - getJdbcTemplate().update("DELETE FROM BATCH_JOB_PARAMS"); - getJdbcTemplate().update("DELETE FROM BATCH_JOB_INSTANCE"); - setComplete(); - endTransaction(); - } - - protected void onTearDownAfterTransaction() throws Exception { - startNewTransaction(); - for (Iterator iterator = jobExecutionIds.iterator(); iterator.hasNext();) { - Long id = (Long) iterator.next(); - getJdbcTemplate().update("DELETE FROM BATCH_JOB_EXECUTION where JOB_EXECUTION_ID=?", new Object[] { id }); - } - for (Iterator iterator = jobIds.iterator(); iterator.hasNext();) { - Long id = (Long) iterator.next(); - getJdbcTemplate().update("DELETE FROM BATCH_JOB_INSTANCE where JOB_INSTANCE_ID=?", new Object[] { id }); - } - setComplete(); - endTransaction(); - for (Iterator iterator = jobIds.iterator(); iterator.hasNext();) { - Long id = (Long) iterator.next(); - int count = getJdbcTemplate().queryForInt("SELECT COUNT(*) FROM BATCH_JOB_INSTANCE where JOB_INSTANCE_ID=?", new Object[] { id }); - assertEquals(0, count); - } - } - - public void testFindOrCreateJob() throws Exception { - jobConfiguration.setName("foo"); - int before = getJdbcTemplate().queryForInt("SELECT COUNT(*) FROM BATCH_JOB_INSTANCE"); - JobExecution execution = repository.createJobExecution(jobConfiguration, new JobParameters()); - int after = getJdbcTemplate().queryForInt("SELECT COUNT(*) FROM BATCH_JOB_INSTANCE"); - assertEquals(before + 1, after); - assertNotNull(execution.getId()); - } - - public void testFindOrCreateJobConcurrently() throws Exception { - - jobConfiguration.setName("bar"); - - int before = getJdbcTemplate().queryForInt("SELECT COUNT(*) FROM BATCH_JOB_INSTANCE"); - assertEquals(0, before); - - endTransaction(); - startNewTransaction(); - - JobExecution execution = null; - long t0 = System.currentTimeMillis(); - try { - execution = doConcurrentStart(); - fail("Expected JobExecutionAlreadyRunningException"); - } - catch (JobExecutionAlreadyRunningException e) { - // expected - } - long t1 = System.currentTimeMillis(); - - if (execution == null) { - execution = (JobExecution) list.get(0); - } - - assertNotNull(execution); - - int after = getJdbcTemplate().queryForInt("SELECT COUNT(*) FROM BATCH_JOB_INSTANCE"); - assertNotNull(execution.getId()); - assertEquals(before + 1, after); - - logger.info("Duration: " + (t1 - t0) - + " - the second transaction did not block if this number is less than about 1000."); - } - - public void testFindOrCreateJobConcurrentlyWhenJobAlreadyExists() throws Exception { - - jobConfiguration.setName("spam"); - - JobExecution execution = repository.createJobExecution(jobConfiguration, new JobParameters()); - cacheJobIds(execution); - execution.setEndTime(new Timestamp(System.currentTimeMillis())); - repository.saveOrUpdate(execution); - execution.setStatus(BatchStatus.FAILED); - setComplete(); - endTransaction(); - - startNewTransaction(); - - int before = getJdbcTemplate().queryForInt("SELECT COUNT(*) FROM BATCH_JOB_INSTANCE"); - assertEquals(1, before); - - endTransaction(); - startNewTransaction(); - - long t0 = System.currentTimeMillis(); - try { - execution = doConcurrentStart(); - fail("Expected JobExecutionAlreadyRunningException"); - } - catch (JobExecutionAlreadyRunningException e) { - // expected - } - long t1 = System.currentTimeMillis(); - - int after = getJdbcTemplate().queryForInt("SELECT COUNT(*) FROM BATCH_JOB_INSTANCE"); - assertNotNull(execution.getId()); - assertEquals(before, after); - - logger.info("Duration: " + (t1 - t0) - + " - the second transaction did not block if this number is less than about 1000."); - } - - private void cacheJobIds(JobExecution execution) { - if (execution == null) - return; - jobExecutionIds.add(execution.getId()); - jobIds.add(execution.getJobId()); - } - - private JobExecution doConcurrentStart() throws Exception { - new Thread(new Runnable() { - public void run() { - try { - new TransactionTemplate(transactionManager).execute(new TransactionCallback() { - public Object doInTransaction(org.springframework.transaction.TransactionStatus status) { - try { - JobExecution execution = repository.createJobExecution(jobConfiguration, new JobParameters()); - cacheJobIds(execution); - list.add(execution); - Thread.sleep(1000); - } - catch (Exception e) { - list.add(e); - } - return null; - } - }); - } - catch (RuntimeException e) { - list.add(e); - } - - } - }).start(); - - Thread.sleep(400); - JobExecution execution = repository.createJobExecution(jobConfiguration, new JobParameters()); - cacheJobIds(execution); - - int count = 0; - while (list.size() == 0 && count++ < 10) { - Thread.sleep(200); - } - - assertEquals("Timed out waiting for JobExecution to be created", 1, list.size()); - assertTrue("JobExecution not created in thread", list.get(0) instanceof JobExecution); - return (JobExecution) list.get(0); - } - -} +package org.springframework.batch.sample.dao; + +import java.sql.Timestamp; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Set; + +import org.springframework.batch.core.domain.BatchStatus; +import org.springframework.batch.core.domain.JobExecution; +import org.springframework.batch.core.domain.JobParameters; +import org.springframework.batch.core.repository.JobExecutionAlreadyRunningException; +import org.springframework.batch.core.repository.JobRepository; +import org.springframework.batch.sample.tasklet.JobSupport; +import org.springframework.test.AbstractTransactionalDataSourceSpringContextTests; +import org.springframework.transaction.support.TransactionCallback; +import org.springframework.transaction.support.TransactionTemplate; + +public class JdbcJobRepositoryTests extends AbstractTransactionalDataSourceSpringContextTests { + + private JobRepository repository; + + private JobSupport jobConfiguration; + + private Set jobExecutionIds = new HashSet(); + + private Set jobIds = new HashSet(); + + private List list = new ArrayList(); + + public void setRepository(JobRepository repository) { + this.repository = repository; + } + + protected String[] getConfigLocations() { + return new String[] { "simple-job-launcher-context.xml" }; + } + + protected void onSetUpInTransaction() throws Exception { + jobConfiguration = new JobSupport("test-job"); + jobConfiguration.setRestartable(true); + } + + protected void onSetUpBeforeTransaction() throws Exception { + startNewTransaction(); + getJdbcTemplate().update("DELETE FROM BATCH_STEP_EXECUTION_CONTEXT"); + getJdbcTemplate().update("DELETE FROM BATCH_STEP_EXECUTION"); + getJdbcTemplate().update("DELETE FROM BATCH_JOB_EXECUTION"); + getJdbcTemplate().update("DELETE FROM BATCH_JOB_PARAMS"); + getJdbcTemplate().update("DELETE FROM BATCH_JOB_INSTANCE"); + setComplete(); + endTransaction(); + } + + protected void onTearDownAfterTransaction() throws Exception { + startNewTransaction(); + for (Iterator iterator = jobExecutionIds.iterator(); iterator.hasNext();) { + Long id = (Long) iterator.next(); + getJdbcTemplate().update("DELETE FROM BATCH_JOB_EXECUTION where JOB_EXECUTION_ID=?", new Object[] { id }); + } + for (Iterator iterator = jobIds.iterator(); iterator.hasNext();) { + Long id = (Long) iterator.next(); + getJdbcTemplate().update("DELETE FROM BATCH_JOB_INSTANCE where JOB_INSTANCE_ID=?", new Object[] { id }); + } + setComplete(); + endTransaction(); + for (Iterator iterator = jobIds.iterator(); iterator.hasNext();) { + Long id = (Long) iterator.next(); + int count = getJdbcTemplate().queryForInt("SELECT COUNT(*) FROM BATCH_JOB_INSTANCE where JOB_INSTANCE_ID=?", new Object[] { id }); + assertEquals(0, count); + } + } + + public void testFindOrCreateJob() throws Exception { + jobConfiguration.setName("foo"); + int before = getJdbcTemplate().queryForInt("SELECT COUNT(*) FROM BATCH_JOB_INSTANCE"); + JobExecution execution = repository.createJobExecution(jobConfiguration, new JobParameters()); + int after = getJdbcTemplate().queryForInt("SELECT COUNT(*) FROM BATCH_JOB_INSTANCE"); + assertEquals(before + 1, after); + assertNotNull(execution.getId()); + } + + public void testFindOrCreateJobConcurrently() throws Exception { + + jobConfiguration.setName("bar"); + + int before = getJdbcTemplate().queryForInt("SELECT COUNT(*) FROM BATCH_JOB_INSTANCE"); + assertEquals(0, before); + + endTransaction(); + startNewTransaction(); + + JobExecution execution = null; + long t0 = System.currentTimeMillis(); + try { + execution = doConcurrentStart(); + fail("Expected JobExecutionAlreadyRunningException"); + } + catch (JobExecutionAlreadyRunningException e) { + // expected + } + long t1 = System.currentTimeMillis(); + + if (execution == null) { + execution = (JobExecution) list.get(0); + } + + assertNotNull(execution); + + int after = getJdbcTemplate().queryForInt("SELECT COUNT(*) FROM BATCH_JOB_INSTANCE"); + assertNotNull(execution.getId()); + assertEquals(before + 1, after); + + logger.info("Duration: " + (t1 - t0) + + " - the second transaction did not block if this number is less than about 1000."); + } + + public void testFindOrCreateJobConcurrentlyWhenJobAlreadyExists() throws Exception { + + jobConfiguration.setName("spam"); + + JobExecution execution = repository.createJobExecution(jobConfiguration, new JobParameters()); + cacheJobIds(execution); + execution.setEndTime(new Timestamp(System.currentTimeMillis())); + repository.saveOrUpdate(execution); + execution.setStatus(BatchStatus.FAILED); + setComplete(); + endTransaction(); + + startNewTransaction(); + + int before = getJdbcTemplate().queryForInt("SELECT COUNT(*) FROM BATCH_JOB_INSTANCE"); + assertEquals(1, before); + + endTransaction(); + startNewTransaction(); + + long t0 = System.currentTimeMillis(); + try { + execution = doConcurrentStart(); + fail("Expected JobExecutionAlreadyRunningException"); + } + catch (JobExecutionAlreadyRunningException e) { + // expected + } + long t1 = System.currentTimeMillis(); + + int after = getJdbcTemplate().queryForInt("SELECT COUNT(*) FROM BATCH_JOB_INSTANCE"); + assertNotNull(execution.getId()); + assertEquals(before, after); + + logger.info("Duration: " + (t1 - t0) + + " - the second transaction did not block if this number is less than about 1000."); + } + + private void cacheJobIds(JobExecution execution) { + if (execution == null) + return; + jobExecutionIds.add(execution.getId()); + jobIds.add(execution.getJobId()); + } + + private JobExecution doConcurrentStart() throws Exception { + new Thread(new Runnable() { + public void run() { + try { + new TransactionTemplate(transactionManager).execute(new TransactionCallback() { + public Object doInTransaction(org.springframework.transaction.TransactionStatus status) { + try { + JobExecution execution = repository.createJobExecution(jobConfiguration, new JobParameters()); + cacheJobIds(execution); + list.add(execution); + Thread.sleep(1000); + } + catch (Exception e) { + list.add(e); + } + return null; + } + }); + } + catch (RuntimeException e) { + list.add(e); + } + + } + }).start(); + + Thread.sleep(400); + JobExecution execution = repository.createJobExecution(jobConfiguration, new JobParameters()); + cacheJobIds(execution); + + int count = 0; + while (list.size() == 0 && count++ < 10) { + Thread.sleep(200); + } + + assertEquals("Timed out waiting for JobExecution to be created", 1, list.size()); + assertTrue("JobExecution not created in thread", list.get(0) instanceof JobExecution); + return (JobExecution) list.get(0); + } + +} diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/dao/JdbcPlayerDaoIntegrationTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/dao/JdbcPlayerDaoIntegrationTests.java index c18281fdb6..70de92dcfc 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/dao/JdbcPlayerDaoIntegrationTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/dao/JdbcPlayerDaoIntegrationTests.java @@ -1,59 +1,59 @@ -/** - * - */ -package org.springframework.batch.sample.dao; - -import java.sql.ResultSet; -import java.sql.SQLException; - -import org.springframework.batch.sample.domain.Player; -import org.springframework.jdbc.core.RowCallbackHandler; -import org.springframework.test.AbstractTransactionalDataSourceSpringContextTests; - -/** - * @author Lucas Ward - * - */ -public class JdbcPlayerDaoIntegrationTests extends AbstractTransactionalDataSourceSpringContextTests { - - private JdbcPlayerDao playerDao; - private Player player; - private static final String GET_PLAYER = "SELECT * from PLAYERS"; - - protected String[] getConfigLocations() { - return new String[] {"data-source-context.xml"}; - } - - protected void onSetUpBeforeTransaction() throws Exception { - super.onSetUpBeforeTransaction(); - - playerDao = new JdbcPlayerDao(); - playerDao.setJdbcTemplate(this.jdbcTemplate); - - player = new Player(); - player.setID("AKFJDL00"); - player.setFirstName("John"); - player.setLastName("Doe"); - player.setPosition("QB"); - player.setBirthYear(1975); - player.setDebutYear(1998); - } - - public void testSavePlayer(){ - - playerDao.savePlayer(player); - - getJdbcTemplate().query(GET_PLAYER, new RowCallbackHandler(){ - - public void processRow(ResultSet rs) throws SQLException { - assertEquals(rs.getString("PLAYER_ID"), "AKFJDL00"); - assertEquals(rs.getString("LAST_NAME"), "Doe"); - assertEquals(rs.getString("FIRST_NAME"), "John"); - assertEquals(rs.getString("POS"), "QB"); - assertEquals(rs.getInt("YEAR_OF_BIRTH"), 1975); - assertEquals(rs.getInt("YEAR_DRAFTED"), 1998); - } - }); - } - -} +/** + * + */ +package org.springframework.batch.sample.dao; + +import java.sql.ResultSet; +import java.sql.SQLException; + +import org.springframework.batch.sample.domain.Player; +import org.springframework.jdbc.core.RowCallbackHandler; +import org.springframework.test.AbstractTransactionalDataSourceSpringContextTests; + +/** + * @author Lucas Ward + * + */ +public class JdbcPlayerDaoIntegrationTests extends AbstractTransactionalDataSourceSpringContextTests { + + private JdbcPlayerDao playerDao; + private Player player; + private static final String GET_PLAYER = "SELECT * from PLAYERS"; + + protected String[] getConfigLocations() { + return new String[] {"data-source-context.xml"}; + } + + protected void onSetUpBeforeTransaction() throws Exception { + super.onSetUpBeforeTransaction(); + + playerDao = new JdbcPlayerDao(); + playerDao.setJdbcTemplate(this.jdbcTemplate); + + player = new Player(); + player.setID("AKFJDL00"); + player.setFirstName("John"); + player.setLastName("Doe"); + player.setPosition("QB"); + player.setBirthYear(1975); + player.setDebutYear(1998); + } + + public void testSavePlayer(){ + + playerDao.savePlayer(player); + + getJdbcTemplate().query(GET_PLAYER, new RowCallbackHandler(){ + + public void processRow(ResultSet rs) throws SQLException { + assertEquals(rs.getString("PLAYER_ID"), "AKFJDL00"); + assertEquals(rs.getString("LAST_NAME"), "Doe"); + assertEquals(rs.getString("FIRST_NAME"), "John"); + assertEquals(rs.getString("POS"), "QB"); + assertEquals(rs.getInt("YEAR_OF_BIRTH"), 1975); + assertEquals(rs.getInt("YEAR_DRAFTED"), 1998); + } + }); + } + +} diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/dao/JdbcPlayerSummaryDaoIntegrationTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/dao/JdbcPlayerSummaryDaoIntegrationTests.java index df1b537f44..689680285d 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/dao/JdbcPlayerSummaryDaoIntegrationTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/dao/JdbcPlayerSummaryDaoIntegrationTests.java @@ -1,70 +1,70 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.sample.dao; - - -import org.springframework.batch.sample.domain.PlayerSummary; -import org.springframework.batch.sample.mapping.PlayerSummaryMapper; -import org.springframework.test.AbstractTransactionalDataSourceSpringContextTests; - - -/** - * @author Lucas Ward - * - */ -public class JdbcPlayerSummaryDaoIntegrationTests extends - AbstractTransactionalDataSourceSpringContextTests { - - JdbcPlayerSummaryDao playerSummaryDao; - PlayerSummary summary; - - protected String[] getConfigLocations() { - return new String[] { "data-source-context.xml" }; - } - - protected void onSetUpBeforeTransaction() throws Exception { - super.onSetUpBeforeTransaction(); - - playerSummaryDao = new JdbcPlayerSummaryDao(); - playerSummaryDao.setJdbcTemplate(getJdbcTemplate()); - - summary = new PlayerSummary(); - summary.setId("AikmTr00"); - summary.setYear(1997); - summary.setCompletes(294); - summary.setAttempts(517); - summary.setPassingYards(3283); - summary.setPassingTd(19); - summary.setInterceptions(12); - summary.setRushes(25); - summary.setRushYards(79); - summary.setReceptions(0); - summary.setReceptionYards(0); - summary.setTotalTd(0); - } - - public void testWrite() { - - playerSummaryDao.write(summary); - - PlayerSummary testSummary = (PlayerSummary) getJdbcTemplate() - .queryForObject("SELECT * FROM PLAYER_SUMMARY", - new PlayerSummaryMapper()); - - assertEquals(testSummary, summary); - } - -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.sample.dao; + + +import org.springframework.batch.sample.domain.PlayerSummary; +import org.springframework.batch.sample.mapping.PlayerSummaryMapper; +import org.springframework.test.AbstractTransactionalDataSourceSpringContextTests; + + +/** + * @author Lucas Ward + * + */ +public class JdbcPlayerSummaryDaoIntegrationTests extends + AbstractTransactionalDataSourceSpringContextTests { + + JdbcPlayerSummaryDao playerSummaryDao; + PlayerSummary summary; + + protected String[] getConfigLocations() { + return new String[] { "data-source-context.xml" }; + } + + protected void onSetUpBeforeTransaction() throws Exception { + super.onSetUpBeforeTransaction(); + + playerSummaryDao = new JdbcPlayerSummaryDao(); + playerSummaryDao.setJdbcTemplate(getJdbcTemplate()); + + summary = new PlayerSummary(); + summary.setId("AikmTr00"); + summary.setYear(1997); + summary.setCompletes(294); + summary.setAttempts(517); + summary.setPassingYards(3283); + summary.setPassingTd(19); + summary.setInterceptions(12); + summary.setRushes(25); + summary.setRushYards(79); + summary.setReceptions(0); + summary.setReceptionYards(0); + summary.setTotalTd(0); + } + + public void testWrite() { + + playerSummaryDao.write(summary); + + PlayerSummary testSummary = (PlayerSummary) getJdbcTemplate() + .queryForObject("SELECT * FROM PLAYER_SUMMARY", + new PlayerSummaryMapper()); + + assertEquals(testSummary, summary); + } + +} diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/dao/JdbcTradeWriterTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/dao/JdbcTradeWriterTests.java index 130e71b989..15c99667b2 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/dao/JdbcTradeWriterTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/dao/JdbcTradeWriterTests.java @@ -1,44 +1,44 @@ -package org.springframework.batch.sample.dao; - -import java.math.BigDecimal; -import java.sql.ResultSet; -import java.sql.SQLException; - -import org.springframework.batch.sample.domain.Trade; -import org.springframework.jdbc.core.RowCallbackHandler; -import org.springframework.jdbc.support.incrementer.AbstractDataFieldMaxValueIncrementer; -import org.springframework.test.AbstractTransactionalDataSourceSpringContextTests; - -public class JdbcTradeWriterTests extends AbstractTransactionalDataSourceSpringContextTests { - - protected String[] getConfigLocations() { - return new String[] { "data-source-context.xml" }; - } - - public void testWrite() { - - JdbcTradeDao writer = new JdbcTradeDao(); - - AbstractDataFieldMaxValueIncrementer incrementer = (AbstractDataFieldMaxValueIncrementer)applicationContext.getBean("incrementerParent"); - incrementer.setIncrementerName("TRADE_SEQ"); - - writer.setIncrementer(incrementer); - writer.setJdbcTemplate(jdbcTemplate); - - Trade trade = new Trade(); - trade.setCustomer("testCustomer"); - trade.setIsin("5647238492"); - trade.setPrice(new BigDecimal(Double.toString(99.69))); - trade.setQuantity(5); - - writer.writeTrade(trade); - - jdbcTemplate.query("SELECT * FROM TRADE WHERE ISIN = '5647238492'", new RowCallbackHandler() { - public void processRow(ResultSet rs) throws SQLException { - assertEquals("testCustomer", rs.getString("CUSTOMER")); - assertEquals(new BigDecimal(Double.toString(99.69)), rs.getBigDecimal("PRICE")); - assertEquals(5,rs.getLong("QUANTITY")); - } - }); - } -} +package org.springframework.batch.sample.dao; + +import java.math.BigDecimal; +import java.sql.ResultSet; +import java.sql.SQLException; + +import org.springframework.batch.sample.domain.Trade; +import org.springframework.jdbc.core.RowCallbackHandler; +import org.springframework.jdbc.support.incrementer.AbstractDataFieldMaxValueIncrementer; +import org.springframework.test.AbstractTransactionalDataSourceSpringContextTests; + +public class JdbcTradeWriterTests extends AbstractTransactionalDataSourceSpringContextTests { + + protected String[] getConfigLocations() { + return new String[] { "data-source-context.xml" }; + } + + public void testWrite() { + + JdbcTradeDao writer = new JdbcTradeDao(); + + AbstractDataFieldMaxValueIncrementer incrementer = (AbstractDataFieldMaxValueIncrementer)applicationContext.getBean("incrementerParent"); + incrementer.setIncrementerName("TRADE_SEQ"); + + writer.setIncrementer(incrementer); + writer.setJdbcTemplate(jdbcTemplate); + + Trade trade = new Trade(); + trade.setCustomer("testCustomer"); + trade.setIsin("5647238492"); + trade.setPrice(new BigDecimal(Double.toString(99.69))); + trade.setQuantity(5); + + writer.writeTrade(trade); + + jdbcTemplate.query("SELECT * FROM TRADE WHERE ISIN = '5647238492'", new RowCallbackHandler() { + public void processRow(ResultSet rs) throws SQLException { + assertEquals("testCustomer", rs.getString("CUSTOMER")); + assertEquals(new BigDecimal(Double.toString(99.69)), rs.getBigDecimal("PRICE")); + assertEquals(5,rs.getLong("QUANTITY")); + } + }); + } +} diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/dao/OrderTransformerTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/dao/OrderTransformerTests.java index 026bcac77a..2aca104511 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/dao/OrderTransformerTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/dao/OrderTransformerTests.java @@ -1,62 +1,62 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.sample.dao; - -import java.math.BigDecimal; -import java.util.Collection; -import java.util.Collections; -import java.util.Date; -import java.util.HashMap; - -import junit.framework.TestCase; - -import org.springframework.batch.io.file.transform.DelimitedLineAggregator; -import org.springframework.batch.sample.domain.Address; -import org.springframework.batch.sample.domain.BillingInfo; -import org.springframework.batch.sample.domain.Customer; -import org.springframework.batch.sample.domain.Order; - -/** - * @author Dave Syer - * - */ -public class OrderTransformerTests extends TestCase { - - private OrderTransformer converter = new OrderTransformer(); - - public void testConvert() throws Exception { - converter.setAggregators(new HashMap() { - { - put("header", new DelimitedLineAggregator()); - put("customer", new DelimitedLineAggregator()); - put("address", new DelimitedLineAggregator()); - put("billing", new DelimitedLineAggregator()); - put("item", new DelimitedLineAggregator()); - put("footer", new DelimitedLineAggregator()); - } - }); - Order order = new Order(); - order.setOrderDate(new Date()); - order.setCustomer(new Customer()); - order.setBillingAddress(new Address()); - order.setBilling(new BillingInfo()); - order.setLineItems(Collections.EMPTY_LIST); - order.setTotalPrice(new BigDecimal(10)); - Object result = converter.transform(order); - assertTrue(result instanceof Collection); - } - -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.sample.dao; + +import java.math.BigDecimal; +import java.util.Collection; +import java.util.Collections; +import java.util.Date; +import java.util.HashMap; + +import junit.framework.TestCase; + +import org.springframework.batch.io.file.transform.DelimitedLineAggregator; +import org.springframework.batch.sample.domain.Address; +import org.springframework.batch.sample.domain.BillingInfo; +import org.springframework.batch.sample.domain.Customer; +import org.springframework.batch.sample.domain.Order; + +/** + * @author Dave Syer + * + */ +public class OrderTransformerTests extends TestCase { + + private OrderTransformer converter = new OrderTransformer(); + + public void testConvert() throws Exception { + converter.setAggregators(new HashMap() { + { + put("header", new DelimitedLineAggregator()); + put("customer", new DelimitedLineAggregator()); + put("address", new DelimitedLineAggregator()); + put("billing", new DelimitedLineAggregator()); + put("item", new DelimitedLineAggregator()); + put("footer", new DelimitedLineAggregator()); + } + }); + Order order = new Order(); + order.setOrderDate(new Date()); + order.setCustomer(new Customer()); + order.setBillingAddress(new Address()); + order.setBilling(new BillingInfo()); + order.setLineItems(Collections.EMPTY_LIST); + order.setTotalPrice(new BigDecimal(10)); + Object result = converter.transform(order); + assertTrue(result instanceof Collection); + } + +} diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/item/reader/GeneratingItemReaderTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/item/reader/GeneratingItemReaderTests.java index d21c3fbbe1..bf088c8b1f 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/item/reader/GeneratingItemReaderTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/item/reader/GeneratingItemReaderTests.java @@ -1,31 +1,31 @@ -package org.springframework.batch.sample.item.reader; - -import junit.framework.TestCase; - -/** - * Tests for {@link GeneratingItemReader}. - * - * @author Robert Kasanicky - */ -public class GeneratingItemReaderTests extends TestCase { - - private GeneratingItemReader reader = new GeneratingItemReader(); - - /** - * Generates a given number of not-null records, - * consecutive calls return null. - */ - public void testRead() throws Exception { - int counter = 0; - int limit = 10; - reader.setLimit(limit); - - while (reader.read() != null) { - counter++; - } - - assertEquals(null, reader.read()); - assertEquals(limit, counter); - assertEquals(counter, reader.getCounter()); - } -} +package org.springframework.batch.sample.item.reader; + +import junit.framework.TestCase; + +/** + * Tests for {@link GeneratingItemReader}. + * + * @author Robert Kasanicky + */ +public class GeneratingItemReaderTests extends TestCase { + + private GeneratingItemReader reader = new GeneratingItemReader(); + + /** + * Generates a given number of not-null records, + * consecutive calls return null. + */ + public void testRead() throws Exception { + int counter = 0; + int limit = 10; + reader.setLimit(limit); + + while (reader.read() != null) { + counter++; + } + + assertEquals(null, reader.read()); + assertEquals(limit, counter); + assertEquals(counter, reader.getCounter()); + } +} diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/item/reader/OrderItemReaderTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/item/reader/OrderItemReaderTests.java index ab1a36c1ea..798cfaf162 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/item/reader/OrderItemReaderTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/item/reader/OrderItemReaderTests.java @@ -1,151 +1,151 @@ -package org.springframework.batch.sample.item.reader; - -import java.util.Iterator; - -import junit.framework.TestCase; - -import org.easymock.MockControl; -import org.springframework.batch.io.file.mapping.DefaultFieldSet; -import org.springframework.batch.io.file.mapping.FieldSet; -import org.springframework.batch.io.file.mapping.FieldSetMapper; -import org.springframework.batch.item.ItemReader; -import org.springframework.batch.sample.domain.Address; -import org.springframework.batch.sample.domain.BillingInfo; -import org.springframework.batch.sample.domain.Customer; -import org.springframework.batch.sample.domain.LineItem; -import org.springframework.batch.sample.domain.Order; -import org.springframework.batch.sample.domain.ShippingInfo; - -public class OrderItemReaderTests extends TestCase { - - private OrderItemReader provider; - private MockControl inputControl; - private ItemReader input; - private MockControl mapperControl; - private FieldSetMapper mapper; - - public void setUp() { - - inputControl = MockControl.createControl(ItemReader.class); - input = (ItemReader)inputControl.getMock(); - - provider = new OrderItemReader(); - provider.setItemReader(input); - } - - /* - * OrderItemProvider is resposible for retrieving validated value object from input source. - * OrderItemProvider.next(): - * - reads lines from the input source - returned as fieldsets - * - pass fieldsets to the mapper - mapper will create value object - * - pass value object to validator - * - returns validated object - * - * In testNext method we are going to test these responsibilities. So we need create mock - * objects for input source, mapper and validator. - */ - public void testNext() throws Exception { - - //create fieldsets and set return values for input source - FieldSet headerFS = new DefaultFieldSet(new String[] {Order.LINE_ID_HEADER}); - FieldSet customerFS = new DefaultFieldSet(new String[] {Customer.LINE_ID_NON_BUSINESS_CUST}); - FieldSet billingFS = new DefaultFieldSet(new String[] {Address.LINE_ID_BILLING_ADDR}); - FieldSet shippingFS = new DefaultFieldSet(new String[] {Address.LINE_ID_SHIPPING_ADDR}); - FieldSet billingInfoFS = new DefaultFieldSet(new String[] {BillingInfo.LINE_ID_BILLING_INFO}); - FieldSet shippingInfoFS = new DefaultFieldSet(new String[] {ShippingInfo.LINE_ID_SHIPPING_INFO}); - FieldSet itemFS = new DefaultFieldSet(new String[] {LineItem.LINE_ID_ITEM}); - FieldSet footerFS = new DefaultFieldSet(new String[] {Order.LINE_ID_FOOTER, "100","3","3"}, - new String[] {"ID","TOTAL_PRICE","TOTAL_LINE_ITEMS","TOTAL_ITEMS"}); - - input.read(); - inputControl.setReturnValue(headerFS); - input.read(); - inputControl.setReturnValue(customerFS); - input.read(); - inputControl.setReturnValue(billingFS); - input.read(); - inputControl.setReturnValue(shippingFS); - input.read(); - inputControl.setReturnValue(billingInfoFS); - input.read(); - inputControl.setReturnValue(shippingInfoFS); - input.read(); - inputControl.setReturnValue(itemFS,3); - input.read(); - inputControl.setReturnValue(footerFS); - input.read(); - inputControl.setReturnValue(null); - inputControl.replay(); - - //create value objects - Order order = new Order(); - Customer customer = new Customer(); - Address billing = new Address(); - Address shipping = new Address(); - BillingInfo billingInfo = new BillingInfo(); - ShippingInfo shippingInfo = new ShippingInfo(); - LineItem item = new LineItem(); - - //create mock mapper - mapperControl = MockControl.createControl(FieldSetMapper.class); - mapper = (FieldSetMapper)mapperControl.getMock(); - //set how mapper should respond - set return values for mapper - mapper.mapLine(headerFS); - mapperControl.setReturnValue(order); - mapper.mapLine(customerFS); - mapperControl.setReturnValue(customer); - mapper.mapLine(billingFS); - mapperControl.setReturnValue(billing); - mapper.mapLine(shippingFS); - mapperControl.setReturnValue(shipping); - mapper.mapLine(billingInfoFS); - mapperControl.setReturnValue(billingInfo); - mapper.mapLine(shippingInfoFS); - mapperControl.setReturnValue(shippingInfo); - mapper.mapLine(itemFS); - mapperControl.setReturnValue(item,3); - mapperControl.replay(); - - - //set-up provider: set mappers - provider.setAddressMapper(mapper); - provider.setBillingMapper(mapper); - provider.setCustomerMapper(mapper); - provider.setHeaderMapper(mapper); - provider.setItemMapper(mapper); - provider.setShippingMapper(mapper); - - //call tested method - Object result = provider.read(); - - //verify result - assertNotNull(result); - //result should be Order - assertTrue(result instanceof Order); - - //verify whether order is constructed correctly - //Order object should contain same instances as returned by mapper - Order o = (Order) result; - assertEquals(o,order); - assertEquals(o.getCustomer(),customer); - //is it non-bussines customer - assertFalse(o.getCustomer().isBusinessCustomer()); - assertEquals(o.getBillingAddress(),billing); - assertEquals(o.getShippingAddress(),shipping); - assertEquals(o.getBilling(),billingInfo); - assertEquals(o.getShipping(), shippingInfo); - //there should be 3 line items - assertEquals(3, o.getLineItems().size()); - for (Iterator i = o.getLineItems().iterator(); i.hasNext();) { - assertEquals(i.next(),item); - } - - //try to retrieve next object - nothing should be returned - assertNull(provider.read()); - - //verify method calls on input source, mapper and validator - inputControl.verify(); - mapperControl.verify(); - } - -} +package org.springframework.batch.sample.item.reader; + +import java.util.Iterator; + +import junit.framework.TestCase; + +import org.easymock.MockControl; +import org.springframework.batch.io.file.mapping.DefaultFieldSet; +import org.springframework.batch.io.file.mapping.FieldSet; +import org.springframework.batch.io.file.mapping.FieldSetMapper; +import org.springframework.batch.item.ItemReader; +import org.springframework.batch.sample.domain.Address; +import org.springframework.batch.sample.domain.BillingInfo; +import org.springframework.batch.sample.domain.Customer; +import org.springframework.batch.sample.domain.LineItem; +import org.springframework.batch.sample.domain.Order; +import org.springframework.batch.sample.domain.ShippingInfo; + +public class OrderItemReaderTests extends TestCase { + + private OrderItemReader provider; + private MockControl inputControl; + private ItemReader input; + private MockControl mapperControl; + private FieldSetMapper mapper; + + public void setUp() { + + inputControl = MockControl.createControl(ItemReader.class); + input = (ItemReader)inputControl.getMock(); + + provider = new OrderItemReader(); + provider.setItemReader(input); + } + + /* + * OrderItemProvider is resposible for retrieving validated value object from input source. + * OrderItemProvider.next(): + * - reads lines from the input source - returned as fieldsets + * - pass fieldsets to the mapper - mapper will create value object + * - pass value object to validator + * - returns validated object + * + * In testNext method we are going to test these responsibilities. So we need create mock + * objects for input source, mapper and validator. + */ + public void testNext() throws Exception { + + //create fieldsets and set return values for input source + FieldSet headerFS = new DefaultFieldSet(new String[] {Order.LINE_ID_HEADER}); + FieldSet customerFS = new DefaultFieldSet(new String[] {Customer.LINE_ID_NON_BUSINESS_CUST}); + FieldSet billingFS = new DefaultFieldSet(new String[] {Address.LINE_ID_BILLING_ADDR}); + FieldSet shippingFS = new DefaultFieldSet(new String[] {Address.LINE_ID_SHIPPING_ADDR}); + FieldSet billingInfoFS = new DefaultFieldSet(new String[] {BillingInfo.LINE_ID_BILLING_INFO}); + FieldSet shippingInfoFS = new DefaultFieldSet(new String[] {ShippingInfo.LINE_ID_SHIPPING_INFO}); + FieldSet itemFS = new DefaultFieldSet(new String[] {LineItem.LINE_ID_ITEM}); + FieldSet footerFS = new DefaultFieldSet(new String[] {Order.LINE_ID_FOOTER, "100","3","3"}, + new String[] {"ID","TOTAL_PRICE","TOTAL_LINE_ITEMS","TOTAL_ITEMS"}); + + input.read(); + inputControl.setReturnValue(headerFS); + input.read(); + inputControl.setReturnValue(customerFS); + input.read(); + inputControl.setReturnValue(billingFS); + input.read(); + inputControl.setReturnValue(shippingFS); + input.read(); + inputControl.setReturnValue(billingInfoFS); + input.read(); + inputControl.setReturnValue(shippingInfoFS); + input.read(); + inputControl.setReturnValue(itemFS,3); + input.read(); + inputControl.setReturnValue(footerFS); + input.read(); + inputControl.setReturnValue(null); + inputControl.replay(); + + //create value objects + Order order = new Order(); + Customer customer = new Customer(); + Address billing = new Address(); + Address shipping = new Address(); + BillingInfo billingInfo = new BillingInfo(); + ShippingInfo shippingInfo = new ShippingInfo(); + LineItem item = new LineItem(); + + //create mock mapper + mapperControl = MockControl.createControl(FieldSetMapper.class); + mapper = (FieldSetMapper)mapperControl.getMock(); + //set how mapper should respond - set return values for mapper + mapper.mapLine(headerFS); + mapperControl.setReturnValue(order); + mapper.mapLine(customerFS); + mapperControl.setReturnValue(customer); + mapper.mapLine(billingFS); + mapperControl.setReturnValue(billing); + mapper.mapLine(shippingFS); + mapperControl.setReturnValue(shipping); + mapper.mapLine(billingInfoFS); + mapperControl.setReturnValue(billingInfo); + mapper.mapLine(shippingInfoFS); + mapperControl.setReturnValue(shippingInfo); + mapper.mapLine(itemFS); + mapperControl.setReturnValue(item,3); + mapperControl.replay(); + + + //set-up provider: set mappers + provider.setAddressMapper(mapper); + provider.setBillingMapper(mapper); + provider.setCustomerMapper(mapper); + provider.setHeaderMapper(mapper); + provider.setItemMapper(mapper); + provider.setShippingMapper(mapper); + + //call tested method + Object result = provider.read(); + + //verify result + assertNotNull(result); + //result should be Order + assertTrue(result instanceof Order); + + //verify whether order is constructed correctly + //Order object should contain same instances as returned by mapper + Order o = (Order) result; + assertEquals(o,order); + assertEquals(o.getCustomer(),customer); + //is it non-bussines customer + assertFalse(o.getCustomer().isBusinessCustomer()); + assertEquals(o.getBillingAddress(),billing); + assertEquals(o.getShippingAddress(),shipping); + assertEquals(o.getBilling(),billingInfo); + assertEquals(o.getShipping(), shippingInfo); + //there should be 3 line items + assertEquals(3, o.getLineItems().size()); + for (Iterator i = o.getLineItems().iterator(); i.hasNext();) { + assertEquals(i.next(),item); + } + + //try to retrieve next object - nothing should be returned + assertNull(provider.read()); + + //verify method calls on input source, mapper and validator + inputControl.verify(); + mapperControl.verify(); + } + +} diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/item/reader/StagingItemReaderTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/item/reader/StagingItemReaderTests.java index 23fd483c14..ae62495287 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/item/reader/StagingItemReaderTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/item/reader/StagingItemReaderTests.java @@ -1,154 +1,154 @@ -package org.springframework.batch.sample.item.reader; - -import org.springframework.batch.core.domain.JobExecution; -import org.springframework.batch.core.domain.JobInstance; -import org.springframework.batch.core.domain.JobParameters; -import org.springframework.batch.core.domain.StepExecution; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.sample.item.writer.StagingItemWriter; -import org.springframework.batch.sample.tasklet.JobSupport; -import org.springframework.batch.sample.tasklet.StepSupport; -import org.springframework.test.AbstractTransactionalDataSourceSpringContextTests; -import org.springframework.util.ClassUtils; - -public class StagingItemReaderTests extends AbstractTransactionalDataSourceSpringContextTests { - - private StagingItemWriter writer; - - private StagingItemReader reader; - - private Long jobId = new Long(11); - - public void setProcessor(StagingItemWriter writer) { - this.writer = writer; - } - - public void setProvider(StagingItemReader reader) { - this.reader = reader; - } - - protected String[] getConfigLocations() { - return new String[] { ClassUtils.addResourcePathToPackagePath(StagingItemWriter.class, - "staging-test-context.xml") }; - } - - /* (non-Javadoc) - * @see org.springframework.test.AbstractTransactionalSpringContextTests#onSetUpBeforeTransaction() - */ - protected void onSetUpBeforeTransaction() throws Exception { - StepExecution stepExecution = new StepExecution(new StepSupport("stepName"), - new JobExecution(new JobInstance(jobId, new JobParameters(), new JobSupport("testJob")))); - reader.beforeStep(stepExecution); - writer.beforeStep(stepExecution); - } - - protected void onSetUpInTransaction() throws Exception { - writer.write("FOO"); - writer.write("BAR"); - writer.write("SPAM"); - writer.write("BUCKET"); - reader.open(new ExecutionContext()); - } - - protected void onTearDownAfterTransaction() throws Exception { - reader.close(null); - getJdbcTemplate().update("DELETE FROM BATCH_STAGING"); - } - - public void testReaderUpdatesProcessIndicator() throws Exception { - - long id = getJdbcTemplate().queryForLong("SELECT MIN(ID) from BATCH_STAGING where JOB_ID=?", - new Object[] { jobId }); - String before = (String) getJdbcTemplate().queryForObject("SELECT PROCESSED from BATCH_STAGING where ID=?", - new Object[] { new Long(id) }, String.class); - assertEquals(StagingItemWriter.NEW, before); - - Object item = reader.read(); - assertEquals("FOO", item); - - String after = (String) getJdbcTemplate().queryForObject("SELECT PROCESSED from BATCH_STAGING where ID=?", - new Object[] { new Long(id) }, String.class); - assertEquals(StagingItemWriter.DONE, after); - - } - - public void testUpdateProcessIndicatorAfterCommit() throws Exception { - testReaderUpdatesProcessIndicator(); - setComplete(); - endTransaction(); - startNewTransaction(); - long id = getJdbcTemplate().queryForLong("SELECT MIN(ID) from BATCH_STAGING where JOB_ID=?", - new Object[] { jobId }); - String before = (String) getJdbcTemplate().queryForObject("SELECT PROCESSED from BATCH_STAGING where ID=?", - new Object[] { new Long(id) }, String.class); - assertEquals(StagingItemWriter.DONE, before); - } - - public void testProviderRollsBackMultipleTimes() throws Exception { - - reader.mark(); - setComplete(); - endTransaction(); - startNewTransaction(); - - int count = getJdbcTemplate().queryForInt("SELECT COUNT(*) from BATCH_STAGING where JOB_ID=? AND PROCESSED=?", - new Object[] { jobId, StagingItemWriter.NEW }); - assertEquals(4, count); - - Object item = reader.read(); - assertEquals("FOO", item); - item = reader.read(); - assertEquals("BAR", item); - - reader.reset(); - endTransaction(); - startNewTransaction(); - - item = reader.read(); - assertEquals("FOO", item); - item = reader.read(); - assertEquals("BAR", item); - item = reader.read(); - assertEquals("SPAM", item); - - reader.reset(); - endTransaction(); - startNewTransaction(); - - item = reader.read(); - assertEquals("FOO", item); - - } - - public void testProviderRollsBackProcessIndicator() throws Exception { - - reader.mark(); - setComplete(); - endTransaction(); - startNewTransaction(); - // After a rollback we have to resynchronize the TX to simulate a real - // batch - - long id = getJdbcTemplate().queryForLong("SELECT MIN(ID) from BATCH_STAGING where JOB_ID=?", - new Object[] { jobId }); - String before = (String) getJdbcTemplate().queryForObject("SELECT PROCESSED from BATCH_STAGING where ID=?", - new Object[] { new Long(id) }, String.class); - assertEquals(StagingItemWriter.NEW, before); - - Object item = reader.read(); - assertEquals("FOO", item); - - reader.reset(); - endTransaction(); - startNewTransaction(); - // After a rollback we have to resynchronize the TX to simulate a real - // batch - - String after = (String) getJdbcTemplate().queryForObject("SELECT PROCESSED from BATCH_STAGING where ID=?", - new Object[] { new Long(id) }, String.class); - assertEquals(StagingItemWriter.NEW, after); - - item = reader.read(); - assertEquals("FOO", item); - } -} +package org.springframework.batch.sample.item.reader; + +import org.springframework.batch.core.domain.JobExecution; +import org.springframework.batch.core.domain.JobInstance; +import org.springframework.batch.core.domain.JobParameters; +import org.springframework.batch.core.domain.StepExecution; +import org.springframework.batch.item.ExecutionContext; +import org.springframework.batch.sample.item.writer.StagingItemWriter; +import org.springframework.batch.sample.tasklet.JobSupport; +import org.springframework.batch.sample.tasklet.StepSupport; +import org.springframework.test.AbstractTransactionalDataSourceSpringContextTests; +import org.springframework.util.ClassUtils; + +public class StagingItemReaderTests extends AbstractTransactionalDataSourceSpringContextTests { + + private StagingItemWriter writer; + + private StagingItemReader reader; + + private Long jobId = new Long(11); + + public void setProcessor(StagingItemWriter writer) { + this.writer = writer; + } + + public void setProvider(StagingItemReader reader) { + this.reader = reader; + } + + protected String[] getConfigLocations() { + return new String[] { ClassUtils.addResourcePathToPackagePath(StagingItemWriter.class, + "staging-test-context.xml") }; + } + + /* (non-Javadoc) + * @see org.springframework.test.AbstractTransactionalSpringContextTests#onSetUpBeforeTransaction() + */ + protected void onSetUpBeforeTransaction() throws Exception { + StepExecution stepExecution = new StepExecution(new StepSupport("stepName"), + new JobExecution(new JobInstance(jobId, new JobParameters(), new JobSupport("testJob")))); + reader.beforeStep(stepExecution); + writer.beforeStep(stepExecution); + } + + protected void onSetUpInTransaction() throws Exception { + writer.write("FOO"); + writer.write("BAR"); + writer.write("SPAM"); + writer.write("BUCKET"); + reader.open(new ExecutionContext()); + } + + protected void onTearDownAfterTransaction() throws Exception { + reader.close(null); + getJdbcTemplate().update("DELETE FROM BATCH_STAGING"); + } + + public void testReaderUpdatesProcessIndicator() throws Exception { + + long id = getJdbcTemplate().queryForLong("SELECT MIN(ID) from BATCH_STAGING where JOB_ID=?", + new Object[] { jobId }); + String before = (String) getJdbcTemplate().queryForObject("SELECT PROCESSED from BATCH_STAGING where ID=?", + new Object[] { new Long(id) }, String.class); + assertEquals(StagingItemWriter.NEW, before); + + Object item = reader.read(); + assertEquals("FOO", item); + + String after = (String) getJdbcTemplate().queryForObject("SELECT PROCESSED from BATCH_STAGING where ID=?", + new Object[] { new Long(id) }, String.class); + assertEquals(StagingItemWriter.DONE, after); + + } + + public void testUpdateProcessIndicatorAfterCommit() throws Exception { + testReaderUpdatesProcessIndicator(); + setComplete(); + endTransaction(); + startNewTransaction(); + long id = getJdbcTemplate().queryForLong("SELECT MIN(ID) from BATCH_STAGING where JOB_ID=?", + new Object[] { jobId }); + String before = (String) getJdbcTemplate().queryForObject("SELECT PROCESSED from BATCH_STAGING where ID=?", + new Object[] { new Long(id) }, String.class); + assertEquals(StagingItemWriter.DONE, before); + } + + public void testProviderRollsBackMultipleTimes() throws Exception { + + reader.mark(); + setComplete(); + endTransaction(); + startNewTransaction(); + + int count = getJdbcTemplate().queryForInt("SELECT COUNT(*) from BATCH_STAGING where JOB_ID=? AND PROCESSED=?", + new Object[] { jobId, StagingItemWriter.NEW }); + assertEquals(4, count); + + Object item = reader.read(); + assertEquals("FOO", item); + item = reader.read(); + assertEquals("BAR", item); + + reader.reset(); + endTransaction(); + startNewTransaction(); + + item = reader.read(); + assertEquals("FOO", item); + item = reader.read(); + assertEquals("BAR", item); + item = reader.read(); + assertEquals("SPAM", item); + + reader.reset(); + endTransaction(); + startNewTransaction(); + + item = reader.read(); + assertEquals("FOO", item); + + } + + public void testProviderRollsBackProcessIndicator() throws Exception { + + reader.mark(); + setComplete(); + endTransaction(); + startNewTransaction(); + // After a rollback we have to resynchronize the TX to simulate a real + // batch + + long id = getJdbcTemplate().queryForLong("SELECT MIN(ID) from BATCH_STAGING where JOB_ID=?", + new Object[] { jobId }); + String before = (String) getJdbcTemplate().queryForObject("SELECT PROCESSED from BATCH_STAGING where ID=?", + new Object[] { new Long(id) }, String.class); + assertEquals(StagingItemWriter.NEW, before); + + Object item = reader.read(); + assertEquals("FOO", item); + + reader.reset(); + endTransaction(); + startNewTransaction(); + // After a rollback we have to resynchronize the TX to simulate a real + // batch + + String after = (String) getJdbcTemplate().queryForObject("SELECT PROCESSED from BATCH_STAGING where ID=?", + new Object[] { new Long(id) }, String.class); + assertEquals(StagingItemWriter.NEW, after); + + item = reader.read(); + assertEquals("FOO", item); + } +} diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/item/writer/CustomerCreditIncreaseProcessorTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/item/writer/CustomerCreditIncreaseProcessorTests.java index 1e03925133..2b32551906 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/item/writer/CustomerCreditIncreaseProcessorTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/item/writer/CustomerCreditIncreaseProcessorTests.java @@ -1,53 +1,53 @@ -package org.springframework.batch.sample.item.writer; - -import java.math.BigDecimal; - -import junit.framework.TestCase; - -import org.easymock.MockControl; -import org.springframework.batch.sample.dao.CustomerCreditDao; -import org.springframework.batch.sample.domain.CustomerCredit; -import org.springframework.batch.sample.item.writer.CustomerCreditIncreaseWriter; - -/** - * Tests for {@link CustomerCreditIncreaseWriter}. - * - * @author Robert Kasanicky - */ -public class CustomerCreditIncreaseProcessorTests extends TestCase{ - - private CustomerCreditIncreaseWriter writer = new CustomerCreditIncreaseWriter(); - - private CustomerCreditDao outputSource; - private MockControl outputSourceControl = MockControl.createStrictControl(CustomerCreditDao.class); - - private CustomerCredit customerCredit = new CustomerCredit(); - - - protected void setUp() throws Exception { - customerCredit.setId(1); - customerCredit.setName("testCustomer"); - - outputSource = (CustomerCreditDao) outputSourceControl.getMock(); - writer.setCustomerCreditDao(outputSource); - } - - /** - * Increases customer's credit by fixed value - */ - public void testProcess() throws Exception { - BigDecimal oldCredit = new BigDecimal(10.54); - customerCredit.setCredit(oldCredit); - - outputSource.writeCredit(customerCredit); - outputSourceControl.setVoidCallable(); - outputSourceControl.replay(); - - writer.write(customerCredit); - - BigDecimal newCredit = customerCredit.getCredit(); - BigDecimal expectedCredit = oldCredit.add(CustomerCreditIncreaseWriter.FIXED_AMOUNT); - assertTrue(newCredit.compareTo(expectedCredit) == 0); - outputSourceControl.verify(); - } -} +package org.springframework.batch.sample.item.writer; + +import java.math.BigDecimal; + +import junit.framework.TestCase; + +import org.easymock.MockControl; +import org.springframework.batch.sample.dao.CustomerCreditDao; +import org.springframework.batch.sample.domain.CustomerCredit; +import org.springframework.batch.sample.item.writer.CustomerCreditIncreaseWriter; + +/** + * Tests for {@link CustomerCreditIncreaseWriter}. + * + * @author Robert Kasanicky + */ +public class CustomerCreditIncreaseProcessorTests extends TestCase{ + + private CustomerCreditIncreaseWriter writer = new CustomerCreditIncreaseWriter(); + + private CustomerCreditDao outputSource; + private MockControl outputSourceControl = MockControl.createStrictControl(CustomerCreditDao.class); + + private CustomerCredit customerCredit = new CustomerCredit(); + + + protected void setUp() throws Exception { + customerCredit.setId(1); + customerCredit.setName("testCustomer"); + + outputSource = (CustomerCreditDao) outputSourceControl.getMock(); + writer.setCustomerCreditDao(outputSource); + } + + /** + * Increases customer's credit by fixed value + */ + public void testProcess() throws Exception { + BigDecimal oldCredit = new BigDecimal(10.54); + customerCredit.setCredit(oldCredit); + + outputSource.writeCredit(customerCredit); + outputSourceControl.setVoidCallable(); + outputSourceControl.replay(); + + writer.write(customerCredit); + + BigDecimal newCredit = customerCredit.getCredit(); + BigDecimal expectedCredit = oldCredit.add(CustomerCreditIncreaseWriter.FIXED_AMOUNT); + assertTrue(newCredit.compareTo(expectedCredit) == 0); + outputSourceControl.verify(); + } +} diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/item/writer/CustomerCreditUpdateProcessorTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/item/writer/CustomerCreditUpdateProcessorTests.java index 7890967d2c..29b88c9098 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/item/writer/CustomerCreditUpdateProcessorTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/item/writer/CustomerCreditUpdateProcessorTests.java @@ -1,57 +1,57 @@ -package org.springframework.batch.sample.item.writer; - -import java.math.BigDecimal; - -import junit.framework.TestCase; - -import org.easymock.MockControl; -import org.springframework.batch.sample.dao.CustomerCreditDao; -import org.springframework.batch.sample.domain.CustomerCredit; -import org.springframework.batch.sample.item.writer.CustomerCreditUpdateWriter; - -public class CustomerCreditUpdateProcessorTests extends TestCase { - - private MockControl daoControl; - private CustomerCreditDao dao; - private CustomerCreditUpdateWriter writer; - private static final double CREDIT_FILTER = 355.0; - - public void setUp() { - //create mock writer - daoControl = MockControl.createControl(CustomerCreditDao.class); - dao = (CustomerCreditDao) daoControl.getMock(); - //create processor, set writer and credit filter - writer = new CustomerCreditUpdateWriter(); - writer.setWriter(dao); - writer.setCreditFilter(CREDIT_FILTER); - } - - public void testProcess() throws Exception { - - //set-up mock writer - no writer's method should be called - daoControl.replay(); - - //create credit and set it to same value as credit filter - CustomerCredit credit = new CustomerCredit(); - credit.setCredit(new BigDecimal(CREDIT_FILTER)); - //call tested method - writer.write(credit); - //verify method calls - no method should be called - //because credit is not greater then credit filter - daoControl.verify(); - - //change credit to be greater than credit filter - credit.setCredit(new BigDecimal(CREDIT_FILTER + 1)); - //reset and set-up writer - write method is expected to be called - daoControl.reset(); - dao.writeCredit(credit); - daoControl.replay(); - - //call tested method - writer.write(credit); - - //verify method calls - daoControl.verify(); - } - -} +package org.springframework.batch.sample.item.writer; + +import java.math.BigDecimal; + +import junit.framework.TestCase; + +import org.easymock.MockControl; +import org.springframework.batch.sample.dao.CustomerCreditDao; +import org.springframework.batch.sample.domain.CustomerCredit; +import org.springframework.batch.sample.item.writer.CustomerCreditUpdateWriter; + +public class CustomerCreditUpdateProcessorTests extends TestCase { + + private MockControl daoControl; + private CustomerCreditDao dao; + private CustomerCreditUpdateWriter writer; + private static final double CREDIT_FILTER = 355.0; + + public void setUp() { + //create mock writer + daoControl = MockControl.createControl(CustomerCreditDao.class); + dao = (CustomerCreditDao) daoControl.getMock(); + //create processor, set writer and credit filter + writer = new CustomerCreditUpdateWriter(); + writer.setWriter(dao); + writer.setCreditFilter(CREDIT_FILTER); + } + + public void testProcess() throws Exception { + + //set-up mock writer - no writer's method should be called + daoControl.replay(); + + //create credit and set it to same value as credit filter + CustomerCredit credit = new CustomerCredit(); + credit.setCredit(new BigDecimal(CREDIT_FILTER)); + //call tested method + writer.write(credit); + //verify method calls - no method should be called + //because credit is not greater then credit filter + daoControl.verify(); + + //change credit to be greater than credit filter + credit.setCredit(new BigDecimal(CREDIT_FILTER + 1)); + //reset and set-up writer - write method is expected to be called + daoControl.reset(); + dao.writeCredit(credit); + daoControl.replay(); + + //call tested method + writer.write(credit); + + //verify method calls + daoControl.verify(); + } + +} diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/item/writer/CustomerUpdateProcessorTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/item/writer/CustomerUpdateProcessorTests.java index 5526d878b2..5e802c0513 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/item/writer/CustomerUpdateProcessorTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/item/writer/CustomerUpdateProcessorTests.java @@ -1,36 +1,36 @@ -package org.springframework.batch.sample.item.writer; - -import java.math.BigDecimal; - -import junit.framework.TestCase; - -import org.springframework.batch.sample.dao.JdbcCustomerDebitDao; -import org.springframework.batch.sample.domain.CustomerDebit; -import org.springframework.batch.sample.domain.Trade; -import org.springframework.batch.sample.item.writer.CustomerUpdateWriter; - -public class CustomerUpdateProcessorTests extends TestCase { - - public void testProcess() { - - //create trade object - Trade trade = new Trade(); - trade.setCustomer("testCustomerName"); - trade.setPrice(new BigDecimal(123.0)); - - //create dao - JdbcCustomerDebitDao dao = new JdbcCustomerDebitDao() { - public void write(CustomerDebit customerDebit) { - assertEquals("testCustomerName", customerDebit.getName()); - assertEquals(new BigDecimal(123.0), customerDebit.getDebit()); - } - }; - - //create processor and set dao - CustomerUpdateWriter processor = new CustomerUpdateWriter(); - processor.setDao(dao); - - //call tested method - see asserts in dao.write() method - processor.write(trade); - } -} +package org.springframework.batch.sample.item.writer; + +import java.math.BigDecimal; + +import junit.framework.TestCase; + +import org.springframework.batch.sample.dao.JdbcCustomerDebitDao; +import org.springframework.batch.sample.domain.CustomerDebit; +import org.springframework.batch.sample.domain.Trade; +import org.springframework.batch.sample.item.writer.CustomerUpdateWriter; + +public class CustomerUpdateProcessorTests extends TestCase { + + public void testProcess() { + + //create trade object + Trade trade = new Trade(); + trade.setCustomer("testCustomerName"); + trade.setPrice(new BigDecimal(123.0)); + + //create dao + JdbcCustomerDebitDao dao = new JdbcCustomerDebitDao() { + public void write(CustomerDebit customerDebit) { + assertEquals("testCustomerName", customerDebit.getName()); + assertEquals(new BigDecimal(123.0), customerDebit.getDebit()); + } + }; + + //create processor and set dao + CustomerUpdateWriter processor = new CustomerUpdateWriter(); + processor.setDao(dao); + + //call tested method - see asserts in dao.write() method + processor.write(trade); + } +} diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/item/writer/OrderWriterTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/item/writer/OrderWriterTests.java index 6b1ed49827..533543a896 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/item/writer/OrderWriterTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/item/writer/OrderWriterTests.java @@ -1,54 +1,54 @@ -package org.springframework.batch.sample.item.writer; - -import junit.framework.TestCase; - -import org.easymock.MockControl; -import org.springframework.batch.io.exception.InfrastructureException; -import org.springframework.batch.item.ItemWriter; -import org.springframework.batch.sample.domain.Order; -import org.springframework.batch.sample.item.writer.OrderWriter; - -public class OrderWriterTests extends TestCase { - - private MockControl writerControl; - private OrderWriter processor; - private ItemWriter writer; - - public void setUp() { - - //create mock writer - writerControl = MockControl.createControl(ItemWriter.class); - writer = (ItemWriter)writerControl.getMock(); - - //create processor - processor = new OrderWriter(); - processor.setDelegate(writer); - } - - public void testProcess() throws Exception { - - Order order = new Order(); - //set-up mock writer - writer.write(order); - writerControl.replay(); - - //call tested method - processor.write(order); - - //verify method calls - writerControl.verify(); - } - - public void testProcessWithException() throws Exception { - - writerControl.replay(); - //call tested method - try { - processor.write(this); - fail("Batch critical exception was expected"); - } catch (InfrastructureException bce) { - assertTrue(true); - } - writerControl.verify(); - } -} +package org.springframework.batch.sample.item.writer; + +import junit.framework.TestCase; + +import org.easymock.MockControl; +import org.springframework.batch.io.exception.InfrastructureException; +import org.springframework.batch.item.ItemWriter; +import org.springframework.batch.sample.domain.Order; +import org.springframework.batch.sample.item.writer.OrderWriter; + +public class OrderWriterTests extends TestCase { + + private MockControl writerControl; + private OrderWriter processor; + private ItemWriter writer; + + public void setUp() { + + //create mock writer + writerControl = MockControl.createControl(ItemWriter.class); + writer = (ItemWriter)writerControl.getMock(); + + //create processor + processor = new OrderWriter(); + processor.setDelegate(writer); + } + + public void testProcess() throws Exception { + + Order order = new Order(); + //set-up mock writer + writer.write(order); + writerControl.replay(); + + //call tested method + processor.write(order); + + //verify method calls + writerControl.verify(); + } + + public void testProcessWithException() throws Exception { + + writerControl.replay(); + //call tested method + try { + processor.write(this); + fail("Batch critical exception was expected"); + } catch (InfrastructureException bce) { + assertTrue(true); + } + writerControl.verify(); + } +} diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/item/writer/RetrySampleItemWriterTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/item/writer/RetrySampleItemWriterTests.java index bd2e74d6d2..8f7efede04 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/item/writer/RetrySampleItemWriterTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/item/writer/RetrySampleItemWriterTests.java @@ -1,35 +1,35 @@ -package org.springframework.batch.sample.item.writer; - -import junit.framework.TestCase; - -/** - * Tests for {@link RetrySampleItemWriter}. - * - * @author Robert Kasanicky - */ -public class RetrySampleItemWriterTests extends TestCase { - - private RetrySampleItemWriter processor = new RetrySampleItemWriter(); - - /** - * Processing throws exception on 2nd and 3rd call. - */ - public void testProcess() throws Exception { - Object item = null; - processor.write(item); - - for (int i = 0; i < 2; i++) { - try { - processor.write(item); - fail(); - } - catch (RuntimeException e) { - // expected - } - } - - processor.write(item); - - assertEquals(4, processor.getCounter()); - } -} +package org.springframework.batch.sample.item.writer; + +import junit.framework.TestCase; + +/** + * Tests for {@link RetrySampleItemWriter}. + * + * @author Robert Kasanicky + */ +public class RetrySampleItemWriterTests extends TestCase { + + private RetrySampleItemWriter processor = new RetrySampleItemWriter(); + + /** + * Processing throws exception on 2nd and 3rd call. + */ + public void testProcess() throws Exception { + Object item = null; + processor.write(item); + + for (int i = 0; i < 2; i++) { + try { + processor.write(item); + fail(); + } + catch (RuntimeException e) { + // expected + } + } + + processor.write(item); + + assertEquals(4, processor.getCounter()); + } +} diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/item/writer/TradeProcessorTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/item/writer/TradeProcessorTests.java index 9029420478..da3a28f549 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/item/writer/TradeProcessorTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/item/writer/TradeProcessorTests.java @@ -1,48 +1,48 @@ -package org.springframework.batch.sample.item.writer; - -import junit.framework.TestCase; - -import org.easymock.MockControl; -import org.springframework.batch.sample.dao.TradeDao; -import org.springframework.batch.sample.domain.Trade; -import org.springframework.batch.sample.item.writer.TradeWriter; - -public class TradeProcessorTests extends TestCase { - - private MockControl writerControl; - private TradeDao writer; - private TradeWriter processor; - - public void setUp() { - - //create mock writer - writerControl = MockControl.createControl(TradeDao.class); - writer = (TradeDao)writerControl.getMock(); - - //create processor - processor = new TradeWriter(); - processor.setDao(writer); - } - - public void testProcess() { - - Trade trade = new Trade(); - //set-up mock writer - writer.writeTrade(trade); - writerControl.replay(); - - //call tested method - processor.write(trade); - - //verify method calls - writerControl.verify(); - } - - public void testProcessNonTradeObject() { - - writerControl.replay(); - //call tested method - processor.write(this); - writerControl.verify(); - } -} +package org.springframework.batch.sample.item.writer; + +import junit.framework.TestCase; + +import org.easymock.MockControl; +import org.springframework.batch.sample.dao.TradeDao; +import org.springframework.batch.sample.domain.Trade; +import org.springframework.batch.sample.item.writer.TradeWriter; + +public class TradeProcessorTests extends TestCase { + + private MockControl writerControl; + private TradeDao writer; + private TradeWriter processor; + + public void setUp() { + + //create mock writer + writerControl = MockControl.createControl(TradeDao.class); + writer = (TradeDao)writerControl.getMock(); + + //create processor + processor = new TradeWriter(); + processor.setDao(writer); + } + + public void testProcess() { + + Trade trade = new Trade(); + //set-up mock writer + writer.writeTrade(trade); + writerControl.replay(); + + //call tested method + processor.write(trade); + + //verify method calls + writerControl.verify(); + } + + public void testProcessNonTradeObject() { + + writerControl.replay(); + //call tested method + processor.write(this); + writerControl.verify(); + } +} diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/mapping/AbstractFieldSetMapperTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/mapping/AbstractFieldSetMapperTests.java index bc2972d7fe..a88139ee8c 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/mapping/AbstractFieldSetMapperTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/mapping/AbstractFieldSetMapperTests.java @@ -1,41 +1,41 @@ -package org.springframework.batch.sample.mapping; - -import org.springframework.batch.io.file.mapping.FieldSet; -import org.springframework.batch.io.file.mapping.FieldSetMapper; - -import junit.framework.TestCase; - -/** - * Encapsulates basic logic for testing custom {@link FieldSetMapper} implementations. - * - * @author Robert Kasanicky - */ -public abstract class AbstractFieldSetMapperTests extends TestCase { - - /** - * @return FieldSet used for mapping - */ - protected abstract FieldSet fieldSet(); - - /** - * @return domain object excepted as a result of mapping the FieldSet - * returned by this.fieldSet() - */ - protected abstract Object expectedDomainObject(); - - /** - * @return mapper which takes this.fieldSet() and maps it to - * domain object. - */ - protected abstract FieldSetMapper fieldSetMapper(); - - - /** - * Regular usage scenario. - * Assumes the domain object implements sensible equals(Object other) - */ - public void testRegularUse() { - assertEquals(expectedDomainObject(), fieldSetMapper().mapLine(fieldSet())); - } - -} +package org.springframework.batch.sample.mapping; + +import org.springframework.batch.io.file.mapping.FieldSet; +import org.springframework.batch.io.file.mapping.FieldSetMapper; + +import junit.framework.TestCase; + +/** + * Encapsulates basic logic for testing custom {@link FieldSetMapper} implementations. + * + * @author Robert Kasanicky + */ +public abstract class AbstractFieldSetMapperTests extends TestCase { + + /** + * @return FieldSet used for mapping + */ + protected abstract FieldSet fieldSet(); + + /** + * @return domain object excepted as a result of mapping the FieldSet + * returned by this.fieldSet() + */ + protected abstract Object expectedDomainObject(); + + /** + * @return mapper which takes this.fieldSet() and maps it to + * domain object. + */ + protected abstract FieldSetMapper fieldSetMapper(); + + + /** + * Regular usage scenario. + * Assumes the domain object implements sensible equals(Object other) + */ + public void testRegularUse() { + assertEquals(expectedDomainObject(), fieldSetMapper().mapLine(fieldSet())); + } + +} diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/mapping/AbstractRowMapperTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/mapping/AbstractRowMapperTests.java index bfbb2b3d49..7d671a79b9 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/mapping/AbstractRowMapperTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/mapping/AbstractRowMapperTests.java @@ -1,51 +1,51 @@ -package org.springframework.batch.sample.mapping; - -import java.sql.ResultSet; -import java.sql.SQLException; - -import junit.framework.TestCase; - -import org.easymock.MockControl; -import org.springframework.jdbc.core.RowMapper; - -/** - * Encapsulates logic for testing custom {@link RowMapper} implementations. - * - * @author Robert Kasanicky - */ -public abstract class AbstractRowMapperTests extends TestCase { - - //row number should be irrelevant - private static final int IGNORED_ROW_NUMBER = 0; - - //mock result set - private MockControl rsControl = MockControl.createControl(ResultSet.class); - private ResultSet rs = (ResultSet) rsControl.getMock(); - - /** - * @return Expected result of mapping the mock ResultSet by - * the mapper being tested. - */ - abstract protected Object expectedDomainObject(); - - /** - * @return RowMapper implementation that is being tested. - */ - abstract protected RowMapper rowMapper(); - - /** - * Define the behaviour of mock ResultSet. - */ - abstract protected void setUpResultSetMock(ResultSet rs, MockControl rsControl) throws SQLException; - - - /** - * Regular usage scenario. - */ - public void testRegularUse() throws SQLException { - setUpResultSetMock(rs, rsControl); - rsControl.replay(); - - assertEquals(expectedDomainObject(), rowMapper().mapRow(rs, IGNORED_ROW_NUMBER)); - } -} +package org.springframework.batch.sample.mapping; + +import java.sql.ResultSet; +import java.sql.SQLException; + +import junit.framework.TestCase; + +import org.easymock.MockControl; +import org.springframework.jdbc.core.RowMapper; + +/** + * Encapsulates logic for testing custom {@link RowMapper} implementations. + * + * @author Robert Kasanicky + */ +public abstract class AbstractRowMapperTests extends TestCase { + + //row number should be irrelevant + private static final int IGNORED_ROW_NUMBER = 0; + + //mock result set + private MockControl rsControl = MockControl.createControl(ResultSet.class); + private ResultSet rs = (ResultSet) rsControl.getMock(); + + /** + * @return Expected result of mapping the mock ResultSet by + * the mapper being tested. + */ + abstract protected Object expectedDomainObject(); + + /** + * @return RowMapper implementation that is being tested. + */ + abstract protected RowMapper rowMapper(); + + /** + * Define the behaviour of mock ResultSet. + */ + abstract protected void setUpResultSetMock(ResultSet rs, MockControl rsControl) throws SQLException; + + + /** + * Regular usage scenario. + */ + public void testRegularUse() throws SQLException { + setUpResultSetMock(rs, rsControl); + rsControl.replay(); + + assertEquals(expectedDomainObject(), rowMapper().mapRow(rs, IGNORED_ROW_NUMBER)); + } +} diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/mapping/AddressFieldSetMapperTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/mapping/AddressFieldSetMapperTests.java index 644475b1b7..8a89fc941a 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/mapping/AddressFieldSetMapperTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/mapping/AddressFieldSetMapperTests.java @@ -1,53 +1,53 @@ -package org.springframework.batch.sample.mapping; - -import org.springframework.batch.io.file.mapping.DefaultFieldSet; -import org.springframework.batch.io.file.mapping.FieldSet; -import org.springframework.batch.io.file.mapping.FieldSetMapper; -import org.springframework.batch.sample.domain.Address; -import org.springframework.batch.sample.mapping.AddressFieldSetMapper; - - -public class AddressFieldSetMapperTests extends AbstractFieldSetMapperTests { - - private static final String ADDRESSEE = "Jan Hrach"; - private static final String ADDRESS_LINE_1 = "Plynarenska 7c"; - private static final String ADDRESS_LINE_2 = ""; - private static final String CITY = "Bratislava"; - private static final String STATE = ""; - private static final String COUNTRY = "Slovakia"; - private static final String ZIP_CODE = "80000"; - - - - protected Object expectedDomainObject() { - Address address = new Address(); - address.setAddressee(ADDRESSEE); - address.setAddrLine1(ADDRESS_LINE_1); - address.setAddrLine2(ADDRESS_LINE_2); - address.setCity(CITY); - address.setState(STATE); - address.setCountry(COUNTRY); - address.setZipCode(ZIP_CODE); - return address; - } - - protected FieldSet fieldSet() { - String[] tokens = - new String[]{ADDRESSEE, ADDRESS_LINE_1, ADDRESS_LINE_2, CITY, STATE, COUNTRY, ZIP_CODE}; - String[] columnNames = - new String[]{ - AddressFieldSetMapper.ADDRESSEE_COLUMN, - AddressFieldSetMapper.ADDRESS_LINE1_COLUMN, - AddressFieldSetMapper.ADDRESS_LINE2_COLUMN, - AddressFieldSetMapper.CITY_COLUMN, - AddressFieldSetMapper.STATE_COLUMN, - AddressFieldSetMapper.COUNTRY_COLUMN, - AddressFieldSetMapper.ZIP_CODE_COLUMN }; - - return new DefaultFieldSet(tokens, columnNames); - } - - protected FieldSetMapper fieldSetMapper() { - return new AddressFieldSetMapper(); - } -} +package org.springframework.batch.sample.mapping; + +import org.springframework.batch.io.file.mapping.DefaultFieldSet; +import org.springframework.batch.io.file.mapping.FieldSet; +import org.springframework.batch.io.file.mapping.FieldSetMapper; +import org.springframework.batch.sample.domain.Address; +import org.springframework.batch.sample.mapping.AddressFieldSetMapper; + + +public class AddressFieldSetMapperTests extends AbstractFieldSetMapperTests { + + private static final String ADDRESSEE = "Jan Hrach"; + private static final String ADDRESS_LINE_1 = "Plynarenska 7c"; + private static final String ADDRESS_LINE_2 = ""; + private static final String CITY = "Bratislava"; + private static final String STATE = ""; + private static final String COUNTRY = "Slovakia"; + private static final String ZIP_CODE = "80000"; + + + + protected Object expectedDomainObject() { + Address address = new Address(); + address.setAddressee(ADDRESSEE); + address.setAddrLine1(ADDRESS_LINE_1); + address.setAddrLine2(ADDRESS_LINE_2); + address.setCity(CITY); + address.setState(STATE); + address.setCountry(COUNTRY); + address.setZipCode(ZIP_CODE); + return address; + } + + protected FieldSet fieldSet() { + String[] tokens = + new String[]{ADDRESSEE, ADDRESS_LINE_1, ADDRESS_LINE_2, CITY, STATE, COUNTRY, ZIP_CODE}; + String[] columnNames = + new String[]{ + AddressFieldSetMapper.ADDRESSEE_COLUMN, + AddressFieldSetMapper.ADDRESS_LINE1_COLUMN, + AddressFieldSetMapper.ADDRESS_LINE2_COLUMN, + AddressFieldSetMapper.CITY_COLUMN, + AddressFieldSetMapper.STATE_COLUMN, + AddressFieldSetMapper.COUNTRY_COLUMN, + AddressFieldSetMapper.ZIP_CODE_COLUMN }; + + return new DefaultFieldSet(tokens, columnNames); + } + + protected FieldSetMapper fieldSetMapper() { + return new AddressFieldSetMapper(); + } +} diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/mapping/BillingFieldSetMapperTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/mapping/BillingFieldSetMapperTests.java index 030d137be2..3a1d251fd4 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/mapping/BillingFieldSetMapperTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/mapping/BillingFieldSetMapperTests.java @@ -1,34 +1,34 @@ -package org.springframework.batch.sample.mapping; - -import org.springframework.batch.io.file.mapping.DefaultFieldSet; -import org.springframework.batch.io.file.mapping.FieldSet; -import org.springframework.batch.io.file.mapping.FieldSetMapper; -import org.springframework.batch.sample.domain.BillingInfo; - -public class BillingFieldSetMapperTests extends AbstractFieldSetMapperTests{ - - private static final String PAYMENT_ID = "777"; - private static final String PAYMENT_DESC = "My last penny"; - - protected Object expectedDomainObject() { - BillingInfo bInfo = new BillingInfo(); - bInfo.setPaymentDesc(PAYMENT_DESC); - bInfo.setPaymentId(PAYMENT_ID); - return bInfo; - } - - protected FieldSet fieldSet() { - String[] tokens = new String[]{ - PAYMENT_ID, - PAYMENT_DESC}; - String[] columnNames = new String[]{ - BillingFieldSetMapper.PAYMENT_TYPE_ID_COLUMN, - BillingFieldSetMapper.PAYMENT_DESC_COLUMN}; - return new DefaultFieldSet(tokens, columnNames); - } - - protected FieldSetMapper fieldSetMapper() { - return new BillingFieldSetMapper(); - } - -} +package org.springframework.batch.sample.mapping; + +import org.springframework.batch.io.file.mapping.DefaultFieldSet; +import org.springframework.batch.io.file.mapping.FieldSet; +import org.springframework.batch.io.file.mapping.FieldSetMapper; +import org.springframework.batch.sample.domain.BillingInfo; + +public class BillingFieldSetMapperTests extends AbstractFieldSetMapperTests{ + + private static final String PAYMENT_ID = "777"; + private static final String PAYMENT_DESC = "My last penny"; + + protected Object expectedDomainObject() { + BillingInfo bInfo = new BillingInfo(); + bInfo.setPaymentDesc(PAYMENT_DESC); + bInfo.setPaymentId(PAYMENT_ID); + return bInfo; + } + + protected FieldSet fieldSet() { + String[] tokens = new String[]{ + PAYMENT_ID, + PAYMENT_DESC}; + String[] columnNames = new String[]{ + BillingFieldSetMapper.PAYMENT_TYPE_ID_COLUMN, + BillingFieldSetMapper.PAYMENT_DESC_COLUMN}; + return new DefaultFieldSet(tokens, columnNames); + } + + protected FieldSetMapper fieldSetMapper() { + return new BillingFieldSetMapper(); + } + +} diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/mapping/CustomerCreditRowMapperTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/mapping/CustomerCreditRowMapperTests.java index eac3aad86f..d7d7a8fc52 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/mapping/CustomerCreditRowMapperTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/mapping/CustomerCreditRowMapperTests.java @@ -1,42 +1,42 @@ -package org.springframework.batch.sample.mapping; - -import java.math.BigDecimal; -import java.sql.ResultSet; -import java.sql.SQLException; - -import org.easymock.MockControl; -import org.springframework.batch.sample.domain.CustomerCredit; -import org.springframework.batch.sample.mapping.CustomerCreditRowMapper; -import org.springframework.jdbc.core.RowMapper; - -public class CustomerCreditRowMapperTests extends AbstractRowMapperTests { - - /** - * - */ - private static final int ID = 12; - private static final String CUSTOMER = "Jozef Mak"; - private static final BigDecimal CREDIT = new BigDecimal(0.1); - - protected Object expectedDomainObject() { - CustomerCredit credit = new CustomerCredit(); - credit.setId(ID); - credit.setCredit(CREDIT); - credit.setName(CUSTOMER); - return credit; - } - - protected RowMapper rowMapper() { - return new CustomerCreditRowMapper(); - } - - protected void setUpResultSetMock(ResultSet rs, MockControl rsControl) throws SQLException { - rs.getInt(CustomerCreditRowMapper.ID_COLUMN); - rsControl.setReturnValue(ID); - rs.getString(CustomerCreditRowMapper.NAME_COLUMN); - rsControl.setReturnValue(CUSTOMER); - rs.getBigDecimal(CustomerCreditRowMapper.CREDIT_COLUMN); - rsControl.setReturnValue(CREDIT); - } - -} +package org.springframework.batch.sample.mapping; + +import java.math.BigDecimal; +import java.sql.ResultSet; +import java.sql.SQLException; + +import org.easymock.MockControl; +import org.springframework.batch.sample.domain.CustomerCredit; +import org.springframework.batch.sample.mapping.CustomerCreditRowMapper; +import org.springframework.jdbc.core.RowMapper; + +public class CustomerCreditRowMapperTests extends AbstractRowMapperTests { + + /** + * + */ + private static final int ID = 12; + private static final String CUSTOMER = "Jozef Mak"; + private static final BigDecimal CREDIT = new BigDecimal(0.1); + + protected Object expectedDomainObject() { + CustomerCredit credit = new CustomerCredit(); + credit.setId(ID); + credit.setCredit(CREDIT); + credit.setName(CUSTOMER); + return credit; + } + + protected RowMapper rowMapper() { + return new CustomerCreditRowMapper(); + } + + protected void setUpResultSetMock(ResultSet rs, MockControl rsControl) throws SQLException { + rs.getInt(CustomerCreditRowMapper.ID_COLUMN); + rsControl.setReturnValue(ID); + rs.getString(CustomerCreditRowMapper.NAME_COLUMN); + rsControl.setReturnValue(CUSTOMER); + rs.getBigDecimal(CustomerCreditRowMapper.CREDIT_COLUMN); + rsControl.setReturnValue(CREDIT); + } + +} diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/mapping/CustomerFieldSetMapperTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/mapping/CustomerFieldSetMapperTests.java index 6c6138ee11..e66a0b4d6d 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/mapping/CustomerFieldSetMapperTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/mapping/CustomerFieldSetMapperTests.java @@ -1,57 +1,57 @@ -package org.springframework.batch.sample.mapping; - -import org.springframework.batch.io.file.mapping.DefaultFieldSet; -import org.springframework.batch.io.file.mapping.FieldSet; -import org.springframework.batch.io.file.mapping.FieldSetMapper; -import org.springframework.batch.sample.domain.Customer; -import org.springframework.batch.sample.mapping.CustomerFieldSetMapper; - -public class CustomerFieldSetMapperTests extends AbstractFieldSetMapperTests { - - private static final boolean BUSINESS_CUSTOMER = false; - //private static final String COMPANY_NAME = "Accenture"; - private static final String FIRST_NAME = "Jan"; - private static final String LAST_NAME = "Hrach"; - private static final String MIDDLE_NAME = ""; - private static final boolean REGISTERED = true; - private static final long REG_ID = 1; - private static final boolean VIP = true; - - protected Object expectedDomainObject() { - Customer cs = new Customer(); - cs.setBusinessCustomer(BUSINESS_CUSTOMER); - cs.setFirstName(FIRST_NAME); - cs.setLastName(LAST_NAME); - cs.setMiddleName(MIDDLE_NAME); - cs.setRegistered(REGISTERED); - cs.setRegistrationId(REG_ID); - cs.setVip(VIP); - return cs; - } - - protected FieldSet fieldSet() { - String[] tokens = new String[]{ - Customer.LINE_ID_NON_BUSINESS_CUST, - FIRST_NAME, - LAST_NAME, - MIDDLE_NAME, - CustomerFieldSetMapper.TRUE_SYMBOL, - String.valueOf(REG_ID), - CustomerFieldSetMapper.TRUE_SYMBOL}; - String[] columnNames = new String[]{ - CustomerFieldSetMapper.LINE_ID_COLUMN, - CustomerFieldSetMapper.FIRST_NAME_COLUMN, - CustomerFieldSetMapper.LAST_NAME_COLUMN, - CustomerFieldSetMapper.MIDDLE_NAME_COLUMN, - CustomerFieldSetMapper.REGISTERED_COLUMN, - CustomerFieldSetMapper.REG_ID_COLUMN, - CustomerFieldSetMapper.VIP_COLUMN}; - - return new DefaultFieldSet(tokens, columnNames); - } - - protected FieldSetMapper fieldSetMapper() { - return new CustomerFieldSetMapper(); - } - -} +package org.springframework.batch.sample.mapping; + +import org.springframework.batch.io.file.mapping.DefaultFieldSet; +import org.springframework.batch.io.file.mapping.FieldSet; +import org.springframework.batch.io.file.mapping.FieldSetMapper; +import org.springframework.batch.sample.domain.Customer; +import org.springframework.batch.sample.mapping.CustomerFieldSetMapper; + +public class CustomerFieldSetMapperTests extends AbstractFieldSetMapperTests { + + private static final boolean BUSINESS_CUSTOMER = false; + //private static final String COMPANY_NAME = "Accenture"; + private static final String FIRST_NAME = "Jan"; + private static final String LAST_NAME = "Hrach"; + private static final String MIDDLE_NAME = ""; + private static final boolean REGISTERED = true; + private static final long REG_ID = 1; + private static final boolean VIP = true; + + protected Object expectedDomainObject() { + Customer cs = new Customer(); + cs.setBusinessCustomer(BUSINESS_CUSTOMER); + cs.setFirstName(FIRST_NAME); + cs.setLastName(LAST_NAME); + cs.setMiddleName(MIDDLE_NAME); + cs.setRegistered(REGISTERED); + cs.setRegistrationId(REG_ID); + cs.setVip(VIP); + return cs; + } + + protected FieldSet fieldSet() { + String[] tokens = new String[]{ + Customer.LINE_ID_NON_BUSINESS_CUST, + FIRST_NAME, + LAST_NAME, + MIDDLE_NAME, + CustomerFieldSetMapper.TRUE_SYMBOL, + String.valueOf(REG_ID), + CustomerFieldSetMapper.TRUE_SYMBOL}; + String[] columnNames = new String[]{ + CustomerFieldSetMapper.LINE_ID_COLUMN, + CustomerFieldSetMapper.FIRST_NAME_COLUMN, + CustomerFieldSetMapper.LAST_NAME_COLUMN, + CustomerFieldSetMapper.MIDDLE_NAME_COLUMN, + CustomerFieldSetMapper.REGISTERED_COLUMN, + CustomerFieldSetMapper.REG_ID_COLUMN, + CustomerFieldSetMapper.VIP_COLUMN}; + + return new DefaultFieldSet(tokens, columnNames); + } + + protected FieldSetMapper fieldSetMapper() { + return new CustomerFieldSetMapper(); + } + +} diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/mapping/HeaderFieldSetMapperTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/mapping/HeaderFieldSetMapperTests.java index 7d3f8769f1..3ec5946b00 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/mapping/HeaderFieldSetMapperTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/mapping/HeaderFieldSetMapperTests.java @@ -1,41 +1,41 @@ -package org.springframework.batch.sample.mapping; - -import java.util.Calendar; - -import org.springframework.batch.io.file.mapping.DefaultFieldSet; -import org.springframework.batch.io.file.mapping.FieldSet; -import org.springframework.batch.io.file.mapping.FieldSetMapper; -import org.springframework.batch.sample.domain.Order; - -public class HeaderFieldSetMapperTests extends AbstractFieldSetMapperTests { - - private static final long ORDER_ID = 1; - private static final String DATE = "2007-01-01"; - - protected Object expectedDomainObject() { - Order order = new Order(); - Calendar calendar = Calendar.getInstance(); - calendar.set(2007, 0, 1, 0, 0, 0); - calendar.set(Calendar.MILLISECOND, 0); - order.setOrderDate(calendar.getTime()); - order.setOrderId(ORDER_ID); - return order; - } - - protected FieldSet fieldSet() { - String[] tokens = new String[]{ - String.valueOf(ORDER_ID), - DATE - }; - String[] columnNames = new String[]{ - HeaderFieldSetMapper.ORDER_ID_COLUMN, - HeaderFieldSetMapper.ORDER_DATE_COLUMN - }; - return new DefaultFieldSet(tokens, columnNames); - } - - protected FieldSetMapper fieldSetMapper() { - return new HeaderFieldSetMapper(); - } - -} +package org.springframework.batch.sample.mapping; + +import java.util.Calendar; + +import org.springframework.batch.io.file.mapping.DefaultFieldSet; +import org.springframework.batch.io.file.mapping.FieldSet; +import org.springframework.batch.io.file.mapping.FieldSetMapper; +import org.springframework.batch.sample.domain.Order; + +public class HeaderFieldSetMapperTests extends AbstractFieldSetMapperTests { + + private static final long ORDER_ID = 1; + private static final String DATE = "2007-01-01"; + + protected Object expectedDomainObject() { + Order order = new Order(); + Calendar calendar = Calendar.getInstance(); + calendar.set(2007, 0, 1, 0, 0, 0); + calendar.set(Calendar.MILLISECOND, 0); + order.setOrderDate(calendar.getTime()); + order.setOrderId(ORDER_ID); + return order; + } + + protected FieldSet fieldSet() { + String[] tokens = new String[]{ + String.valueOf(ORDER_ID), + DATE + }; + String[] columnNames = new String[]{ + HeaderFieldSetMapper.ORDER_ID_COLUMN, + HeaderFieldSetMapper.ORDER_DATE_COLUMN + }; + return new DefaultFieldSet(tokens, columnNames); + } + + protected FieldSetMapper fieldSetMapper() { + return new HeaderFieldSetMapper(); + } + +} diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/mapping/OrderItemFieldSetMapperTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/mapping/OrderItemFieldSetMapperTests.java index 7a513e7540..7b44dc18b4 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/mapping/OrderItemFieldSetMapperTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/mapping/OrderItemFieldSetMapperTests.java @@ -1,62 +1,62 @@ -package org.springframework.batch.sample.mapping; - -import java.math.BigDecimal; - -import org.springframework.batch.io.file.mapping.DefaultFieldSet; -import org.springframework.batch.io.file.mapping.FieldSet; -import org.springframework.batch.io.file.mapping.FieldSetMapper; -import org.springframework.batch.sample.domain.LineItem; - -public class OrderItemFieldSetMapperTests extends AbstractFieldSetMapperTests{ - - private static final BigDecimal DISCOUNT_AMOUNT = new BigDecimal(1); - private static final BigDecimal DISCOUNT_PERC = new BigDecimal(2); - private static final BigDecimal HANDLING_PRICE = new BigDecimal(3); - private static final long ITEM_ID = 4; - private static final BigDecimal PRICE = new BigDecimal(5); - private static final int QUANTITY = 6; - private static final BigDecimal SHIPPING_PRICE = new BigDecimal(7); - private static final BigDecimal TOTAL_PRICE = new BigDecimal(8); - - protected Object expectedDomainObject() { - LineItem item = new LineItem(); - item.setDiscountAmount(DISCOUNT_AMOUNT); - item.setDiscountPerc(DISCOUNT_PERC); - item.setHandlingPrice(HANDLING_PRICE); - item.setItemId(ITEM_ID); - item.setPrice(PRICE); - item.setQuantity(QUANTITY); - item.setShippingPrice(SHIPPING_PRICE); - item.setTotalPrice(TOTAL_PRICE); - return item; - } - - protected FieldSet fieldSet() { - String[] tokens = new String[]{ - String.valueOf(DISCOUNT_AMOUNT), - String.valueOf(DISCOUNT_PERC), - String.valueOf(HANDLING_PRICE), - String.valueOf(ITEM_ID), - String.valueOf(PRICE), - String.valueOf(QUANTITY), - String.valueOf(SHIPPING_PRICE), - String.valueOf(TOTAL_PRICE) - }; - String[] columnNames = new String[]{ - OrderItemFieldSetMapper.DISCOUNT_AMOUNT_COLUMN, - OrderItemFieldSetMapper.DISCOUNT_PERC_COLUMN, - OrderItemFieldSetMapper.HANDLING_PRICE_COLUMN, - OrderItemFieldSetMapper.ITEM_ID_COLUMN, - OrderItemFieldSetMapper.PRICE_COLUMN, - OrderItemFieldSetMapper.QUANTITY_COLUMN, - OrderItemFieldSetMapper.SHIPPING_PRICE_COLUMN, - OrderItemFieldSetMapper.TOTAL_PRICE_COLUMN - }; - return new DefaultFieldSet(tokens, columnNames); - } - - protected FieldSetMapper fieldSetMapper() { - return new OrderItemFieldSetMapper(); - } - -} +package org.springframework.batch.sample.mapping; + +import java.math.BigDecimal; + +import org.springframework.batch.io.file.mapping.DefaultFieldSet; +import org.springframework.batch.io.file.mapping.FieldSet; +import org.springframework.batch.io.file.mapping.FieldSetMapper; +import org.springframework.batch.sample.domain.LineItem; + +public class OrderItemFieldSetMapperTests extends AbstractFieldSetMapperTests{ + + private static final BigDecimal DISCOUNT_AMOUNT = new BigDecimal(1); + private static final BigDecimal DISCOUNT_PERC = new BigDecimal(2); + private static final BigDecimal HANDLING_PRICE = new BigDecimal(3); + private static final long ITEM_ID = 4; + private static final BigDecimal PRICE = new BigDecimal(5); + private static final int QUANTITY = 6; + private static final BigDecimal SHIPPING_PRICE = new BigDecimal(7); + private static final BigDecimal TOTAL_PRICE = new BigDecimal(8); + + protected Object expectedDomainObject() { + LineItem item = new LineItem(); + item.setDiscountAmount(DISCOUNT_AMOUNT); + item.setDiscountPerc(DISCOUNT_PERC); + item.setHandlingPrice(HANDLING_PRICE); + item.setItemId(ITEM_ID); + item.setPrice(PRICE); + item.setQuantity(QUANTITY); + item.setShippingPrice(SHIPPING_PRICE); + item.setTotalPrice(TOTAL_PRICE); + return item; + } + + protected FieldSet fieldSet() { + String[] tokens = new String[]{ + String.valueOf(DISCOUNT_AMOUNT), + String.valueOf(DISCOUNT_PERC), + String.valueOf(HANDLING_PRICE), + String.valueOf(ITEM_ID), + String.valueOf(PRICE), + String.valueOf(QUANTITY), + String.valueOf(SHIPPING_PRICE), + String.valueOf(TOTAL_PRICE) + }; + String[] columnNames = new String[]{ + OrderItemFieldSetMapper.DISCOUNT_AMOUNT_COLUMN, + OrderItemFieldSetMapper.DISCOUNT_PERC_COLUMN, + OrderItemFieldSetMapper.HANDLING_PRICE_COLUMN, + OrderItemFieldSetMapper.ITEM_ID_COLUMN, + OrderItemFieldSetMapper.PRICE_COLUMN, + OrderItemFieldSetMapper.QUANTITY_COLUMN, + OrderItemFieldSetMapper.SHIPPING_PRICE_COLUMN, + OrderItemFieldSetMapper.TOTAL_PRICE_COLUMN + }; + return new DefaultFieldSet(tokens, columnNames); + } + + protected FieldSetMapper fieldSetMapper() { + return new OrderItemFieldSetMapper(); + } + +} diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/mapping/ShippingFieldSetMapperTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/mapping/ShippingFieldSetMapperTests.java index 62475f8e7e..fe46e002a3 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/mapping/ShippingFieldSetMapperTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/mapping/ShippingFieldSetMapperTests.java @@ -1,37 +1,37 @@ -package org.springframework.batch.sample.mapping; - -import org.springframework.batch.io.file.mapping.DefaultFieldSet; -import org.springframework.batch.io.file.mapping.FieldSet; -import org.springframework.batch.io.file.mapping.FieldSetMapper; -import org.springframework.batch.sample.domain.ShippingInfo; -import org.springframework.batch.sample.mapping.ShippingFieldSetMapper; - -public class ShippingFieldSetMapperTests extends AbstractFieldSetMapperTests{ - - private static final String SHIPPER_ID = "1"; - private static final String SHIPPING_INFO = "most interesting and informative shipping info ever"; - private static final String SHIPPING_TYPE_ID = "X"; - - protected Object expectedDomainObject() { - ShippingInfo info = new ShippingInfo(); - info.setShipperId(SHIPPER_ID); - info.setShippingInfo(SHIPPING_INFO); - info.setShippingTypeId(SHIPPING_TYPE_ID); - return info; - } - - protected FieldSet fieldSet() { - String[] tokens = new String[]{SHIPPER_ID, SHIPPING_INFO, SHIPPING_TYPE_ID}; - String[] columnNames = new String[]{ - ShippingFieldSetMapper.SHIPPER_ID_COLUMN, - ShippingFieldSetMapper.ADDITIONAL_SHIPPING_INFO_COLUMN, - ShippingFieldSetMapper.SHIPPING_TYPE_ID_COLUMN - }; - return new DefaultFieldSet(tokens, columnNames); - } - - protected FieldSetMapper fieldSetMapper() { - return new ShippingFieldSetMapper(); - } - -} +package org.springframework.batch.sample.mapping; + +import org.springframework.batch.io.file.mapping.DefaultFieldSet; +import org.springframework.batch.io.file.mapping.FieldSet; +import org.springframework.batch.io.file.mapping.FieldSetMapper; +import org.springframework.batch.sample.domain.ShippingInfo; +import org.springframework.batch.sample.mapping.ShippingFieldSetMapper; + +public class ShippingFieldSetMapperTests extends AbstractFieldSetMapperTests{ + + private static final String SHIPPER_ID = "1"; + private static final String SHIPPING_INFO = "most interesting and informative shipping info ever"; + private static final String SHIPPING_TYPE_ID = "X"; + + protected Object expectedDomainObject() { + ShippingInfo info = new ShippingInfo(); + info.setShipperId(SHIPPER_ID); + info.setShippingInfo(SHIPPING_INFO); + info.setShippingTypeId(SHIPPING_TYPE_ID); + return info; + } + + protected FieldSet fieldSet() { + String[] tokens = new String[]{SHIPPER_ID, SHIPPING_INFO, SHIPPING_TYPE_ID}; + String[] columnNames = new String[]{ + ShippingFieldSetMapper.SHIPPER_ID_COLUMN, + ShippingFieldSetMapper.ADDITIONAL_SHIPPING_INFO_COLUMN, + ShippingFieldSetMapper.SHIPPING_TYPE_ID_COLUMN + }; + return new DefaultFieldSet(tokens, columnNames); + } + + protected FieldSetMapper fieldSetMapper() { + return new ShippingFieldSetMapper(); + } + +} diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/mapping/TradeFieldSetMapperTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/mapping/TradeFieldSetMapperTests.java index 2d377c0399..c3f3419456 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/mapping/TradeFieldSetMapperTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/mapping/TradeFieldSetMapperTests.java @@ -1,50 +1,50 @@ -package org.springframework.batch.sample.mapping; - -import java.math.BigDecimal; - -import org.springframework.batch.io.file.mapping.DefaultFieldSet; -import org.springframework.batch.io.file.mapping.FieldSet; -import org.springframework.batch.io.file.mapping.FieldSetMapper; -import org.springframework.batch.item.reader.AggregateItemReader; -import org.springframework.batch.sample.domain.Trade; -import org.springframework.batch.sample.mapping.TradeFieldSetMapper; - -public class TradeFieldSetMapperTests extends AbstractFieldSetMapperTests{ - - private static final String CUSTOMER = "Mike Tomcat"; - private static final BigDecimal PRICE = new BigDecimal(1.3); - private static final long QUANTITY = 7; - private static final String ISIN = "fj893gnsalX"; - - protected Object expectedDomainObject() { - Trade trade = new Trade(); - trade.setIsin(ISIN); - trade.setQuantity(QUANTITY); - trade.setPrice(PRICE); - trade.setCustomer(CUSTOMER); - return trade; - } - - protected FieldSet fieldSet() { - String[] tokens = new String[4]; - tokens[TradeFieldSetMapper.ISIN_COLUMN] = ISIN; - tokens[TradeFieldSetMapper.QUANTITY_COLUMN] = String.valueOf(QUANTITY); - tokens[TradeFieldSetMapper.PRICE_COLUMN] = String.valueOf(PRICE); - tokens[TradeFieldSetMapper.CUSTOMER_COLUMN] = CUSTOMER; - - return new DefaultFieldSet(tokens); - } - - protected FieldSetMapper fieldSetMapper() { - return new TradeFieldSetMapper(); - } - - public void testBeginRecord() throws Exception { - assertEquals(AggregateItemReader.BEGIN_RECORD, fieldSetMapper().mapLine(new DefaultFieldSet(new String[] {"BEGIN"}))); - } - - public void testEndRecord() throws Exception { - assertEquals(AggregateItemReader.END_RECORD, fieldSetMapper().mapLine(new DefaultFieldSet(new String[] {"END"}))); - } - -} +package org.springframework.batch.sample.mapping; + +import java.math.BigDecimal; + +import org.springframework.batch.io.file.mapping.DefaultFieldSet; +import org.springframework.batch.io.file.mapping.FieldSet; +import org.springframework.batch.io.file.mapping.FieldSetMapper; +import org.springframework.batch.item.reader.AggregateItemReader; +import org.springframework.batch.sample.domain.Trade; +import org.springframework.batch.sample.mapping.TradeFieldSetMapper; + +public class TradeFieldSetMapperTests extends AbstractFieldSetMapperTests{ + + private static final String CUSTOMER = "Mike Tomcat"; + private static final BigDecimal PRICE = new BigDecimal(1.3); + private static final long QUANTITY = 7; + private static final String ISIN = "fj893gnsalX"; + + protected Object expectedDomainObject() { + Trade trade = new Trade(); + trade.setIsin(ISIN); + trade.setQuantity(QUANTITY); + trade.setPrice(PRICE); + trade.setCustomer(CUSTOMER); + return trade; + } + + protected FieldSet fieldSet() { + String[] tokens = new String[4]; + tokens[TradeFieldSetMapper.ISIN_COLUMN] = ISIN; + tokens[TradeFieldSetMapper.QUANTITY_COLUMN] = String.valueOf(QUANTITY); + tokens[TradeFieldSetMapper.PRICE_COLUMN] = String.valueOf(PRICE); + tokens[TradeFieldSetMapper.CUSTOMER_COLUMN] = CUSTOMER; + + return new DefaultFieldSet(tokens); + } + + protected FieldSetMapper fieldSetMapper() { + return new TradeFieldSetMapper(); + } + + public void testBeginRecord() throws Exception { + assertEquals(AggregateItemReader.BEGIN_RECORD, fieldSetMapper().mapLine(new DefaultFieldSet(new String[] {"BEGIN"}))); + } + + public void testEndRecord() throws Exception { + assertEquals(AggregateItemReader.END_RECORD, fieldSetMapper().mapLine(new DefaultFieldSet(new String[] {"END"}))); + } + +} diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/mapping/TradeRowMapperTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/mapping/TradeRowMapperTests.java index 8c2b5d65cb..7f0f1ae417 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/mapping/TradeRowMapperTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/mapping/TradeRowMapperTests.java @@ -1,46 +1,46 @@ -package org.springframework.batch.sample.mapping; - -import java.math.BigDecimal; -import java.sql.ResultSet; -import java.sql.SQLException; - -import org.easymock.MockControl; -import org.springframework.batch.sample.domain.Trade; -import org.springframework.batch.sample.mapping.TradeRowMapper; -import org.springframework.jdbc.core.RowMapper; - -public class TradeRowMapperTests extends AbstractRowMapperTests { - - private static final String ISIN = "jsgk342"; - private static final long QUANTITY = 0; - private static final BigDecimal PRICE = new BigDecimal(1.1); - private static final String CUSTOMER = "Martin Hrancok"; - - protected Object expectedDomainObject() { - Trade trade = new Trade(); - trade.setIsin(ISIN); - trade.setQuantity(QUANTITY); - trade.setPrice(PRICE); - trade.setCustomer(CUSTOMER); - return trade; - } - - protected RowMapper rowMapper() { - return new TradeRowMapper(); - } - - protected void setUpResultSetMock(ResultSet rs, MockControl rsControl) throws SQLException { - rs.getString(TradeRowMapper.ISIN_COLUMN); - rsControl.setReturnValue(ISIN); - - rs.getLong(TradeRowMapper.QUANTITY_COLUMN); - rsControl.setReturnValue(QUANTITY); - - rs.getBigDecimal(TradeRowMapper.PRICE_COLUMN); - rsControl.setReturnValue(PRICE); - - rs.getString(TradeRowMapper.CUSTOMER_COLUMN); - rsControl.setReturnValue(CUSTOMER); - } - -} +package org.springframework.batch.sample.mapping; + +import java.math.BigDecimal; +import java.sql.ResultSet; +import java.sql.SQLException; + +import org.easymock.MockControl; +import org.springframework.batch.sample.domain.Trade; +import org.springframework.batch.sample.mapping.TradeRowMapper; +import org.springframework.jdbc.core.RowMapper; + +public class TradeRowMapperTests extends AbstractRowMapperTests { + + private static final String ISIN = "jsgk342"; + private static final long QUANTITY = 0; + private static final BigDecimal PRICE = new BigDecimal(1.1); + private static final String CUSTOMER = "Martin Hrancok"; + + protected Object expectedDomainObject() { + Trade trade = new Trade(); + trade.setIsin(ISIN); + trade.setQuantity(QUANTITY); + trade.setPrice(PRICE); + trade.setCustomer(CUSTOMER); + return trade; + } + + protected RowMapper rowMapper() { + return new TradeRowMapper(); + } + + protected void setUpResultSetMock(ResultSet rs, MockControl rsControl) throws SQLException { + rs.getString(TradeRowMapper.ISIN_COLUMN); + rsControl.setReturnValue(ISIN); + + rs.getLong(TradeRowMapper.QUANTITY_COLUMN); + rsControl.setReturnValue(QUANTITY); + + rs.getBigDecimal(TradeRowMapper.PRICE_COLUMN); + rsControl.setReturnValue(PRICE); + + rs.getString(TradeRowMapper.CUSTOMER_COLUMN); + rsControl.setReturnValue(CUSTOMER); + } + +} diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/tasklet/ExceptionThrowingItemReaderProxyTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/tasklet/ExceptionThrowingItemReaderProxyTests.java index fb6ddab98d..966b6cc763 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/tasklet/ExceptionThrowingItemReaderProxyTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/tasklet/ExceptionThrowingItemReaderProxyTests.java @@ -1,49 +1,49 @@ -package org.springframework.batch.sample.tasklet; - -import java.util.ArrayList; - -import junit.framework.TestCase; - -import org.springframework.batch.io.exception.InfrastructureException; -import org.springframework.batch.item.reader.ListItemReader; -import org.springframework.batch.repeat.context.RepeatContextSupport; -import org.springframework.batch.repeat.synch.RepeatSynchronizationManager; - -public class ExceptionThrowingItemReaderProxyTests extends TestCase { - - //expected call count before exception is thrown (exception should be thrown in next iteration) - private static final int ITER_COUNT = 5; - - protected void tearDown() throws Exception { - RepeatSynchronizationManager.clear(); - } - - public void testProcess() throws Exception { - - //create module and set item processor and iteration count - ExceptionThrowingItemReaderProxy itemReader = new ExceptionThrowingItemReaderProxy(); - itemReader.setItemReader(new ListItemReader(new ArrayList() {{ - add("a"); - add("b"); - add("c"); - add("d"); - add("e"); - add("f"); - }})); - - itemReader.setThrowExceptionOnRecordNumber(ITER_COUNT + 1); - - RepeatSynchronizationManager.register(new RepeatContextSupport(null)); - - //call process method multiple times and verify whether exception is thrown when expected - for (int i = 0; i <= ITER_COUNT; i++) { - try { - itemReader.read(); - assertTrue(i < ITER_COUNT); - } catch (InfrastructureException bce) { - assertEquals(ITER_COUNT,i); - } - } - - } -} +package org.springframework.batch.sample.tasklet; + +import java.util.ArrayList; + +import junit.framework.TestCase; + +import org.springframework.batch.io.exception.InfrastructureException; +import org.springframework.batch.item.reader.ListItemReader; +import org.springframework.batch.repeat.context.RepeatContextSupport; +import org.springframework.batch.repeat.synch.RepeatSynchronizationManager; + +public class ExceptionThrowingItemReaderProxyTests extends TestCase { + + //expected call count before exception is thrown (exception should be thrown in next iteration) + private static final int ITER_COUNT = 5; + + protected void tearDown() throws Exception { + RepeatSynchronizationManager.clear(); + } + + public void testProcess() throws Exception { + + //create module and set item processor and iteration count + ExceptionThrowingItemReaderProxy itemReader = new ExceptionThrowingItemReaderProxy(); + itemReader.setItemReader(new ListItemReader(new ArrayList() {{ + add("a"); + add("b"); + add("c"); + add("d"); + add("e"); + add("f"); + }})); + + itemReader.setThrowExceptionOnRecordNumber(ITER_COUNT + 1); + + RepeatSynchronizationManager.register(new RepeatContextSupport(null)); + + //call process method multiple times and verify whether exception is thrown when expected + for (int i = 0; i <= ITER_COUNT; i++) { + try { + itemReader.read(); + assertTrue(i < ITER_COUNT); + } catch (InfrastructureException bce) { + assertEquals(ITER_COUNT,i); + } + } + + } +} diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/tasklet/SimpleTradeTaskletTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/tasklet/SimpleTradeTaskletTests.java index b148bc467f..9d6a786986 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/tasklet/SimpleTradeTaskletTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/tasklet/SimpleTradeTaskletTests.java @@ -1,57 +1,57 @@ -package org.springframework.batch.sample.tasklet; - -import java.math.BigDecimal; - -import junit.framework.TestCase; - -import org.springframework.batch.io.file.FlatFileItemReader; -import org.springframework.batch.sample.dao.TradeDao; -import org.springframework.batch.sample.domain.Trade; - -public class SimpleTradeTaskletTests extends TestCase { - - private boolean inputCalled = false; - private boolean writerCalled = false; - - public void testReadAndProcess() throws Exception { - - //create input - FlatFileItemReader input = new FlatFileItemReader() { - - private boolean done = false; - - public Object read() { - if (!done) { - Trade trade = new Trade("1234", 5, new BigDecimal(100), "testName"); - inputCalled = true; - done = true; - return trade; - } else { - return null; - } - } - }; - - //create writer - TradeDao dao = new TradeDao() { - public void writeTrade(Trade trade) { - assertEquals("1234",trade.getIsin()); - assertEquals(5, trade.getQuantity()); - assertEquals(new BigDecimal(100), trade.getPrice()); - assertEquals("testName", trade.getCustomer()); - writerCalled = true; - } - }; - - //create module - SimpleTradeWriter module = new SimpleTradeWriter(); - module.setTradeDao(dao); - - module.write(input.read()); - - //verify whether input and writer were called - assertTrue(inputCalled); - assertTrue(writerCalled); - - } -} +package org.springframework.batch.sample.tasklet; + +import java.math.BigDecimal; + +import junit.framework.TestCase; + +import org.springframework.batch.io.file.FlatFileItemReader; +import org.springframework.batch.sample.dao.TradeDao; +import org.springframework.batch.sample.domain.Trade; + +public class SimpleTradeTaskletTests extends TestCase { + + private boolean inputCalled = false; + private boolean writerCalled = false; + + public void testReadAndProcess() throws Exception { + + //create input + FlatFileItemReader input = new FlatFileItemReader() { + + private boolean done = false; + + public Object read() { + if (!done) { + Trade trade = new Trade("1234", 5, new BigDecimal(100), "testName"); + inputCalled = true; + done = true; + return trade; + } else { + return null; + } + } + }; + + //create writer + TradeDao dao = new TradeDao() { + public void writeTrade(Trade trade) { + assertEquals("1234",trade.getIsin()); + assertEquals(5, trade.getQuantity()); + assertEquals(new BigDecimal(100), trade.getPrice()); + assertEquals("testName", trade.getCustomer()); + writerCalled = true; + } + }; + + //create module + SimpleTradeWriter module = new SimpleTradeWriter(); + module.setTradeDao(dao); + + module.write(input.read()); + + //verify whether input and writer were called + assertTrue(inputCalled); + assertTrue(writerCalled); + + } +} diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/tasklet/StepSupport.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/tasklet/StepSupport.java index c1c1abae4b..28eabb74c2 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/tasklet/StepSupport.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/tasklet/StepSupport.java @@ -1,117 +1,117 @@ -/* - * Copyright 2006-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.sample.tasklet; - -import org.springframework.batch.core.domain.JobInterruptedException; -import org.springframework.batch.core.domain.Step; -import org.springframework.batch.core.domain.StepExecution; -import org.springframework.batch.io.exception.InfrastructureException; -import org.springframework.beans.factory.BeanNameAware; - -/** - * Basic no-op support implementation for use as base class for {@link Step}. Implements {@link BeanNameAware} so that - * if no name is provided explicitly it will be inferred from the bean definition in Spring configuration. - * - * @author Dave Syer - * - */ -public class StepSupport implements Step, BeanNameAware { - - private String name; - - private int startLimit = Integer.MAX_VALUE; - - private boolean allowStartIfComplete; - - /** - * Default constructor for {@link StepSupport}. - */ - public StepSupport() { - super(); - } - - /** - * @param string - */ - public StepSupport(String string) { - super(); - this.name = string; - } - - public String getName() { - return this.name; - } - - /** - * Set the name property if it is not already set. Because of the order of the callbacks in a Spring container the - * name property will be set first if it is present. Care is needed with bean definition inheritance - if a parent - * bean has a name, then its children need an explicit name as well, otherwise they will not be unique. - * - * @see org.springframework.beans.factory.BeanNameAware#setBeanName(java.lang.String) - */ - public void setBeanName(String name) { - if (this.name == null) { - this.name = name; - } - } - - /** - * Set the name property. Always overrides the default value if this object is a Spring bean. - * - * @see #setBeanName(java.lang.String) - */ - public void setName(String name) { - this.name = name; - } - - public int getStartLimit() { - return this.startLimit; - } - - /** - * Public setter for the startLimit. - * - * @param startLimit the startLimit to set - */ - public void setStartLimit(int startLimit) { - this.startLimit = startLimit; - } - - public boolean isAllowStartIfComplete() { - return this.allowStartIfComplete; - } - - /** - * Public setter for the shouldAllowStartIfComplete. - * - * @param allowStartIfComplete the shouldAllowStartIfComplete to set - */ - public void setAllowStartIfComplete(boolean allowStartIfComplete) { - this.allowStartIfComplete = allowStartIfComplete; - } - - /** - * Not supported but provided so that tests can easily create a step. - * - * @throws UnsupportedOperationException always - * - * @see org.springframework.batch.core.domain.Step#execute(org.springframework.batch.core.domain.StepExecution) - */ - public void execute(StepExecution stepExecution) throws JobInterruptedException, InfrastructureException { - throw new UnsupportedOperationException( - "Cannot process a StepExecution. Use a smarter subclass of StepSupport."); - } -} +/* + * Copyright 2006-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.sample.tasklet; + +import org.springframework.batch.core.domain.JobInterruptedException; +import org.springframework.batch.core.domain.Step; +import org.springframework.batch.core.domain.StepExecution; +import org.springframework.batch.io.exception.InfrastructureException; +import org.springframework.beans.factory.BeanNameAware; + +/** + * Basic no-op support implementation for use as base class for {@link Step}. Implements {@link BeanNameAware} so that + * if no name is provided explicitly it will be inferred from the bean definition in Spring configuration. + * + * @author Dave Syer + * + */ +public class StepSupport implements Step, BeanNameAware { + + private String name; + + private int startLimit = Integer.MAX_VALUE; + + private boolean allowStartIfComplete; + + /** + * Default constructor for {@link StepSupport}. + */ + public StepSupport() { + super(); + } + + /** + * @param string + */ + public StepSupport(String string) { + super(); + this.name = string; + } + + public String getName() { + return this.name; + } + + /** + * Set the name property if it is not already set. Because of the order of the callbacks in a Spring container the + * name property will be set first if it is present. Care is needed with bean definition inheritance - if a parent + * bean has a name, then its children need an explicit name as well, otherwise they will not be unique. + * + * @see org.springframework.beans.factory.BeanNameAware#setBeanName(java.lang.String) + */ + public void setBeanName(String name) { + if (this.name == null) { + this.name = name; + } + } + + /** + * Set the name property. Always overrides the default value if this object is a Spring bean. + * + * @see #setBeanName(java.lang.String) + */ + public void setName(String name) { + this.name = name; + } + + public int getStartLimit() { + return this.startLimit; + } + + /** + * Public setter for the startLimit. + * + * @param startLimit the startLimit to set + */ + public void setStartLimit(int startLimit) { + this.startLimit = startLimit; + } + + public boolean isAllowStartIfComplete() { + return this.allowStartIfComplete; + } + + /** + * Public setter for the shouldAllowStartIfComplete. + * + * @param allowStartIfComplete the shouldAllowStartIfComplete to set + */ + public void setAllowStartIfComplete(boolean allowStartIfComplete) { + this.allowStartIfComplete = allowStartIfComplete; + } + + /** + * Not supported but provided so that tests can easily create a step. + * + * @throws UnsupportedOperationException always + * + * @see org.springframework.batch.core.domain.Step#execute(org.springframework.batch.core.domain.StepExecution) + */ + public void execute(StepExecution stepExecution) throws JobInterruptedException, InfrastructureException { + throw new UnsupportedOperationException( + "Cannot process a StepExecution. Use a smarter subclass of StepSupport."); + } +} diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/validation/valang/custom/FutureDateFunctionTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/validation/valang/custom/FutureDateFunctionTests.java index f94d6abaae..5cf38867dd 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/validation/valang/custom/FutureDateFunctionTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/validation/valang/custom/FutureDateFunctionTests.java @@ -1,61 +1,61 @@ -package org.springframework.batch.sample.validation.valang.custom; - -import java.util.Date; - -import org.easymock.MockControl; -import org.springmodules.validation.valang.functions.Function; -import junit.framework.TestCase; - -public class FutureDateFunctionTests extends TestCase { - - private FutureDateFunction function; - private MockControl argumentControl; - private Function argument; - - public void setUp() { - argumentControl = MockControl.createControl(Function.class); - argument = (Function) argumentControl.getMock(); - - //create function - function = new FutureDateFunction(new Function[] {argument}, 0, 0); - } - - public void testFunctionWithNonDateValue() { - - //set-up mock argument - set return value to non Date value - argument.getResult(null); - argumentControl.setReturnValue(this); - argumentControl.replay(); - - //call tested method - exception is expected because non date value - try { - function.doGetResult(null); - fail("Exception was expected."); - } catch (Exception e) { - assertTrue(true); - } - } - - public void testFunctionWithFutureDate() throws Exception { - - //set-up mock argument - set return value to future Date - argument.getResult(null); - argumentControl.setReturnValue(new Date(Long.MAX_VALUE)); - argumentControl.replay(); - - //vefify result - should be true because of future date - assertTrue(((Boolean)function.doGetResult(null)).booleanValue()); - } - - public void testFunctionWithPastDate() throws Exception { - - //set-up mock argument - set return value to future Date - argument.getResult(null); - argumentControl.setReturnValue(new Date(0)); - argumentControl.replay(); - - //vefify result - should be false because of past date - assertFalse(((Boolean)function.doGetResult(null)).booleanValue()); - - } -} +package org.springframework.batch.sample.validation.valang.custom; + +import java.util.Date; + +import org.easymock.MockControl; +import org.springmodules.validation.valang.functions.Function; +import junit.framework.TestCase; + +public class FutureDateFunctionTests extends TestCase { + + private FutureDateFunction function; + private MockControl argumentControl; + private Function argument; + + public void setUp() { + argumentControl = MockControl.createControl(Function.class); + argument = (Function) argumentControl.getMock(); + + //create function + function = new FutureDateFunction(new Function[] {argument}, 0, 0); + } + + public void testFunctionWithNonDateValue() { + + //set-up mock argument - set return value to non Date value + argument.getResult(null); + argumentControl.setReturnValue(this); + argumentControl.replay(); + + //call tested method - exception is expected because non date value + try { + function.doGetResult(null); + fail("Exception was expected."); + } catch (Exception e) { + assertTrue(true); + } + } + + public void testFunctionWithFutureDate() throws Exception { + + //set-up mock argument - set return value to future Date + argument.getResult(null); + argumentControl.setReturnValue(new Date(Long.MAX_VALUE)); + argumentControl.replay(); + + //vefify result - should be true because of future date + assertTrue(((Boolean)function.doGetResult(null)).booleanValue()); + } + + public void testFunctionWithPastDate() throws Exception { + + //set-up mock argument - set return value to future Date + argument.getResult(null); + argumentControl.setReturnValue(new Date(0)); + argumentControl.replay(); + + //vefify result - should be false because of past date + assertFalse(((Boolean)function.doGetResult(null)).booleanValue()); + + } +} diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/validation/valang/custom/TotalOrderItemsFunctionTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/validation/valang/custom/TotalOrderItemsFunctionTests.java index a3cacea9cb..e296d19179 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/validation/valang/custom/TotalOrderItemsFunctionTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/validation/valang/custom/TotalOrderItemsFunctionTests.java @@ -1,82 +1,82 @@ -package org.springframework.batch.sample.validation.valang.custom; - -import java.util.ArrayList; -import java.util.List; - -import org.springframework.batch.sample.domain.LineItem; - -import org.easymock.MockControl; -import org.springmodules.validation.valang.functions.Function; -import junit.framework.TestCase; - -public class TotalOrderItemsFunctionTests extends TestCase { - - private TotalOrderItemsFunction function; - private MockControl argument1Control; - private Function argument1; - private MockControl argument2Control; - private Function argument2; - - public void setUp() { - //create mock for first argument - set count to 3 - argument1Control = MockControl.createControl(Function.class); - argument1 = (Function) argument1Control.getMock(); - argument1.getResult(null); - argument1Control.setReturnValue(new Integer(3)); - argument1Control.replay(); - - argument2Control = MockControl.createControl(Function.class); - argument2 = (Function) argument2Control.getMock(); - - //create function - function = new TotalOrderItemsFunction(new Function[] {argument1, argument2}, 0, 0); - } - - public void testFunctionWithNonListValue() { - - argument2.getResult(null); - argument2Control.setReturnValue(this); - argument2Control.replay(); - - //call tested method - exception is expected because non list value - try { - function.doGetResult(null); - fail("Exception was expected."); - } catch (Exception e) { - assertTrue(true); - } - } - - public void testFunctionWithCorrectItemCount() throws Exception { - - //create list with correct item count - LineItem item = new LineItem(); - item.setQuantity(3); - List list = new ArrayList(); - list.add(item); - - argument2.getResult(null); - argument2Control.setReturnValue(list); - argument2Control.replay(); - - //vefify result - assertTrue(((Boolean)function.doGetResult(null)).booleanValue()); - } - - public void testFunctionWithIncorrectItemCount() throws Exception { - - //create list with incorrect item count - LineItem item = new LineItem(); - item.setQuantity(99); - List list = new ArrayList(); - list.add(item); - - argument2.getResult(null); - argument2Control.setReturnValue(list); - argument2Control.replay(); - - //vefify result - assertFalse(((Boolean)function.doGetResult(null)).booleanValue()); - } - -} +package org.springframework.batch.sample.validation.valang.custom; + +import java.util.ArrayList; +import java.util.List; + +import org.springframework.batch.sample.domain.LineItem; + +import org.easymock.MockControl; +import org.springmodules.validation.valang.functions.Function; +import junit.framework.TestCase; + +public class TotalOrderItemsFunctionTests extends TestCase { + + private TotalOrderItemsFunction function; + private MockControl argument1Control; + private Function argument1; + private MockControl argument2Control; + private Function argument2; + + public void setUp() { + //create mock for first argument - set count to 3 + argument1Control = MockControl.createControl(Function.class); + argument1 = (Function) argument1Control.getMock(); + argument1.getResult(null); + argument1Control.setReturnValue(new Integer(3)); + argument1Control.replay(); + + argument2Control = MockControl.createControl(Function.class); + argument2 = (Function) argument2Control.getMock(); + + //create function + function = new TotalOrderItemsFunction(new Function[] {argument1, argument2}, 0, 0); + } + + public void testFunctionWithNonListValue() { + + argument2.getResult(null); + argument2Control.setReturnValue(this); + argument2Control.replay(); + + //call tested method - exception is expected because non list value + try { + function.doGetResult(null); + fail("Exception was expected."); + } catch (Exception e) { + assertTrue(true); + } + } + + public void testFunctionWithCorrectItemCount() throws Exception { + + //create list with correct item count + LineItem item = new LineItem(); + item.setQuantity(3); + List list = new ArrayList(); + list.add(item); + + argument2.getResult(null); + argument2Control.setReturnValue(list); + argument2Control.replay(); + + //vefify result + assertTrue(((Boolean)function.doGetResult(null)).booleanValue()); + } + + public void testFunctionWithIncorrectItemCount() throws Exception { + + //create list with incorrect item count + LineItem item = new LineItem(); + item.setQuantity(99); + List list = new ArrayList(); + list.add(item); + + argument2.getResult(null); + argument2Control.setReturnValue(list); + argument2Control.replay(); + + //vefify result + assertFalse(((Boolean)function.doGetResult(null)).booleanValue()); + } + +} diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/validation/valang/custom/ValidateDiscountsFunctionTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/validation/valang/custom/ValidateDiscountsFunctionTests.java index 6f2b2fee09..1cd912561c 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/validation/valang/custom/ValidateDiscountsFunctionTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/validation/valang/custom/ValidateDiscountsFunctionTests.java @@ -1,166 +1,166 @@ -package org.springframework.batch.sample.validation.valang.custom; - -import java.math.BigDecimal; -import java.util.ArrayList; -import java.util.List; - -import org.springframework.batch.sample.domain.LineItem; - -import org.easymock.MockControl; -import org.springmodules.validation.valang.functions.Function; -import junit.framework.TestCase; - -public class ValidateDiscountsFunctionTests extends TestCase { - - private ValidateDiscountsFunction function; - private MockControl argumentControl; - private Function argument; - - public void setUp() { - argumentControl = MockControl.createControl(Function.class); - argument = (Function) argumentControl.getMock(); - - //create function - function = new ValidateDiscountsFunction(new Function[] {argument}, 0, 0); - } - - public void testDiscountPercentageMin() throws Exception { - - //create line item with correct discount percentage and zero discount amount - LineItem item = new LineItem(); - item.setDiscountPerc(new BigDecimal(1.0)); - item.setDiscountAmount(new BigDecimal(0.0)); - - //add it to line items list - List items = new ArrayList(); - items.add(item); - - //set return value for mock argument - argument.getResult(null); - argumentControl.setReturnValue(items,2); - argumentControl.replay(); - - //verify result - should be true - all discount percentages are correct - assertTrue(((Boolean)function.doGetResult(null)).booleanValue()); - - //now add line item with negative percentage - item = new LineItem(); - item.setDiscountPerc(new BigDecimal(-1.0)); - item.setDiscountAmount(new BigDecimal(0.0)); - items.add(item); - - //verify result - should be false - second item has invalid discount percentage - assertFalse(((Boolean)function.doGetResult(null)).booleanValue()); - } - - public void testDiscountPercentageMax() throws Exception { - - //create line item with correct discount percentage and zero discount amount - LineItem item = new LineItem(); - item.setDiscountPerc(new BigDecimal(99.0)); - item.setDiscountAmount(new BigDecimal(0.0)); - - //add it to line items list - List items = new ArrayList(); - items.add(item); - - //set return value for mock argument - argument.getResult(null); - argumentControl.setReturnValue(items,2); - argumentControl.replay(); - - //verify result - should be true - all discount percentages are correct - assertTrue(((Boolean)function.doGetResult(null)).booleanValue()); - - //now add line item with discount percentage above 100 - item = new LineItem(); - item.setDiscountPerc(new BigDecimal(101.0)); - item.setDiscountAmount(new BigDecimal(0.0)); - items.add(item); - - //verify result - should be false - second item has invalid discount percentage - assertFalse(((Boolean)function.doGetResult(null)).booleanValue()); - } - - public void testDiscountPriceMin() throws Exception { - - //create line item with correct discount amount and zero discount percentage - LineItem item = new LineItem(); - item.setDiscountPerc(new BigDecimal(0.0)); - item.setDiscountAmount(new BigDecimal(10.0)); - item.setPrice(new BigDecimal(100.0)); - - //add it to line items list - List items = new ArrayList(); - items.add(item); - - //set return value for mock argument - argument.getResult(null); - argumentControl.setReturnValue(items,2); - argumentControl.replay(); - - //verify result - should be true - all discount amounts are correct - assertTrue(((Boolean)function.doGetResult(null)).booleanValue()); - - //now add line item with negative discount amount - item = new LineItem(); - item.setDiscountPerc(new BigDecimal(0.0)); - item.setDiscountAmount(new BigDecimal(-1.0)); - item.setPrice(new BigDecimal(100.0)); - items.add(item); - - //verify result - should be false - second item has invalid discount amount - assertFalse(((Boolean)function.doGetResult(null)).booleanValue()); - } - - public void testDiscountPriceMax() throws Exception { - - //create line item with correct discount amount and zero discount percentage - LineItem item = new LineItem(); - item.setDiscountPerc(new BigDecimal(0.0)); - item.setDiscountAmount(new BigDecimal(99.0)); - item.setPrice(new BigDecimal(100.0)); - - //add it to line items list - List items = new ArrayList(); - items.add(item); - - //set return value for mock argument - argument.getResult(null); - argumentControl.setReturnValue(items,2); - argumentControl.replay(); - - //verify result - should be true - all discount amounts are correct - assertTrue(((Boolean)function.doGetResult(null)).booleanValue()); - - //now add line item with discount amount above item price - item = new LineItem(); - item.setDiscountPerc(new BigDecimal(0.0)); - item.setDiscountAmount(new BigDecimal(101.0)); - item.setPrice(new BigDecimal(100.0)); - items.add(item); - - //verify result - should be false - second item has invalid discount amount - assertFalse(((Boolean)function.doGetResult(null)).booleanValue()); - } - - public void testBothDiscountValuesNonZero() throws Exception { - - //create line item with non-zero discount amount and non-zero discount percentage - LineItem item = new LineItem(); - item.setDiscountPerc(new BigDecimal(10.0)); - item.setDiscountAmount(new BigDecimal(99.0)); - - //add it to line items list - List items = new ArrayList(); - items.add(item); - - //set return value for mock argument - argument.getResult(null); - argumentControl.setReturnValue(items); - argumentControl.replay(); - - //verify result - should be false - only one of the discount values is empty - assertFalse(((Boolean)function.doGetResult(null)).booleanValue()); - } -} +package org.springframework.batch.sample.validation.valang.custom; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.List; + +import org.springframework.batch.sample.domain.LineItem; + +import org.easymock.MockControl; +import org.springmodules.validation.valang.functions.Function; +import junit.framework.TestCase; + +public class ValidateDiscountsFunctionTests extends TestCase { + + private ValidateDiscountsFunction function; + private MockControl argumentControl; + private Function argument; + + public void setUp() { + argumentControl = MockControl.createControl(Function.class); + argument = (Function) argumentControl.getMock(); + + //create function + function = new ValidateDiscountsFunction(new Function[] {argument}, 0, 0); + } + + public void testDiscountPercentageMin() throws Exception { + + //create line item with correct discount percentage and zero discount amount + LineItem item = new LineItem(); + item.setDiscountPerc(new BigDecimal(1.0)); + item.setDiscountAmount(new BigDecimal(0.0)); + + //add it to line items list + List items = new ArrayList(); + items.add(item); + + //set return value for mock argument + argument.getResult(null); + argumentControl.setReturnValue(items,2); + argumentControl.replay(); + + //verify result - should be true - all discount percentages are correct + assertTrue(((Boolean)function.doGetResult(null)).booleanValue()); + + //now add line item with negative percentage + item = new LineItem(); + item.setDiscountPerc(new BigDecimal(-1.0)); + item.setDiscountAmount(new BigDecimal(0.0)); + items.add(item); + + //verify result - should be false - second item has invalid discount percentage + assertFalse(((Boolean)function.doGetResult(null)).booleanValue()); + } + + public void testDiscountPercentageMax() throws Exception { + + //create line item with correct discount percentage and zero discount amount + LineItem item = new LineItem(); + item.setDiscountPerc(new BigDecimal(99.0)); + item.setDiscountAmount(new BigDecimal(0.0)); + + //add it to line items list + List items = new ArrayList(); + items.add(item); + + //set return value for mock argument + argument.getResult(null); + argumentControl.setReturnValue(items,2); + argumentControl.replay(); + + //verify result - should be true - all discount percentages are correct + assertTrue(((Boolean)function.doGetResult(null)).booleanValue()); + + //now add line item with discount percentage above 100 + item = new LineItem(); + item.setDiscountPerc(new BigDecimal(101.0)); + item.setDiscountAmount(new BigDecimal(0.0)); + items.add(item); + + //verify result - should be false - second item has invalid discount percentage + assertFalse(((Boolean)function.doGetResult(null)).booleanValue()); + } + + public void testDiscountPriceMin() throws Exception { + + //create line item with correct discount amount and zero discount percentage + LineItem item = new LineItem(); + item.setDiscountPerc(new BigDecimal(0.0)); + item.setDiscountAmount(new BigDecimal(10.0)); + item.setPrice(new BigDecimal(100.0)); + + //add it to line items list + List items = new ArrayList(); + items.add(item); + + //set return value for mock argument + argument.getResult(null); + argumentControl.setReturnValue(items,2); + argumentControl.replay(); + + //verify result - should be true - all discount amounts are correct + assertTrue(((Boolean)function.doGetResult(null)).booleanValue()); + + //now add line item with negative discount amount + item = new LineItem(); + item.setDiscountPerc(new BigDecimal(0.0)); + item.setDiscountAmount(new BigDecimal(-1.0)); + item.setPrice(new BigDecimal(100.0)); + items.add(item); + + //verify result - should be false - second item has invalid discount amount + assertFalse(((Boolean)function.doGetResult(null)).booleanValue()); + } + + public void testDiscountPriceMax() throws Exception { + + //create line item with correct discount amount and zero discount percentage + LineItem item = new LineItem(); + item.setDiscountPerc(new BigDecimal(0.0)); + item.setDiscountAmount(new BigDecimal(99.0)); + item.setPrice(new BigDecimal(100.0)); + + //add it to line items list + List items = new ArrayList(); + items.add(item); + + //set return value for mock argument + argument.getResult(null); + argumentControl.setReturnValue(items,2); + argumentControl.replay(); + + //verify result - should be true - all discount amounts are correct + assertTrue(((Boolean)function.doGetResult(null)).booleanValue()); + + //now add line item with discount amount above item price + item = new LineItem(); + item.setDiscountPerc(new BigDecimal(0.0)); + item.setDiscountAmount(new BigDecimal(101.0)); + item.setPrice(new BigDecimal(100.0)); + items.add(item); + + //verify result - should be false - second item has invalid discount amount + assertFalse(((Boolean)function.doGetResult(null)).booleanValue()); + } + + public void testBothDiscountValuesNonZero() throws Exception { + + //create line item with non-zero discount amount and non-zero discount percentage + LineItem item = new LineItem(); + item.setDiscountPerc(new BigDecimal(10.0)); + item.setDiscountAmount(new BigDecimal(99.0)); + + //add it to line items list + List items = new ArrayList(); + items.add(item); + + //set return value for mock argument + argument.getResult(null); + argumentControl.setReturnValue(items); + argumentControl.replay(); + + //verify result - should be false - only one of the discount values is empty + assertFalse(((Boolean)function.doGetResult(null)).booleanValue()); + } +} diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/validation/valang/custom/ValidateHandlingPricesFunctionTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/validation/valang/custom/ValidateHandlingPricesFunctionTests.java index 31ccab808f..5329f414be 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/validation/valang/custom/ValidateHandlingPricesFunctionTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/validation/valang/custom/ValidateHandlingPricesFunctionTests.java @@ -1,81 +1,81 @@ -package org.springframework.batch.sample.validation.valang.custom; - -import java.math.BigDecimal; -import java.util.ArrayList; -import java.util.List; - -import org.easymock.MockControl; - -import org.springframework.batch.sample.domain.LineItem; - -import org.springmodules.validation.valang.functions.Function; -import junit.framework.TestCase; - -public class ValidateHandlingPricesFunctionTests extends TestCase { - - private ValidateHandlingPricesFunction function; - private MockControl argumentControl; - private Function argument; - - public void setUp() { - argumentControl = MockControl.createControl(Function.class); - argument = (Function) argumentControl.getMock(); - - //create function - function = new ValidateHandlingPricesFunction(new Function[] {argument}, 0, 0); - } - - public void testHandlingPriceMin() throws Exception { - - //create line item with correct handling price - LineItem item = new LineItem(); - item.setHandlingPrice(new BigDecimal(1.0)); - - //add it to line items list - List items = new ArrayList(); - items.add(item); - - //set return value for mock argument - argument.getResult(null); - argumentControl.setReturnValue(items,2); - argumentControl.replay(); - - //verify result - should be true - all handling prices are correct - assertTrue(((Boolean)function.doGetResult(null)).booleanValue()); - - //now add line item with negative handling price - item = new LineItem(); - item.setHandlingPrice(new BigDecimal(-1.0)); - items.add(item); - - //verify result - should be false - second item has invalid handling price - assertFalse(((Boolean)function.doGetResult(null)).booleanValue()); - } - - public void testHandlingPriceMax() throws Exception { - - //create line item with correct handling price - LineItem item = new LineItem(); - item.setHandlingPrice(new BigDecimal(99999999.0)); - - //add it to line items list - List items = new ArrayList(); - items.add(item); - - //set return value for mock argument - argument.getResult(null); - argumentControl.setReturnValue(items,2); - argumentControl.replay(); - - //verify result - should be true - all handling prices are correct - assertTrue(((Boolean)function.doGetResult(null)).booleanValue()); - - //now add line item with handling price above allowed max - item = new LineItem(); - item.setHandlingPrice(new BigDecimal(100000000.0)); - items.add(item); - - //verify result - should be false - second item has invalid handling price - assertFalse(((Boolean)function.doGetResult(null)).booleanValue()); - } -} +package org.springframework.batch.sample.validation.valang.custom; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.List; + +import org.easymock.MockControl; + +import org.springframework.batch.sample.domain.LineItem; + +import org.springmodules.validation.valang.functions.Function; +import junit.framework.TestCase; + +public class ValidateHandlingPricesFunctionTests extends TestCase { + + private ValidateHandlingPricesFunction function; + private MockControl argumentControl; + private Function argument; + + public void setUp() { + argumentControl = MockControl.createControl(Function.class); + argument = (Function) argumentControl.getMock(); + + //create function + function = new ValidateHandlingPricesFunction(new Function[] {argument}, 0, 0); + } + + public void testHandlingPriceMin() throws Exception { + + //create line item with correct handling price + LineItem item = new LineItem(); + item.setHandlingPrice(new BigDecimal(1.0)); + + //add it to line items list + List items = new ArrayList(); + items.add(item); + + //set return value for mock argument + argument.getResult(null); + argumentControl.setReturnValue(items,2); + argumentControl.replay(); + + //verify result - should be true - all handling prices are correct + assertTrue(((Boolean)function.doGetResult(null)).booleanValue()); + + //now add line item with negative handling price + item = new LineItem(); + item.setHandlingPrice(new BigDecimal(-1.0)); + items.add(item); + + //verify result - should be false - second item has invalid handling price + assertFalse(((Boolean)function.doGetResult(null)).booleanValue()); + } + + public void testHandlingPriceMax() throws Exception { + + //create line item with correct handling price + LineItem item = new LineItem(); + item.setHandlingPrice(new BigDecimal(99999999.0)); + + //add it to line items list + List items = new ArrayList(); + items.add(item); + + //set return value for mock argument + argument.getResult(null); + argumentControl.setReturnValue(items,2); + argumentControl.replay(); + + //verify result - should be true - all handling prices are correct + assertTrue(((Boolean)function.doGetResult(null)).booleanValue()); + + //now add line item with handling price above allowed max + item = new LineItem(); + item.setHandlingPrice(new BigDecimal(100000000.0)); + items.add(item); + + //verify result - should be false - second item has invalid handling price + assertFalse(((Boolean)function.doGetResult(null)).booleanValue()); + } +} diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/validation/valang/custom/ValidateIdsFunctionTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/validation/valang/custom/ValidateIdsFunctionTests.java index 6819cf5267..24857a79c5 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/validation/valang/custom/ValidateIdsFunctionTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/validation/valang/custom/ValidateIdsFunctionTests.java @@ -1,80 +1,80 @@ -package org.springframework.batch.sample.validation.valang.custom; - -import java.util.ArrayList; -import java.util.List; - -import junit.framework.TestCase; -import org.easymock.MockControl; - -import org.springframework.batch.sample.domain.LineItem; - -import org.springmodules.validation.valang.functions.Function; - -public class ValidateIdsFunctionTests extends TestCase { - - private ValidateIdsFunction function; - private MockControl argumentControl; - private Function argument; - - public void setUp() { - argumentControl = MockControl.createControl(Function.class); - argument = (Function) argumentControl.getMock(); - - //create function - function = new ValidateIdsFunction(new Function[] {argument}, 0, 0); - } - - public void testIdMin() throws Exception { - - //create line item with correct item id - LineItem item = new LineItem(); - item.setItemId(1); - - //add it to line items list - List items = new ArrayList(); - items.add(item); - - //set return value for mock argument - argument.getResult(null); - argumentControl.setReturnValue(items,2); - argumentControl.replay(); - - //verify result - should be true - all ids are correct - assertTrue(((Boolean)function.doGetResult(null)).booleanValue()); - - //now add line item with negative id - item = new LineItem(); - item.setItemId(-1); - items.add(item); - - //verify result - should be false - second item has invalid id - assertFalse(((Boolean)function.doGetResult(null)).booleanValue()); - } - - public void testIdMax() throws Exception { - - //create line item with correct item id - LineItem item = new LineItem(); - item.setItemId(9999999999L); - - //add it to line items list - List items = new ArrayList(); - items.add(item); - - //set return value for mock argument - argument.getResult(null); - argumentControl.setReturnValue(items,2); - argumentControl.replay(); - - //verify result - should be true - all item ids are correct - assertTrue(((Boolean)function.doGetResult(null)).booleanValue()); - - //now add line item with item id above allowed max - item = new LineItem(); - item.setItemId(10000000000L); - items.add(item); - - //verify result - should be false - second item has invalid item id - assertFalse(((Boolean)function.doGetResult(null)).booleanValue()); - } -} +package org.springframework.batch.sample.validation.valang.custom; + +import java.util.ArrayList; +import java.util.List; + +import junit.framework.TestCase; +import org.easymock.MockControl; + +import org.springframework.batch.sample.domain.LineItem; + +import org.springmodules.validation.valang.functions.Function; + +public class ValidateIdsFunctionTests extends TestCase { + + private ValidateIdsFunction function; + private MockControl argumentControl; + private Function argument; + + public void setUp() { + argumentControl = MockControl.createControl(Function.class); + argument = (Function) argumentControl.getMock(); + + //create function + function = new ValidateIdsFunction(new Function[] {argument}, 0, 0); + } + + public void testIdMin() throws Exception { + + //create line item with correct item id + LineItem item = new LineItem(); + item.setItemId(1); + + //add it to line items list + List items = new ArrayList(); + items.add(item); + + //set return value for mock argument + argument.getResult(null); + argumentControl.setReturnValue(items,2); + argumentControl.replay(); + + //verify result - should be true - all ids are correct + assertTrue(((Boolean)function.doGetResult(null)).booleanValue()); + + //now add line item with negative id + item = new LineItem(); + item.setItemId(-1); + items.add(item); + + //verify result - should be false - second item has invalid id + assertFalse(((Boolean)function.doGetResult(null)).booleanValue()); + } + + public void testIdMax() throws Exception { + + //create line item with correct item id + LineItem item = new LineItem(); + item.setItemId(9999999999L); + + //add it to line items list + List items = new ArrayList(); + items.add(item); + + //set return value for mock argument + argument.getResult(null); + argumentControl.setReturnValue(items,2); + argumentControl.replay(); + + //verify result - should be true - all item ids are correct + assertTrue(((Boolean)function.doGetResult(null)).booleanValue()); + + //now add line item with item id above allowed max + item = new LineItem(); + item.setItemId(10000000000L); + items.add(item); + + //verify result - should be false - second item has invalid item id + assertFalse(((Boolean)function.doGetResult(null)).booleanValue()); + } +} diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/validation/valang/custom/ValidatePricesFunctionTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/validation/valang/custom/ValidatePricesFunctionTests.java index e738323327..6340314413 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/validation/valang/custom/ValidatePricesFunctionTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/validation/valang/custom/ValidatePricesFunctionTests.java @@ -1,82 +1,82 @@ -package org.springframework.batch.sample.validation.valang.custom; - -import java.math.BigDecimal; -import java.util.ArrayList; -import java.util.List; - -import org.easymock.MockControl; - -import org.springframework.batch.sample.domain.LineItem; - -import org.springmodules.validation.valang.functions.Function; -import junit.framework.TestCase; - -public class ValidatePricesFunctionTests extends TestCase { - - private ValidatePricesFunction function; - private MockControl argumentControl; - private Function argument; - - public void setUp() { - argumentControl = MockControl.createControl(Function.class); - argument = (Function) argumentControl.getMock(); - - //create function - function = new ValidatePricesFunction(new Function[] {argument}, 0, 0); - } - - public void testItemPriceMin() throws Exception { - - //create line item with correct item price - LineItem item = new LineItem(); - item.setPrice(new BigDecimal(1.0)); - - //add it to line items list - List items = new ArrayList(); - items.add(item); - - //set return value for mock argument - argument.getResult(null); - argumentControl.setReturnValue(items,2); - argumentControl.replay(); - - //verify result - should be true - all item prices are correct - assertTrue(((Boolean)function.doGetResult(null)).booleanValue()); - - //now add line item with negative item price - item = new LineItem(); - item.setPrice(new BigDecimal(-1.0)); - items.add(item); - - //verify result - should be false - second item has invalid item price - assertFalse(((Boolean)function.doGetResult(null)).booleanValue()); - } - - public void testItemPriceMax() throws Exception { - - //create line item with correct item price - LineItem item = new LineItem(); - item.setPrice(new BigDecimal(99999999.0)); - - //add it to line items list - List items = new ArrayList(); - items.add(item); - - //set return value for mock argument - argument.getResult(null); - argumentControl.setReturnValue(items,2); - argumentControl.replay(); - - //verify result - should be true - all item prices are correct - assertTrue(((Boolean)function.doGetResult(null)).booleanValue()); - - //now add line item with item price above allowed max - item = new LineItem(); - item.setPrice(new BigDecimal(100000000.0)); - items.add(item); - - //verify result - should be false - second item has invalid item price - assertFalse(((Boolean)function.doGetResult(null)).booleanValue()); - } - -} +package org.springframework.batch.sample.validation.valang.custom; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.List; + +import org.easymock.MockControl; + +import org.springframework.batch.sample.domain.LineItem; + +import org.springmodules.validation.valang.functions.Function; +import junit.framework.TestCase; + +public class ValidatePricesFunctionTests extends TestCase { + + private ValidatePricesFunction function; + private MockControl argumentControl; + private Function argument; + + public void setUp() { + argumentControl = MockControl.createControl(Function.class); + argument = (Function) argumentControl.getMock(); + + //create function + function = new ValidatePricesFunction(new Function[] {argument}, 0, 0); + } + + public void testItemPriceMin() throws Exception { + + //create line item with correct item price + LineItem item = new LineItem(); + item.setPrice(new BigDecimal(1.0)); + + //add it to line items list + List items = new ArrayList(); + items.add(item); + + //set return value for mock argument + argument.getResult(null); + argumentControl.setReturnValue(items,2); + argumentControl.replay(); + + //verify result - should be true - all item prices are correct + assertTrue(((Boolean)function.doGetResult(null)).booleanValue()); + + //now add line item with negative item price + item = new LineItem(); + item.setPrice(new BigDecimal(-1.0)); + items.add(item); + + //verify result - should be false - second item has invalid item price + assertFalse(((Boolean)function.doGetResult(null)).booleanValue()); + } + + public void testItemPriceMax() throws Exception { + + //create line item with correct item price + LineItem item = new LineItem(); + item.setPrice(new BigDecimal(99999999.0)); + + //add it to line items list + List items = new ArrayList(); + items.add(item); + + //set return value for mock argument + argument.getResult(null); + argumentControl.setReturnValue(items,2); + argumentControl.replay(); + + //verify result - should be true - all item prices are correct + assertTrue(((Boolean)function.doGetResult(null)).booleanValue()); + + //now add line item with item price above allowed max + item = new LineItem(); + item.setPrice(new BigDecimal(100000000.0)); + items.add(item); + + //verify result - should be false - second item has invalid item price + assertFalse(((Boolean)function.doGetResult(null)).booleanValue()); + } + +} diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/validation/valang/custom/ValidateQuantitiesFunctionTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/validation/valang/custom/ValidateQuantitiesFunctionTests.java index 836d0f51a5..40a8cd45e9 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/validation/valang/custom/ValidateQuantitiesFunctionTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/validation/valang/custom/ValidateQuantitiesFunctionTests.java @@ -1,80 +1,80 @@ -package org.springframework.batch.sample.validation.valang.custom; - -import java.util.ArrayList; -import java.util.List; - -import org.easymock.MockControl; - -import org.springframework.batch.sample.domain.LineItem; - -import org.springmodules.validation.valang.functions.Function; -import junit.framework.TestCase; - -public class ValidateQuantitiesFunctionTests extends TestCase { - - private ValidateQuantitiesFunction function; - private MockControl argumentControl; - private Function argument; - - public void setUp() { - argumentControl = MockControl.createControl(Function.class); - argument = (Function) argumentControl.getMock(); - - //create function - function = new ValidateQuantitiesFunction(new Function[] {argument}, 0, 0); - } - - public void testQuantityMin() throws Exception { - - //create line item with correct item quantity - LineItem item = new LineItem(); - item.setQuantity(1); - - //add it to line items list - List items = new ArrayList(); - items.add(item); - - //set return value for mock argument - argument.getResult(null); - argumentControl.setReturnValue(items,2); - argumentControl.replay(); - - //verify result - should be true - all quantities are correct - assertTrue(((Boolean)function.doGetResult(null)).booleanValue()); - - //now add line item with negative quantity - item = new LineItem(); - item.setQuantity(-1); - items.add(item); - - //verify result - should be false - second item has invalid quantity - assertFalse(((Boolean)function.doGetResult(null)).booleanValue()); - } - - public void testQuantityMax() throws Exception { - - //create line item with correct item quantity - LineItem item = new LineItem(); - item.setQuantity(9999); - - //add it to line items list - List items = new ArrayList(); - items.add(item); - - //set return value for mock argument - argument.getResult(null); - argumentControl.setReturnValue(items,2); - argumentControl.replay(); - - //verify result - should be true - all item quantities are correct - assertTrue(((Boolean)function.doGetResult(null)).booleanValue()); - - //now add line item with item quantity above allowed max - item = new LineItem(); - item.setQuantity(10000); - items.add(item); - - //verify result - should be false - second item has invalid item quantity - assertFalse(((Boolean)function.doGetResult(null)).booleanValue()); - } -} +package org.springframework.batch.sample.validation.valang.custom; + +import java.util.ArrayList; +import java.util.List; + +import org.easymock.MockControl; + +import org.springframework.batch.sample.domain.LineItem; + +import org.springmodules.validation.valang.functions.Function; +import junit.framework.TestCase; + +public class ValidateQuantitiesFunctionTests extends TestCase { + + private ValidateQuantitiesFunction function; + private MockControl argumentControl; + private Function argument; + + public void setUp() { + argumentControl = MockControl.createControl(Function.class); + argument = (Function) argumentControl.getMock(); + + //create function + function = new ValidateQuantitiesFunction(new Function[] {argument}, 0, 0); + } + + public void testQuantityMin() throws Exception { + + //create line item with correct item quantity + LineItem item = new LineItem(); + item.setQuantity(1); + + //add it to line items list + List items = new ArrayList(); + items.add(item); + + //set return value for mock argument + argument.getResult(null); + argumentControl.setReturnValue(items,2); + argumentControl.replay(); + + //verify result - should be true - all quantities are correct + assertTrue(((Boolean)function.doGetResult(null)).booleanValue()); + + //now add line item with negative quantity + item = new LineItem(); + item.setQuantity(-1); + items.add(item); + + //verify result - should be false - second item has invalid quantity + assertFalse(((Boolean)function.doGetResult(null)).booleanValue()); + } + + public void testQuantityMax() throws Exception { + + //create line item with correct item quantity + LineItem item = new LineItem(); + item.setQuantity(9999); + + //add it to line items list + List items = new ArrayList(); + items.add(item); + + //set return value for mock argument + argument.getResult(null); + argumentControl.setReturnValue(items,2); + argumentControl.replay(); + + //verify result - should be true - all item quantities are correct + assertTrue(((Boolean)function.doGetResult(null)).booleanValue()); + + //now add line item with item quantity above allowed max + item = new LineItem(); + item.setQuantity(10000); + items.add(item); + + //verify result - should be false - second item has invalid item quantity + assertFalse(((Boolean)function.doGetResult(null)).booleanValue()); + } +} diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/validation/valang/custom/ValidateShippingPricesFunctionTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/validation/valang/custom/ValidateShippingPricesFunctionTests.java index 51b1d1c413..dec88491ec 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/validation/valang/custom/ValidateShippingPricesFunctionTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/validation/valang/custom/ValidateShippingPricesFunctionTests.java @@ -1,81 +1,81 @@ -package org.springframework.batch.sample.validation.valang.custom; - -import java.math.BigDecimal; -import java.util.ArrayList; -import java.util.List; - -import org.easymock.MockControl; - -import org.springframework.batch.sample.domain.LineItem; - -import org.springmodules.validation.valang.functions.Function; -import junit.framework.TestCase; - -public class ValidateShippingPricesFunctionTests extends TestCase { - - private ValidateShippingPricesFunction function; - private MockControl argumentControl; - private Function argument; - - public void setUp() { - argumentControl = MockControl.createControl(Function.class); - argument = (Function) argumentControl.getMock(); - - //create function - function = new ValidateShippingPricesFunction(new Function[] {argument}, 0, 0); - } - - public void testShippingPriceMin() throws Exception { - - //create line item with correct shipping price - LineItem item = new LineItem(); - item.setShippingPrice(new BigDecimal(1.0)); - - //add it to line items list - List items = new ArrayList(); - items.add(item); - - //set return value for mock argument - argument.getResult(null); - argumentControl.setReturnValue(items,2); - argumentControl.replay(); - - //verify result - should be true - all shipping prices are correct - assertTrue(((Boolean)function.doGetResult(null)).booleanValue()); - - //now add line item with negative shipping price - item = new LineItem(); - item.setShippingPrice(new BigDecimal(-1.0)); - items.add(item); - - //verify result - should be false - second item has invalid shipping price - assertFalse(((Boolean)function.doGetResult(null)).booleanValue()); - } - - public void testShippingPriceMax() throws Exception { - - //create line item with correct shipping price - LineItem item = new LineItem(); - item.setShippingPrice(new BigDecimal(99999999.0)); - - //add it to line items list - List items = new ArrayList(); - items.add(item); - - //set return value for mock argument - argument.getResult(null); - argumentControl.setReturnValue(items,2); - argumentControl.replay(); - - //verify result - should be true - all shipping prices are correct - assertTrue(((Boolean)function.doGetResult(null)).booleanValue()); - - //now add line item with shipping price above allowed max - item = new LineItem(); - item.setShippingPrice(new BigDecimal(100000000.0)); - items.add(item); - - //verify result - should be false - second item has invalid shipping price - assertFalse(((Boolean)function.doGetResult(null)).booleanValue()); - } -} +package org.springframework.batch.sample.validation.valang.custom; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.List; + +import org.easymock.MockControl; + +import org.springframework.batch.sample.domain.LineItem; + +import org.springmodules.validation.valang.functions.Function; +import junit.framework.TestCase; + +public class ValidateShippingPricesFunctionTests extends TestCase { + + private ValidateShippingPricesFunction function; + private MockControl argumentControl; + private Function argument; + + public void setUp() { + argumentControl = MockControl.createControl(Function.class); + argument = (Function) argumentControl.getMock(); + + //create function + function = new ValidateShippingPricesFunction(new Function[] {argument}, 0, 0); + } + + public void testShippingPriceMin() throws Exception { + + //create line item with correct shipping price + LineItem item = new LineItem(); + item.setShippingPrice(new BigDecimal(1.0)); + + //add it to line items list + List items = new ArrayList(); + items.add(item); + + //set return value for mock argument + argument.getResult(null); + argumentControl.setReturnValue(items,2); + argumentControl.replay(); + + //verify result - should be true - all shipping prices are correct + assertTrue(((Boolean)function.doGetResult(null)).booleanValue()); + + //now add line item with negative shipping price + item = new LineItem(); + item.setShippingPrice(new BigDecimal(-1.0)); + items.add(item); + + //verify result - should be false - second item has invalid shipping price + assertFalse(((Boolean)function.doGetResult(null)).booleanValue()); + } + + public void testShippingPriceMax() throws Exception { + + //create line item with correct shipping price + LineItem item = new LineItem(); + item.setShippingPrice(new BigDecimal(99999999.0)); + + //add it to line items list + List items = new ArrayList(); + items.add(item); + + //set return value for mock argument + argument.getResult(null); + argumentControl.setReturnValue(items,2); + argumentControl.replay(); + + //verify result - should be true - all shipping prices are correct + assertTrue(((Boolean)function.doGetResult(null)).booleanValue()); + + //now add line item with shipping price above allowed max + item = new LineItem(); + item.setShippingPrice(new BigDecimal(100000000.0)); + items.add(item); + + //verify result - should be false - second item has invalid shipping price + assertFalse(((Boolean)function.doGetResult(null)).booleanValue()); + } +} diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/validation/valang/custom/ValidateTotalPricesFunctionTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/validation/valang/custom/ValidateTotalPricesFunctionTests.java index 3ef27e2cf2..1d4b8ca6eb 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/validation/valang/custom/ValidateTotalPricesFunctionTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/validation/valang/custom/ValidateTotalPricesFunctionTests.java @@ -1,133 +1,133 @@ -package org.springframework.batch.sample.validation.valang.custom; - -import java.math.BigDecimal; -import java.util.ArrayList; -import java.util.List; - -import org.easymock.MockControl; - -import org.springframework.batch.sample.domain.LineItem; - -import org.springmodules.validation.valang.functions.Function; -import junit.framework.TestCase; - -public class ValidateTotalPricesFunctionTests extends TestCase { - - private ValidateTotalPricesFunction function; - private MockControl argumentControl; - private Function argument; - - public void setUp() { - argumentControl = MockControl.createControl(Function.class); - argument = (Function) argumentControl.getMock(); - - //create function - function = new ValidateTotalPricesFunction(new Function[] {argument}, 0, 0); - } - - public void testTotalPriceMin() throws Exception { - - //create line item with correct total price - LineItem item = new LineItem(); - item.setDiscountAmount(new BigDecimal(0.0)); - item.setDiscountPerc(new BigDecimal(0.0)); - item.setHandlingPrice(new BigDecimal(0.0)); - item.setShippingPrice(new BigDecimal(0.0)); - item.setPrice(new BigDecimal(1.0)); - item.setQuantity(1); - item.setTotalPrice(new BigDecimal(1.0)); - - //add it to line items list - List items = new ArrayList(); - items.add(item); - - //set return value for mock argument - argument.getResult(null); - argumentControl.setReturnValue(items,2); - argumentControl.replay(); - - //verify result - should be true - all total prices are correct - assertTrue(((Boolean)function.doGetResult(null)).booleanValue()); - - //now add line item with negative item price - item = new LineItem(); - item.setTotalPrice(new BigDecimal(-1.0)); - items.add(item); - - //verify result - should be false - second item has invalid total price - assertFalse(((Boolean)function.doGetResult(null)).booleanValue()); - } - - public void testTotalPriceMax() throws Exception { - - //create line item with correct total price - LineItem item = new LineItem(); - item.setDiscountAmount(new BigDecimal(0.0)); - item.setDiscountPerc(new BigDecimal(0.0)); - item.setHandlingPrice(new BigDecimal(0.0)); - item.setShippingPrice(new BigDecimal(0.0)); - item.setPrice(new BigDecimal(99999999.0)); - item.setQuantity(1); - item.setTotalPrice(new BigDecimal(99999999.0)); - - //add it to line items list - List items = new ArrayList(); - items.add(item); - - //set return value for mock argument - argument.getResult(null); - argumentControl.setReturnValue(items,2); - argumentControl.replay(); - - //verify result - should be true - all total prices are correct - assertTrue(((Boolean)function.doGetResult(null)).booleanValue()); - - //now add line item with total price above allowed max - item = new LineItem(); - item.setTotalPrice(new BigDecimal(100000000.0)); - items.add(item); - - //verify result - should be false - second item has invalid total price - assertFalse(((Boolean)function.doGetResult(null)).booleanValue()); - } - - public void testTotalPriceCalculation() throws Exception { - - //create line item - LineItem item = new LineItem(); - item.setDiscountAmount(new BigDecimal(5.0)); - item.setDiscountPerc(new BigDecimal(0.0)); - item.setHandlingPrice(new BigDecimal(1.0)); - item.setShippingPrice(new BigDecimal(2.0)); - item.setPrice(new BigDecimal(250.0)); - item.setQuantity(1); - item.setTotalPrice(new BigDecimal(248.0)); - - //add it to line items list - List items = new ArrayList(); - items.add(item); - - //set return value for mock argument - argument.getResult(null); - argumentControl.setReturnValue(items,2); - argumentControl.replay(); - - //verify result - should be true - all total prices are correct - assertTrue(((Boolean)function.doGetResult(null)).booleanValue()); - - //now add line item with incorrect total price - item = new LineItem(); - item.setDiscountAmount(new BigDecimal(5.0)); - item.setDiscountPerc(new BigDecimal(0.0)); - item.setHandlingPrice(new BigDecimal(1.0)); - item.setShippingPrice(new BigDecimal(2.0)); - item.setPrice(new BigDecimal(250.0)); - item.setQuantity(1); - item.setTotalPrice(new BigDecimal(253.0)); - - items.add(item); - - //verify result - should be false - second item has incorrect total price - assertFalse(((Boolean)function.doGetResult(null)).booleanValue()); - } -} +package org.springframework.batch.sample.validation.valang.custom; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.List; + +import org.easymock.MockControl; + +import org.springframework.batch.sample.domain.LineItem; + +import org.springmodules.validation.valang.functions.Function; +import junit.framework.TestCase; + +public class ValidateTotalPricesFunctionTests extends TestCase { + + private ValidateTotalPricesFunction function; + private MockControl argumentControl; + private Function argument; + + public void setUp() { + argumentControl = MockControl.createControl(Function.class); + argument = (Function) argumentControl.getMock(); + + //create function + function = new ValidateTotalPricesFunction(new Function[] {argument}, 0, 0); + } + + public void testTotalPriceMin() throws Exception { + + //create line item with correct total price + LineItem item = new LineItem(); + item.setDiscountAmount(new BigDecimal(0.0)); + item.setDiscountPerc(new BigDecimal(0.0)); + item.setHandlingPrice(new BigDecimal(0.0)); + item.setShippingPrice(new BigDecimal(0.0)); + item.setPrice(new BigDecimal(1.0)); + item.setQuantity(1); + item.setTotalPrice(new BigDecimal(1.0)); + + //add it to line items list + List items = new ArrayList(); + items.add(item); + + //set return value for mock argument + argument.getResult(null); + argumentControl.setReturnValue(items,2); + argumentControl.replay(); + + //verify result - should be true - all total prices are correct + assertTrue(((Boolean)function.doGetResult(null)).booleanValue()); + + //now add line item with negative item price + item = new LineItem(); + item.setTotalPrice(new BigDecimal(-1.0)); + items.add(item); + + //verify result - should be false - second item has invalid total price + assertFalse(((Boolean)function.doGetResult(null)).booleanValue()); + } + + public void testTotalPriceMax() throws Exception { + + //create line item with correct total price + LineItem item = new LineItem(); + item.setDiscountAmount(new BigDecimal(0.0)); + item.setDiscountPerc(new BigDecimal(0.0)); + item.setHandlingPrice(new BigDecimal(0.0)); + item.setShippingPrice(new BigDecimal(0.0)); + item.setPrice(new BigDecimal(99999999.0)); + item.setQuantity(1); + item.setTotalPrice(new BigDecimal(99999999.0)); + + //add it to line items list + List items = new ArrayList(); + items.add(item); + + //set return value for mock argument + argument.getResult(null); + argumentControl.setReturnValue(items,2); + argumentControl.replay(); + + //verify result - should be true - all total prices are correct + assertTrue(((Boolean)function.doGetResult(null)).booleanValue()); + + //now add line item with total price above allowed max + item = new LineItem(); + item.setTotalPrice(new BigDecimal(100000000.0)); + items.add(item); + + //verify result - should be false - second item has invalid total price + assertFalse(((Boolean)function.doGetResult(null)).booleanValue()); + } + + public void testTotalPriceCalculation() throws Exception { + + //create line item + LineItem item = new LineItem(); + item.setDiscountAmount(new BigDecimal(5.0)); + item.setDiscountPerc(new BigDecimal(0.0)); + item.setHandlingPrice(new BigDecimal(1.0)); + item.setShippingPrice(new BigDecimal(2.0)); + item.setPrice(new BigDecimal(250.0)); + item.setQuantity(1); + item.setTotalPrice(new BigDecimal(248.0)); + + //add it to line items list + List items = new ArrayList(); + items.add(item); + + //set return value for mock argument + argument.getResult(null); + argumentControl.setReturnValue(items,2); + argumentControl.replay(); + + //verify result - should be true - all total prices are correct + assertTrue(((Boolean)function.doGetResult(null)).booleanValue()); + + //now add line item with incorrect total price + item = new LineItem(); + item.setDiscountAmount(new BigDecimal(5.0)); + item.setDiscountPerc(new BigDecimal(0.0)); + item.setHandlingPrice(new BigDecimal(1.0)); + item.setShippingPrice(new BigDecimal(2.0)); + item.setPrice(new BigDecimal(250.0)); + item.setQuantity(1); + item.setTotalPrice(new BigDecimal(253.0)); + + items.add(item); + + //verify result - should be false - second item has incorrect total price + assertFalse(((Boolean)function.doGetResult(null)).booleanValue()); + } +} diff --git a/src/.project b/src/.project index 6897b1e456..2a1cf817c8 100644 --- a/src/.project +++ b/src/.project @@ -1,24 +1,14 @@ - - - src - - - - - - org.eclipse.jdt.core.javabuilder - - - - - - org.eclipse.jdt.core.javanature - - - - pom.xml - 1 - PARENT/pom.xml - - - + + + src + + + + + + pom.xml + 1 + PARENT/pom.xml + + + diff --git a/src/.settings/org.eclipse.mylyn.tasks.ui.prefs b/src/.settings/org.eclipse.mylyn.tasks.ui.prefs index 0f8c117dd5..0b6c22e768 100644 --- a/src/.settings/org.eclipse.mylyn.tasks.ui.prefs +++ b/src/.settings/org.eclipse.mylyn.tasks.ui.prefs @@ -1,4 +1,4 @@ -#Thu Aug 23 07:01:54 BST 2007 -eclipse.preferences.version=1 -project.repository.kind=jira -project.repository.url=http\://opensource.atlassian.com/projects/spring +#Thu Aug 23 07:01:54 BST 2007 +eclipse.preferences.version=1 +project.repository.kind=jira +project.repository.url=http\://opensource.atlassian.com/projects/spring diff --git a/src/main/xsl/emma.xsl b/src/main/xsl/emma.xsl index e01fe5cbdd..48619c77ab 100644 --- a/src/main/xsl/emma.xsl +++ b/src/main/xsl/emma.xsl @@ -1,17 +1,17 @@ - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + diff --git a/src/site/apt/building.apt b/src/site/apt/building.apt index d444714f9f..7d2f73953b 100644 --- a/src/site/apt/building.apt +++ b/src/site/apt/building.apt @@ -90,6 +90,21 @@ $ mvn -P snapshots dependency:tree We use the "snapshots" profile here so that we get a snapshot of the dependency plugin (older versions did not have the tree goal, but newer versions are not stable enough to use in production). + +* Subversion and Line Endings + + Please use + ++--- +*.xml = svn:eol-style=LF +*.sql = svn:eol-style=LF +*.txt = svn:eol-style=LF +*.java = svn:eol-style=LF +*.apt = svn:eol-style=LF +*.properties = svn:eol-style=LF ++--- + + in your <<<~/.subversion>>> (or <<\Application Data\Subversion/config>>>). If anyone forgets to do that then the property can be recursively set using Tortoise (type in the property key and value and use the recursive checkbox). * Documentation diff --git a/src/site/apt/migration/1.0-m2-m3.apt b/src/site/apt/migration/1.0-m2-m3.apt index 0629cebb9d..0e7766e65e 100644 --- a/src/site/apt/migration/1.0-m2-m3.apt +++ b/src/site/apt/migration/1.0-m2-m3.apt @@ -1,67 +1,67 @@ - ------ - Spring Batch Upgrade - ------ - Robert Kasanicky - ------ - December 2007 - -Updating Spring Batch from 1.0-m2 to 1.0-m3 - - This is a description of what needed to be done to migrate the samples from m2 to the new m3 release. - - [Tip:] if you use SpringIDE, make sure it tracks all your configuration files, -so that errors are immediately visible. - -* VARIOUS - - * OutputSource interface has been renamed to ItemWriter, implementations have been renamed correspondingly -(e.g. FlatFileOutputSource is now FlatFileItemWriter). ItemWriter no longer extends ResourceLifecycle -(which declares methods open() and close). Often you don't need to call these methods at all, in case -you do you should implement InitializingBean and DisposableBean interfaces and declare the bean -in step scope. - - * Sql renamed to Jdbc (e.g. SqlInputSource -> JdbcInputSource). - - * Database input sources split into driving and cursor packages (cursor makes a single query and iterates -over the result set, driving query for keys and then make a new query for each key). - - * ExceptionHandler interface has been changed to handle single throwable instead of a collection of throwables -and it has become responsible for deciding about step completion. See javadoc for more details. - - * FlatFileInputSources now include FieldSet mapping logic - you can inject a FieldSetMapper -into the input source, so you no longer need to handle this in ItemProvider. Therefore -FieldSetInputSource interface and FlatFileItemProvider have been removed. Where FlatFileItemProvider -was used you can use the InputSourceItemProvider and inject the mapper into the input source. - - * Validation has been removed from input sources and moved upwards to ValidatingItemProvider. - - * XML related classes have been moved from io.stax package under io.file - - * Fixed-length tokenizer accept ranges property instead of array of lengths, e.g. "2,3" -(see javadoc for more details and fixedLengthImportJob.xml for example usage). - - -* CONTAINER CONFIGURATION - - * Use the value of JobConfiguration name property as the bean id. - - * Simplest approach to update is to use the simple-container-definition.xml, -data-source-context.xml (plus hibernate-context.xml) and batch.properties -from M3 samples and replace the post-processor bean in your job xml file with -"\" - - * JobLauncher has been moved from execution.bootstrap to execution.launch - - * JobExecutor facade has been removed, it's properties are now injected directly -into SimpleJobLauncher intead of the facade itself. - - * DefaultStepExecutorFactory is now SimpleStepExecutorFactory located in simple subpackage -and needs a reference to jobRepository instead of value for StepExecutor name. - - * ScheduledJobIdentifier has a new jobKey property replaces jobRun and jobStream. - - * SimpleStepConfiguration has been moved one package up (from execution.step.simple to execution.step). - - * Transaction manager class is specified in batch.properties - - + ------ + Spring Batch Upgrade + ------ + Robert Kasanicky + ------ + December 2007 + +Updating Spring Batch from 1.0-m2 to 1.0-m3 + + This is a description of what needed to be done to migrate the samples from m2 to the new m3 release. + + [Tip:] if you use SpringIDE, make sure it tracks all your configuration files, +so that errors are immediately visible. + +* VARIOUS + + * OutputSource interface has been renamed to ItemWriter, implementations have been renamed correspondingly +(e.g. FlatFileOutputSource is now FlatFileItemWriter). ItemWriter no longer extends ResourceLifecycle +(which declares methods open() and close). Often you don't need to call these methods at all, in case +you do you should implement InitializingBean and DisposableBean interfaces and declare the bean +in step scope. + + * Sql renamed to Jdbc (e.g. SqlInputSource -> JdbcInputSource). + + * Database input sources split into driving and cursor packages (cursor makes a single query and iterates +over the result set, driving query for keys and then make a new query for each key). + + * ExceptionHandler interface has been changed to handle single throwable instead of a collection of throwables +and it has become responsible for deciding about step completion. See javadoc for more details. + + * FlatFileInputSources now include FieldSet mapping logic - you can inject a FieldSetMapper +into the input source, so you no longer need to handle this in ItemProvider. Therefore +FieldSetInputSource interface and FlatFileItemProvider have been removed. Where FlatFileItemProvider +was used you can use the InputSourceItemProvider and inject the mapper into the input source. + + * Validation has been removed from input sources and moved upwards to ValidatingItemProvider. + + * XML related classes have been moved from io.stax package under io.file + + * Fixed-length tokenizer accept ranges property instead of array of lengths, e.g. "2,3" +(see javadoc for more details and fixedLengthImportJob.xml for example usage). + + +* CONTAINER CONFIGURATION + + * Use the value of JobConfiguration name property as the bean id. + + * Simplest approach to update is to use the simple-container-definition.xml, +data-source-context.xml (plus hibernate-context.xml) and batch.properties +from M3 samples and replace the post-processor bean in your job xml file with +"\" + + * JobLauncher has been moved from execution.bootstrap to execution.launch + + * JobExecutor facade has been removed, it's properties are now injected directly +into SimpleJobLauncher intead of the facade itself. + + * DefaultStepExecutorFactory is now SimpleStepExecutorFactory located in simple subpackage +and needs a reference to jobRepository instead of value for StepExecutor name. + + * ScheduledJobIdentifier has a new jobKey property replaces jobRun and jobStream. + + * SimpleStepConfiguration has been moved one package up (from execution.step.simple to execution.step). + + * Transaction manager class is specified in batch.properties + + diff --git a/src/site/apt/migration/1.0-m3-m4.apt b/src/site/apt/migration/1.0-m3-m4.apt index 534ed9934f..f8cf4a196f 100644 --- a/src/site/apt/migration/1.0-m3-m4.apt +++ b/src/site/apt/migration/1.0-m3-m4.apt @@ -1,59 +1,59 @@ - ------ - Spring Batch Upgrade - ------ - Robert Kasanicky - ------ - February 2008 - -Updating Spring Batch jobs from 1.0.0.m3 to 1.0.0.m4 framework - - This is a description of what needed to be done to migrate the samples -from m3 to the m4 release. - - [Tip:] if you use SpringIDE, make sure it tracks all your configuration -files, so that errors are immediately visible. - -* JOB CONFIGURATION - - * ItemProviderTasklet and RestartableItemProviderTasklet have been replaced -with ItemOrientedTasklet - - * ItemProvider/ItemProcessor pair is now ItemReader/ItemWriter - - * InputSource and ItemProvider interfaces have been merged into ItemReader -(ItemReaders can be composite when desired) - - * OutputSource and ItemProcessor interfaces have been merged into ItemWriter -(ItemTransformerItemWriter and CompositeItemTransformer provide support for -item transformations before writing to output) - - * JobConfiguration and Step Configuration are now called simply Job and Step. There is no JobExecutor or StepExecutor. - -* CONTAINER CONFIGURATION - - * JobIdentifier is replaced by JobParameters - - * JobLauncher#run(Job, JobParameters) now returns JobExecution which has -methods stop() and isRunnig() (previously part of JobLauncher) - - * Hibernate repository (JobDao and StepDao) has been removed - - * JobExecutor and StepExecutor are no longer explicitly declared -(Job and Step execute themselves) - - -* VARIOUS - - * Remember to update the database schema - - * Several moves and package renames easily fixed by IDE refactoring support -('organize imports' in Eclipse) - - * FieldSet is now an interface with DefaultFieldSet as provided implementation - - * ResourceLifecycle and Restartable interfaces have been removed, ItemStream -now covers their responsibilities - - * StatisticsProvider interface has been superceded by ExecutionAttributesProvider - - * BatchTransationSynchronizationManager has been removed. Use the regular TransactionSynchronizationManager if you need to register a synchronization. + ------ + Spring Batch Upgrade + ------ + Robert Kasanicky + ------ + February 2008 + +Updating Spring Batch jobs from 1.0.0.m3 to 1.0.0.m4 framework + + This is a description of what needed to be done to migrate the samples +from m3 to the m4 release. + + [Tip:] if you use SpringIDE, make sure it tracks all your configuration +files, so that errors are immediately visible. + +* JOB CONFIGURATION + + * ItemProviderTasklet and RestartableItemProviderTasklet have been replaced +with ItemOrientedTasklet + + * ItemProvider/ItemProcessor pair is now ItemReader/ItemWriter + + * InputSource and ItemProvider interfaces have been merged into ItemReader +(ItemReaders can be composite when desired) + + * OutputSource and ItemProcessor interfaces have been merged into ItemWriter +(ItemTransformerItemWriter and CompositeItemTransformer provide support for +item transformations before writing to output) + + * JobConfiguration and Step Configuration are now called simply Job and Step. There is no JobExecutor or StepExecutor. + +* CONTAINER CONFIGURATION + + * JobIdentifier is replaced by JobParameters + + * JobLauncher#run(Job, JobParameters) now returns JobExecution which has +methods stop() and isRunnig() (previously part of JobLauncher) + + * Hibernate repository (JobDao and StepDao) has been removed + + * JobExecutor and StepExecutor are no longer explicitly declared +(Job and Step execute themselves) + + +* VARIOUS + + * Remember to update the database schema + + * Several moves and package renames easily fixed by IDE refactoring support +('organize imports' in Eclipse) + + * FieldSet is now an interface with DefaultFieldSet as provided implementation + + * ResourceLifecycle and Restartable interfaces have been removed, ItemStream +now covers their responsibilities + + * StatisticsProvider interface has been superceded by ExecutionAttributesProvider + + * BatchTransationSynchronizationManager has been removed. Use the regular TransactionSynchronizationManager if you need to register a synchronization. diff --git a/src/site/apt/migration/1.0-m4-m5.apt b/src/site/apt/migration/1.0-m4-m5.apt index e71d2a503e..901bf04c3f 100644 --- a/src/site/apt/migration/1.0-m4-m5.apt +++ b/src/site/apt/migration/1.0-m4-m5.apt @@ -1,49 +1,49 @@ - ------ - Spring Batch Upgrade - ------ - Robert Kasanicky - ------ - March 2008 - -Updating Spring Batch jobs from 1.0.0.m4 to 1.0.0.m5 framework - - The following is a description of what is needed to migrate the samples from m4 to the m5 release. - -* JOB CONFIGURATION - - * Tasklet's role has changed - It is no longer called iteratively, but is now dedicated for tasks that are not natural to split into read-write phases (e.g. calling stored procedure or system command). Readers and writers are now typically injected into (ItemOriented)Step. See Tasklet and TaskletStep javadoc for more details. - - * Step scope removed - lifecycle of readers and writers explicitly handled by Step. They need to be registered for the lifecycle callbacks with the step. This is automatic if using one of the new step factory beans, but only for the directly injected reader and writer. Any indirect dependencies need to be registered separately (using the streams property of the factory bean). - - * When launching from command line there is one applicaton context for job rather than parent container and child job context. CommandLineJobRunner requires only one xml file location. It is recommended to use a new ApplicationContext per job execution for other use cases involving launching multiple jobs in a single VM. The JMX demo in the samples shows this in practice. - - * SimpleFlatFileItemReader and DefaultFlatFileItemReader merged into FlatFileItemReader - - * LineAggregator is now inverse to LineTokenizer - method signature changed to 'String aggregate(FieldSet)'. - - -* CONTAINER CONFIGURATION - - * Modularized repository daos - JobInstanceDao, JobExecutionDao and StepExecutionDao instead of JobDao and StepDao. - - * Step creation handled by factories. - - -* VARIOUS - - * ItemStream now has single 'open(ExecutionContext)' rather than 'open()' and 'restoreFrom(ExecutionContext)'. - - * ItemStream no longer has mark() and reset() methods - moved to ItemReader. ItemWriter uses more intuitive clear() and flush(). - - * Interceptors renamed to Listeners e.g. RepeatInterceptor is now RepeatListener. - - * StepContext merged into ExecutionContext (previously ExecutionAttributes). Single ExecutionContext is now shared between ItemStreams instead of separate contexts being composed before save and decomposed after load. ItemStreams now have names to distinguish context keys of multiple ItemStreams of the same class. - - * Domain-oriented listeners introduced - JobListener, StepListener, ChunkListener, ItemReadListener, ItemWriteListener. - - * StepInstance removed from domain model. - - * Database schema updated. - - * JobInstance identity is now given by Job and JobParameters pair - identical JobInstances with different IDs no longer allowed (see JobInstance javadoc for more details). - + ------ + Spring Batch Upgrade + ------ + Robert Kasanicky + ------ + March 2008 + +Updating Spring Batch jobs from 1.0.0.m4 to 1.0.0.m5 framework + + The following is a description of what is needed to migrate the samples from m4 to the m5 release. + +* JOB CONFIGURATION + + * Tasklet's role has changed - It is no longer called iteratively, but is now dedicated for tasks that are not natural to split into read-write phases (e.g. calling stored procedure or system command). Readers and writers are now typically injected into (ItemOriented)Step. See Tasklet and TaskletStep javadoc for more details. + + * Step scope removed - lifecycle of readers and writers explicitly handled by Step. They need to be registered for the lifecycle callbacks with the step. This is automatic if using one of the new step factory beans, but only for the directly injected reader and writer. Any indirect dependencies need to be registered separately (using the streams property of the factory bean). + + * When launching from command line there is one applicaton context for job rather than parent container and child job context. CommandLineJobRunner requires only one xml file location. It is recommended to use a new ApplicationContext per job execution for other use cases involving launching multiple jobs in a single VM. The JMX demo in the samples shows this in practice. + + * SimpleFlatFileItemReader and DefaultFlatFileItemReader merged into FlatFileItemReader + + * LineAggregator is now inverse to LineTokenizer - method signature changed to 'String aggregate(FieldSet)'. + + +* CONTAINER CONFIGURATION + + * Modularized repository daos - JobInstanceDao, JobExecutionDao and StepExecutionDao instead of JobDao and StepDao. + + * Step creation handled by factories. + + +* VARIOUS + + * ItemStream now has single 'open(ExecutionContext)' rather than 'open()' and 'restoreFrom(ExecutionContext)'. + + * ItemStream no longer has mark() and reset() methods - moved to ItemReader. ItemWriter uses more intuitive clear() and flush(). + + * Interceptors renamed to Listeners e.g. RepeatInterceptor is now RepeatListener. + + * StepContext merged into ExecutionContext (previously ExecutionAttributes). Single ExecutionContext is now shared between ItemStreams instead of separate contexts being composed before save and decomposed after load. ItemStreams now have names to distinguish context keys of multiple ItemStreams of the same class. + + * Domain-oriented listeners introduced - JobListener, StepListener, ChunkListener, ItemReadListener, ItemWriteListener. + + * StepInstance removed from domain model. + + * Database schema updated. + + * JobInstance identity is now given by Job and JobParameters pair - identical JobInstances with different IDs no longer allowed (see JobInstance javadoc for more details). + diff --git a/src/site/apt/migration/index.apt b/src/site/apt/migration/index.apt new file mode 100644 index 0000000000..3a1d9dda89 --- /dev/null +++ b/src/site/apt/migration/index.apt @@ -0,0 +1,14 @@ + ------ + Spring Batch Migration Guides + ------ + Dave Syer + ------ + March 2008 + + Links: + + * {{{1.0-m2-m3.html}1.0 m2 to m3}} + + * {{{1.0-m3-m4.html}1.0 m3 to m4}} + + * {{{1.0-m4-m5.html}1.0 m4 to m5}}