├── CONTRIBUTING.md ├── LICENSE.md ├── README.md ├── chapters ├── exercice1.adoc ├── exercice2.adoc ├── exercice3.adoc ├── exercice4.adoc ├── exercice5.adoc └── introduction.adoc ├── lab1 solution ├── Lab1.txt ├── build.xml ├── nbproject │ ├── ant-deploy.xml │ ├── build-impl.xml │ ├── genfiles.properties │ ├── private │ │ ├── private.properties │ │ ├── private.xml │ │ └── retriever │ │ │ ├── catalog.xml │ │ │ └── www.oracle.com │ │ │ └── webfolder │ │ │ └── technetwork │ │ │ └── jsc │ │ │ └── xml │ │ │ └── ns │ │ │ └── javaee │ │ │ └── index.html │ ├── project.properties │ └── project.xml ├── src │ ├── conf │ │ └── MANIFEST.MF │ └── java │ │ └── org │ │ └── glassfish │ │ └── javaee7 │ │ └── batch │ │ └── lab1 │ │ ├── BatchJobSubmitter.java │ │ ├── NetPayProcessor.java │ │ ├── PayrollDataHolderBean.java │ │ ├── PayrollInputRecord.java │ │ ├── PayrollInputRecordReader.java │ │ ├── PayrollOutputRecord.java │ │ └── PayrollOutputRecordWriter.java └── web │ ├── WEB-INF │ ├── beans.xml │ ├── classes │ │ └── META-INF │ │ │ └── batch-jobs │ │ │ └── PayrollJob.xml │ └── glassfish-web.xml │ └── index.html ├── lab1-solution.zip ├── lab2-solution.zip ├── lab2.zip ├── lab3-solution.zip ├── lab3.zip ├── lab4-solution.zip ├── lab4.zip ├── lab5-solution.zip ├── lab5.zip ├── masterLab.adoc ├── masterLab.html └── pic ├── E1.1.jpg ├── E1.1.png ├── E1.10.jpg ├── E1.10.png ├── E1.11.jpg ├── E1.11.png ├── E1.12.jpg ├── E1.12.png ├── E1.14.jpg ├── E1.14.png ├── E1.15.jpg ├── E1.15.png ├── E1.16.jpg ├── E1.16.png ├── E1.17.jpg ├── E1.17.png ├── E1.2.jpg ├── E1.2.png ├── E1.3.jpg ├── E1.3.png ├── E1.4.jpg ├── E1.4.png ├── E1.5.jpg ├── E1.5.png ├── E1.6.jpg ├── E1.6.png ├── E1.7.jpg ├── E1.7.png ├── E1.8.jpg ├── E1.8.png ├── E1.9.jpg ├── E1.9.png ├── E2.1.jpg ├── E2.1.png ├── E2.2.jpg ├── E2.2.png ├── E2.3.jpg ├── E2.3.png ├── E3.1.jpg ├── E3.1.png ├── E3.2.jpg ├── E3.2.png ├── cover.jpg └── originals ├── E1.1.png ├── E1.10.png ├── E1.11.png ├── E1.12.png ├── E1.14.png ├── E1.15.png ├── E1.16.png ├── E1.17.png ├── E1.2.png ├── E1.3.png ├── E1.4.png ├── E1.5.png ├── E1.6.png ├── E1.7.png ├── E1.8.png └── E1.9.png /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | --- 4 | 5 | # Source Code Submissions 6 | We welcome your contributions and look forward to collaborating with you. We can only accept source code repository 7 | submissions from users who have signed and returned the Oracle 8 | Contributor Agreement. You will find details and the agreement to sign at this OTN web page: 9 | [Oracle Contributor Agreement](http://www.oracle.com/technetwork/community/oca-486395.html). 10 | 11 | # Other Contrbutions 12 | For all project Submissions other than source code repository contributions, the following also applies: Oracle does 13 | not claim ownership of Your Submissions. However, in order to fulfill 14 | the purposes of this project, You must give Oracle and all Users 15 | the right to post, access, discuss, use, publish, disseminate, and refine 16 | Your Submissions. 17 | 18 | In legalese: *You hereby grant to Oracle and all 19 | Users a royalty-free, perpetual, irrevocable, worldwide, non-exclusive, 20 | and fully sub-licensable right and license, under Your intellectual 21 | property rights, to reproduce, modify, adapt, publish, translate, create 22 | derivative works from, distribute, perform, display, and use Your 23 | Submissions (in whole or part) and to incorporate or implement them in 24 | other works in any form, media, or technology now known or later 25 | developed, all subject to the obligation to retain any copyright notices 26 | included in Your Submissions. All Users, Oracle, and their 27 | sublicensees are responsible for any modifications they make to the 28 | Submissions of others.* 29 | 30 | Copyright © 2017 Oracle and/or its affiliates. All rights reserved 31 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.1 2 | 3 | 1. Definitions. 4 | 5 | 1.1. "Contributor" means each individual or entity that creates or 6 | contributes to the creation of Modifications. 7 | 8 | 1.2. "Contributor Version" means the combination of the Original 9 | Software, prior Modifications used by a Contributor (if any), and 10 | the Modifications made by that particular Contributor. 11 | 12 | 1.3. "Covered Software" means (a) the Original Software, or (b) 13 | Modifications, or (c) the combination of files containing Original 14 | Software with files containing Modifications, in each case including 15 | portions thereof. 16 | 17 | 1.4. "Executable" means the Covered Software in any form other than 18 | Source Code. 19 | 20 | 1.5. "Initial Developer" means the individual or entity that first 21 | makes Original Software available under this License. 22 | 23 | 1.6. "Larger Work" means a work which combines Covered Software or 24 | portions thereof with code not governed by the terms of this License. 25 | 26 | 1.7. "License" means this document. 27 | 28 | 1.8. "Licensable" means having the right to grant, to the maximum 29 | extent possible, whether at the time of the initial grant or 30 | subsequently acquired, any and all of the rights conveyed herein. 31 | 32 | 1.9. "Modifications" means the Source Code and Executable form of 33 | any of the following: 34 | 35 | A. Any file that results from an addition to, deletion from or 36 | modification of the contents of a file containing Original Software 37 | or previous Modifications; 38 | 39 | B. Any new file that contains any part of the Original Software or 40 | previous Modification; or 41 | 42 | C. Any new file that is contributed or otherwise made available 43 | under the terms of this License. 44 | 45 | 1.10. "Original Software" means the Source Code and Executable form 46 | of computer software code that is originally released under this 47 | License. 48 | 49 | 1.11. "Patent Claims" means any patent claim(s), now owned or 50 | hereafter acquired, including without limitation, method, process, 51 | and apparatus claims, in any patent Licensable by grantor. 52 | 53 | 1.12. "Source Code" means (a) the common form of computer software 54 | code in which modifications are made and (b) associated 55 | documentation included in or with such code. 56 | 57 | 1.13. "You" (or "Your") means an individual or a legal entity 58 | exercising rights under, and complying with all of the terms of, 59 | this License. For legal entities, "You" includes any entity which 60 | controls, is controlled by, or is under common control with You. For 61 | purposes of this definition, "control" means (a) the power, direct 62 | or indirect, to cause the direction or management of such entity, 63 | whether by contract or otherwise, or (b) ownership of more than 64 | fifty percent (50%) of the outstanding shares or beneficial 65 | ownership of such entity. 66 | 67 | 2. License Grants. 68 | 69 | 2.1. The Initial Developer Grant. 70 | 71 | Conditioned upon Your compliance with Section 3.1 below and subject 72 | to third party intellectual property claims, the Initial Developer 73 | hereby grants You a world-wide, royalty-free, non-exclusive license: 74 | 75 | (a) under intellectual property rights (other than patent or 76 | trademark) Licensable by Initial Developer, to use, reproduce, 77 | modify, display, perform, sublicense and distribute the Original 78 | Software (or portions thereof), with or without Modifications, 79 | and/or as part of a Larger Work; and 80 | 81 | (b) under Patent Claims infringed by the making, using or selling of 82 | Original Software, to make, have made, use, practice, sell, and 83 | offer for sale, and/or otherwise dispose of the Original Software 84 | (or portions thereof). 85 | 86 | (c) The licenses granted in Sections 2.1(a) and (b) are effective on 87 | the date Initial Developer first distributes or otherwise makes the 88 | Original Software available to a third party under the terms of this 89 | License. 90 | 91 | (d) Notwithstanding Section 2.1(b) above, no patent license is 92 | granted: (1) for code that You delete from the Original Software, or 93 | (2) for infringements caused by: (i) the modification of the 94 | Original Software, or (ii) the combination of the Original Software 95 | with other software or devices. 96 | 97 | 2.2. Contributor Grant. 98 | 99 | Conditioned upon Your compliance with Section 3.1 below and subject 100 | to third party intellectual property claims, each Contributor hereby 101 | grants You a world-wide, royalty-free, non-exclusive license: 102 | 103 | (a) under intellectual property rights (other than patent or 104 | trademark) Licensable by Contributor to use, reproduce, modify, 105 | display, perform, sublicense and distribute the Modifications 106 | created by such Contributor (or portions thereof), either on an 107 | unmodified basis, with other Modifications, as Covered Software 108 | and/or as part of a Larger Work; and 109 | 110 | (b) under Patent Claims infringed by the making, using, or selling 111 | of Modifications made by that Contributor either alone and/or in 112 | combination with its Contributor Version (or portions of such 113 | combination), to make, use, sell, offer for sale, have made, and/or 114 | otherwise dispose of: (1) Modifications made by that Contributor (or 115 | portions thereof); and (2) the combination of Modifications made by 116 | that Contributor with its Contributor Version (or portions of such 117 | combination). 118 | 119 | (c) The licenses granted in Sections 2.2(a) and 2.2(b) are effective 120 | on the date Contributor first distributes or otherwise makes the 121 | Modifications available to a third party. 122 | 123 | (d) Notwithstanding Section 2.2(b) above, no patent license is 124 | granted: (1) for any code that Contributor has deleted from the 125 | Contributor Version; (2) for infringements caused by: (i) third 126 | party modifications of Contributor Version, or (ii) the combination 127 | of Modifications made by that Contributor with other software 128 | (except as part of the Contributor Version) or other devices; or (3) 129 | under Patent Claims infringed by Covered Software in the absence of 130 | Modifications made by that Contributor. 131 | 132 | 3. Distribution Obligations. 133 | 134 | 3.1. Availability of Source Code. 135 | 136 | Any Covered Software that You distribute or otherwise make available 137 | in Executable form must also be made available in Source Code form 138 | and that Source Code form must be distributed only under the terms 139 | of this License. You must include a copy of this License with every 140 | copy of the Source Code form of the Covered Software You distribute 141 | or otherwise make available. You must inform recipients of any such 142 | Covered Software in Executable form as to how they can obtain such 143 | Covered Software in Source Code form in a reasonable manner on or 144 | through a medium customarily used for software exchange. 145 | 146 | 3.2. Modifications. 147 | 148 | The Modifications that You create or to which You contribute are 149 | governed by the terms of this License. You represent that You 150 | believe Your Modifications are Your original creation(s) and/or You 151 | have sufficient rights to grant the rights conveyed by this License. 152 | 153 | 3.3. Required Notices. 154 | 155 | You must include a notice in each of Your Modifications that 156 | identifies You as the Contributor of the Modification. You may not 157 | remove or alter any copyright, patent or trademark notices contained 158 | within the Covered Software, or any notices of licensing or any 159 | descriptive text giving attribution to any Contributor or the 160 | Initial Developer. 161 | 162 | 3.4. Application of Additional Terms. 163 | 164 | You may not offer or impose any terms on any Covered Software in 165 | Source Code form that alters or restricts the applicable version of 166 | this License or the recipients' rights hereunder. You may choose to 167 | offer, and to charge a fee for, warranty, support, indemnity or 168 | liability obligations to one or more recipients of Covered Software. 169 | However, you may do so only on Your own behalf, and not on behalf of 170 | the Initial Developer or any Contributor. You must make it 171 | absolutely clear that any such warranty, support, indemnity or 172 | liability obligation is offered by You alone, and You hereby agree 173 | to indemnify the Initial Developer and every Contributor for any 174 | liability incurred by the Initial Developer or such Contributor as a 175 | result of warranty, support, indemnity or liability terms You offer. 176 | 177 | 3.5. Distribution of Executable Versions. 178 | 179 | You may distribute the Executable form of the Covered Software under 180 | the terms of this License or under the terms of a license of Your 181 | choice, which may contain terms different from this License, 182 | provided that You are in compliance with the terms of this License 183 | and that the license for the Executable form does not attempt to 184 | limit or alter the recipient's rights in the Source Code form from 185 | the rights set forth in this License. If You distribute the Covered 186 | Software in Executable form under a different license, You must make 187 | it absolutely clear that any terms which differ from this License 188 | are offered by You alone, not by the Initial Developer or 189 | Contributor. You hereby agree to indemnify the Initial Developer and 190 | every Contributor for any liability incurred by the Initial 191 | Developer or such Contributor as a result of any such terms You offer. 192 | 193 | 3.6. Larger Works. 194 | 195 | You may create a Larger Work by combining Covered Software with 196 | other code not governed by the terms of this License and distribute 197 | the Larger Work as a single product. In such a case, You must make 198 | sure the requirements of this License are fulfilled for the Covered 199 | Software. 200 | 201 | 4. Versions of the License. 202 | 203 | 4.1. New Versions. 204 | 205 | Oracle is the initial license steward and may publish revised and/or 206 | new versions of this License from time to time. Each version will be 207 | given a distinguishing version number. Except as provided in Section 208 | 4.3, no one other than the license steward has the right to modify 209 | this License. 210 | 211 | 4.2. Effect of New Versions. 212 | 213 | You may always continue to use, distribute or otherwise make the 214 | Covered Software available under the terms of the version of the 215 | License under which You originally received the Covered Software. If 216 | the Initial Developer includes a notice in the Original Software 217 | prohibiting it from being distributed or otherwise made available 218 | under any subsequent version of the License, You must distribute and 219 | make the Covered Software available under the terms of the version 220 | of the License under which You originally received the Covered 221 | Software. Otherwise, You may also choose to use, distribute or 222 | otherwise make the Covered Software available under the terms of any 223 | subsequent version of the License published by the license steward. 224 | 225 | 4.3. Modified Versions. 226 | 227 | When You are an Initial Developer and You want to create a new 228 | license for Your Original Software, You may create and use a 229 | modified version of this License if You: (a) rename the license and 230 | remove any references to the name of the license steward (except to 231 | note that the license differs from this License); and (b) otherwise 232 | make it clear that the license contains terms which differ from this 233 | License. 234 | 235 | 5. DISCLAIMER OF WARRANTY. 236 | 237 | COVERED SOFTWARE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, 238 | WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, 239 | INCLUDING, WITHOUT LIMITATION, WARRANTIES THAT THE COVERED SOFTWARE 240 | IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR 241 | NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF 242 | THE COVERED SOFTWARE IS WITH YOU. SHOULD ANY COVERED SOFTWARE PROVE 243 | DEFECTIVE IN ANY RESPECT, YOU (NOT THE INITIAL DEVELOPER OR ANY 244 | OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY SERVICING, 245 | REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN 246 | ESSENTIAL PART OF THIS LICENSE. NO USE OF ANY COVERED SOFTWARE IS 247 | AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER. 248 | 249 | 6. TERMINATION. 250 | 251 | 6.1. This License and the rights granted hereunder will terminate 252 | automatically if You fail to comply with terms herein and fail to 253 | cure such breach within 30 days of becoming aware of the breach. 254 | Provisions which, by their nature, must remain in effect beyond the 255 | termination of this License shall survive. 256 | 257 | 6.2. If You assert a patent infringement claim (excluding 258 | declaratory judgment actions) against Initial Developer or a 259 | Contributor (the Initial Developer or Contributor against whom You 260 | assert such claim is referred to as "Participant") alleging that the 261 | Participant Software (meaning the Contributor Version where the 262 | Participant is a Contributor or the Original Software where the 263 | Participant is the Initial Developer) directly or indirectly 264 | infringes any patent, then any and all rights granted directly or 265 | indirectly to You by such Participant, the Initial Developer (if the 266 | Initial Developer is not the Participant) and all Contributors under 267 | Sections 2.1 and/or 2.2 of this License shall, upon 60 days notice 268 | from Participant terminate prospectively and automatically at the 269 | expiration of such 60 day notice period, unless if within such 60 270 | day period You withdraw Your claim with respect to the Participant 271 | Software against such Participant either unilaterally or pursuant to 272 | a written agreement with Participant. 273 | 274 | 6.3. If You assert a patent infringement claim against Participant 275 | alleging that the Participant Software directly or indirectly 276 | infringes any patent where such claim is resolved (such as by 277 | license or settlement) prior to the initiation of patent 278 | infringement litigation, then the reasonable value of the licenses 279 | granted by such Participant under Sections 2.1 or 2.2 shall be taken 280 | into account in determining the amount or value of any payment or 281 | license. 282 | 283 | 6.4. In the event of termination under Sections 6.1 or 6.2 above, 284 | all end user licenses that have been validly granted by You or any 285 | distributor hereunder prior to termination (excluding licenses 286 | granted to You by any distributor) shall survive termination. 287 | 288 | 7. LIMITATION OF LIABILITY. 289 | 290 | UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT 291 | (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL YOU, THE 292 | INITIAL DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF 293 | COVERED SOFTWARE, OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE 294 | TO ANY PERSON FOR ANY INDIRECT, SPECIAL, INCIDENTAL, OR 295 | CONSEQUENTIAL DAMAGES OF ANY CHARACTER INCLUDING, WITHOUT 296 | LIMITATION, DAMAGES FOR LOSS OF GOODWILL, WORK STOPPAGE, COMPUTER 297 | FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER COMMERCIAL DAMAGES OR 298 | LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN INFORMED OF THE 299 | POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF LIABILITY SHALL NOT 300 | APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY RESULTING FROM SUCH 301 | PARTY'S NEGLIGENCE TO THE EXTENT APPLICABLE LAW PROHIBITS SUCH 302 | LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OR 303 | LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THIS EXCLUSION 304 | AND LIMITATION MAY NOT APPLY TO YOU. 305 | 306 | 8. U.S. GOVERNMENT END USERS. 307 | 308 | The Covered Software is a "commercial item," as that term is defined 309 | in 48 C.F.R. 2.101 (Oct. 1995), consisting of "commercial computer 310 | software" (as that term is defined at 48 C.F.R. § 311 | 252.227-7014(a)(1)) and "commercial computer software documentation" 312 | as such terms are used in 48 C.F.R. 12.212 (Sept. 1995). Consistent 313 | with 48 C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 314 | (June 1995), all U.S. Government End Users acquire Covered Software 315 | with only those rights set forth herein. This U.S. Government Rights 316 | clause is in lieu of, and supersedes, any other FAR, DFAR, or other 317 | clause or provision that addresses Government rights in computer 318 | software under this License. 319 | 320 | 9. MISCELLANEOUS. 321 | 322 | This License represents the complete agreement concerning subject 323 | matter hereof. If any provision of this License is held to be 324 | unenforceable, such provision shall be reformed only to the extent 325 | necessary to make it enforceable. This License shall be governed by 326 | the law of the jurisdiction specified in a notice contained within 327 | the Original Software (except to the extent applicable law, if any, 328 | provides otherwise), excluding such jurisdiction's conflict-of-law 329 | provisions. Any litigation relating to this License shall be subject 330 | to the jurisdiction of the courts located in the jurisdiction and 331 | venue specified in a notice contained within the Original Software, 332 | with the losing party responsible for costs, including, without 333 | limitation, court costs and reasonable attorneys' fees and expenses. 334 | The application of the United Nations Convention on Contracts for 335 | the International Sale of Goods is expressly excluded. Any law or 336 | regulation which provides that the language of a contract shall be 337 | construed against the drafter shall not apply to this License. You 338 | agree that You alone are responsible for compliance with the United 339 | States export administration regulations (and the export control 340 | laws and regulation of any other countries) when You use, distribute 341 | or otherwise make available any Covered Software. 342 | 343 | 10. RESPONSIBILITY FOR CLAIMS. 344 | 345 | As between Initial Developer and the Contributors, each party is 346 | responsible for claims and damages arising, directly or indirectly, 347 | out of its utilization of rights under this License and You agree to 348 | work with Initial Developer and Contributors to distribute such 349 | responsibility on an equitable basis. Nothing herein is intended or 350 | shall be deemed to constitute any admission of liability. 351 | 352 | ------------------------------------------------------------------------ 353 | 354 | NOTICE PURSUANT TO SECTION 9 OF THE COMMON DEVELOPMENT AND DISTRIBUTION 355 | LICENSE (CDDL) 356 | 357 | The code released under the CDDL shall be governed by the laws of the 358 | State of California (excluding conflict-of-law provisions). Any 359 | litigation relating to this License shall be subject to the jurisdiction 360 | of the Federal Courts of the Northern District of California and the 361 | state courts of the State of California, with venue lying in Santa Clara 362 | County, California. 363 | 364 | 365 | 366 | # The GNU General Public License (GPL) Version 2, June 1991 367 | 368 | Copyright (C) 1989, 1991 Free Software Foundation, Inc. 369 | 51 Franklin Street, Fifth Floor 370 | Boston, MA 02110-1335 371 | USA 372 | 373 | Everyone is permitted to copy and distribute verbatim copies 374 | of this license document, but changing it is not allowed. 375 | 376 | Preamble 377 | 378 | The licenses for most software are designed to take away your freedom to 379 | share and change it. By contrast, the GNU General Public License is 380 | intended to guarantee your freedom to share and change free software--to 381 | make sure the software is free for all its users. This General Public 382 | License applies to most of the Free Software Foundation's software and 383 | to any other program whose authors commit to using it. (Some other Free 384 | Software Foundation software is covered by the GNU Library General 385 | Public License instead.) You can apply it to your programs, too. 386 | 387 | When we speak of free software, we are referring to freedom, not price. 388 | Our General Public Licenses are designed to make sure that you have the 389 | freedom to distribute copies of free software (and charge for this 390 | service if you wish), that you receive source code or can get it if you 391 | want it, that you can change the software or use pieces of it in new 392 | free programs; and that you know you can do these things. 393 | 394 | To protect your rights, we need to make restrictions that forbid anyone 395 | to deny you these rights or to ask you to surrender the rights. These 396 | restrictions translate to certain responsibilities for you if you 397 | distribute copies of the software, or if you modify it. 398 | 399 | For example, if you distribute copies of such a program, whether gratis 400 | or for a fee, you must give the recipients all the rights that you have. 401 | You must make sure that they, too, receive or can get the source code. 402 | And you must show them these terms so they know their rights. 403 | 404 | We protect your rights with two steps: (1) copyright the software, and 405 | (2) offer you this license which gives you legal permission to copy, 406 | distribute and/or modify the software. 407 | 408 | Also, for each author's protection and ours, we want to make certain 409 | that everyone understands that there is no warranty for this free 410 | software. If the software is modified by someone else and passed on, we 411 | want its recipients to know that what they have is not the original, so 412 | that any problems introduced by others will not reflect on the original 413 | authors' reputations. 414 | 415 | Finally, any free program is threatened constantly by software patents. 416 | We wish to avoid the danger that redistributors of a free program will 417 | individually obtain patent licenses, in effect making the program 418 | proprietary. To prevent this, we have made it clear that any patent must 419 | be licensed for everyone's free use or not licensed at all. 420 | 421 | The precise terms and conditions for copying, distribution and 422 | modification follow. 423 | 424 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 425 | 426 | 0. This License applies to any program or other work which contains a 427 | notice placed by the copyright holder saying it may be distributed under 428 | the terms of this General Public License. The "Program", below, refers 429 | to any such program or work, and a "work based on the Program" means 430 | either the Program or any derivative work under copyright law: that is 431 | to say, a work containing the Program or a portion of it, either 432 | verbatim or with modifications and/or translated into another language. 433 | (Hereinafter, translation is included without limitation in the term 434 | "modification".) Each licensee is addressed as "you". 435 | 436 | Activities other than copying, distribution and modification are not 437 | covered by this License; they are outside its scope. The act of running 438 | the Program is not restricted, and the output from the Program is 439 | covered only if its contents constitute a work based on the Program 440 | (independent of having been made by running the Program). Whether that 441 | is true depends on what the Program does. 442 | 443 | 1. You may copy and distribute verbatim copies of the Program's source 444 | code as you receive it, in any medium, provided that you conspicuously 445 | and appropriately publish on each copy an appropriate copyright notice 446 | and disclaimer of warranty; keep intact all the notices that refer to 447 | this License and to the absence of any warranty; and give any other 448 | recipients of the Program a copy of this License along with the Program. 449 | 450 | You may charge a fee for the physical act of transferring a copy, and 451 | you may at your option offer warranty protection in exchange for a fee. 452 | 453 | 2. You may modify your copy or copies of the Program or any portion of 454 | it, thus forming a work based on the Program, and copy and distribute 455 | such modifications or work under the terms of Section 1 above, provided 456 | that you also meet all of these conditions: 457 | 458 | a) You must cause the modified files to carry prominent notices 459 | stating that you changed the files and the date of any change. 460 | 461 | b) You must cause any work that you distribute or publish, that in 462 | whole or in part contains or is derived from the Program or any part 463 | thereof, to be licensed as a whole at no charge to all third parties 464 | under the terms of this License. 465 | 466 | c) If the modified program normally reads commands interactively 467 | when run, you must cause it, when started running for such 468 | interactive use in the most ordinary way, to print or display an 469 | announcement including an appropriate copyright notice and a notice 470 | that there is no warranty (or else, saying that you provide a 471 | warranty) and that users may redistribute the program under these 472 | conditions, and telling the user how to view a copy of this License. 473 | (Exception: if the Program itself is interactive but does not 474 | normally print such an announcement, your work based on the Program 475 | is not required to print an announcement.) 476 | 477 | These requirements apply to the modified work as a whole. If 478 | identifiable sections of that work are not derived from the Program, and 479 | can be reasonably considered independent and separate works in 480 | themselves, then this License, and its terms, do not apply to those 481 | sections when you distribute them as separate works. But when you 482 | distribute the same sections as part of a whole which is a work based on 483 | the Program, the distribution of the whole must be on the terms of this 484 | License, whose permissions for other licensees extend to the entire 485 | whole, and thus to each and every part regardless of who wrote it. 486 | 487 | Thus, it is not the intent of this section to claim rights or contest 488 | your rights to work written entirely by you; rather, the intent is to 489 | exercise the right to control the distribution of derivative or 490 | collective works based on the Program. 491 | 492 | In addition, mere aggregation of another work not based on the Program 493 | with the Program (or with a work based on the Program) on a volume of a 494 | storage or distribution medium does not bring the other work under the 495 | scope of this License. 496 | 497 | 3. You may copy and distribute the Program (or a work based on it, 498 | under Section 2) in object code or executable form under the terms of 499 | Sections 1 and 2 above provided that you also do one of the following: 500 | 501 | a) Accompany it with the complete corresponding machine-readable 502 | source code, which must be distributed under the terms of Sections 1 503 | and 2 above on a medium customarily used for software interchange; or, 504 | 505 | b) Accompany it with a written offer, valid for at least three 506 | years, to give any third party, for a charge no more than your cost 507 | of physically performing source distribution, a complete 508 | machine-readable copy of the corresponding source code, to be 509 | distributed under the terms of Sections 1 and 2 above on a medium 510 | customarily used for software interchange; or, 511 | 512 | c) Accompany it with the information you received as to the offer to 513 | distribute corresponding source code. (This alternative is allowed 514 | only for noncommercial distribution and only if you received the 515 | program in object code or executable form with such an offer, in 516 | accord with Subsection b above.) 517 | 518 | The source code for a work means the preferred form of the work for 519 | making modifications to it. For an executable work, complete source code 520 | means all the source code for all modules it contains, plus any 521 | associated interface definition files, plus the scripts used to control 522 | compilation and installation of the executable. However, as a special 523 | exception, the source code distributed need not include anything that is 524 | normally distributed (in either source or binary form) with the major 525 | components (compiler, kernel, and so on) of the operating system on 526 | which the executable runs, unless that component itself accompanies the 527 | executable. 528 | 529 | If distribution of executable or object code is made by offering access 530 | to copy from a designated place, then offering equivalent access to copy 531 | the source code from the same place counts as distribution of the source 532 | code, even though third parties are not compelled to copy the source 533 | along with the object code. 534 | 535 | 4. You may not copy, modify, sublicense, or distribute the Program 536 | except as expressly provided under this License. Any attempt otherwise 537 | to copy, modify, sublicense or distribute the Program is void, and will 538 | automatically terminate your rights under this License. However, parties 539 | who have received copies, or rights, from you under this License will 540 | not have their licenses terminated so long as such parties remain in 541 | full compliance. 542 | 543 | 5. You are not required to accept this License, since you have not 544 | signed it. However, nothing else grants you permission to modify or 545 | distribute the Program or its derivative works. These actions are 546 | prohibited by law if you do not accept this License. Therefore, by 547 | modifying or distributing the Program (or any work based on the 548 | Program), you indicate your acceptance of this License to do so, and all 549 | its terms and conditions for copying, distributing or modifying the 550 | Program or works based on it. 551 | 552 | 6. Each time you redistribute the Program (or any work based on the 553 | Program), the recipient automatically receives a license from the 554 | original licensor to copy, distribute or modify the Program subject to 555 | these terms and conditions. You may not impose any further restrictions 556 | on the recipients' exercise of the rights granted herein. You are not 557 | responsible for enforcing compliance by third parties to this License. 558 | 559 | 7. If, as a consequence of a court judgment or allegation of patent 560 | infringement or for any other reason (not limited to patent issues), 561 | conditions are imposed on you (whether by court order, agreement or 562 | otherwise) that contradict the conditions of this License, they do not 563 | excuse you from the conditions of this License. If you cannot distribute 564 | so as to satisfy simultaneously your obligations under this License and 565 | any other pertinent obligations, then as a consequence you may not 566 | distribute the Program at all. For example, if a patent license would 567 | not permit royalty-free redistribution of the Program by all those who 568 | receive copies directly or indirectly through you, then the only way you 569 | could satisfy both it and this License would be to refrain entirely from 570 | distribution of the Program. 571 | 572 | If any portion of this section is held invalid or unenforceable under 573 | any particular circumstance, the balance of the section is intended to 574 | apply and the section as a whole is intended to apply in other 575 | circumstances. 576 | 577 | It is not the purpose of this section to induce you to infringe any 578 | patents or other property right claims or to contest validity of any 579 | such claims; this section has the sole purpose of protecting the 580 | integrity of the free software distribution system, which is implemented 581 | by public license practices. Many people have made generous 582 | contributions to the wide range of software distributed through that 583 | system in reliance on consistent application of that system; it is up to 584 | the author/donor to decide if he or she is willing to distribute 585 | software through any other system and a licensee cannot impose that choice. 586 | 587 | This section is intended to make thoroughly clear what is believed to be 588 | a consequence of the rest of this License. 589 | 590 | 8. If the distribution and/or use of the Program is restricted in 591 | certain countries either by patents or by copyrighted interfaces, the 592 | original copyright holder who places the Program under this License may 593 | add an explicit geographical distribution limitation excluding those 594 | countries, so that distribution is permitted only in or among countries 595 | not thus excluded. In such case, this License incorporates the 596 | limitation as if written in the body of this License. 597 | 598 | 9. The Free Software Foundation may publish revised and/or new 599 | versions of the General Public License from time to time. Such new 600 | versions will be similar in spirit to the present version, but may 601 | differ in detail to address new problems or concerns. 602 | 603 | Each version is given a distinguishing version number. If the Program 604 | specifies a version number of this License which applies to it and "any 605 | later version", you have the option of following the terms and 606 | conditions either of that version or of any later version published by 607 | the Free Software Foundation. If the Program does not specify a version 608 | number of this License, you may choose any version ever published by the 609 | Free Software Foundation. 610 | 611 | 10. If you wish to incorporate parts of the Program into other free 612 | programs whose distribution conditions are different, write to the 613 | author to ask for permission. For software which is copyrighted by the 614 | Free Software Foundation, write to the Free Software Foundation; we 615 | sometimes make exceptions for this. Our decision will be guided by the 616 | two goals of preserving the free status of all derivatives of our free 617 | software and of promoting the sharing and reuse of software generally. 618 | 619 | NO WARRANTY 620 | 621 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO 622 | WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. 623 | EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR 624 | OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, 625 | EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 626 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE 627 | ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH 628 | YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL 629 | NECESSARY SERVICING, REPAIR OR CORRECTION. 630 | 631 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN 632 | WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY 633 | AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR 634 | DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL 635 | DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM 636 | (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED 637 | INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF 638 | THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR 639 | OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 640 | 641 | END OF TERMS AND CONDITIONS 642 | 643 | How to Apply These Terms to Your New Programs 644 | 645 | If you develop a new program, and you want it to be of the greatest 646 | possible use to the public, the best way to achieve this is to make it 647 | free software which everyone can redistribute and change under these terms. 648 | 649 | To do so, attach the following notices to the program. It is safest to 650 | attach them to the start of each source file to most effectively convey 651 | the exclusion of warranty; and each file should have at least the 652 | "copyright" line and a pointer to where the full notice is found. 653 | 654 | One line to give the program's name and a brief idea of what it does. 655 | Copyright (C) 656 | 657 | This program is free software; you can redistribute it and/or modify 658 | it under the terms of the GNU General Public License as published by 659 | the Free Software Foundation; either version 2 of the License, or 660 | (at your option) any later version. 661 | 662 | This program is distributed in the hope that it will be useful, but 663 | WITHOUT ANY WARRANTY; without even the implied warranty of 664 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 665 | General Public License for more details. 666 | 667 | You should have received a copy of the GNU General Public License 668 | along with this program; if not, write to the Free Software 669 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA 670 | 671 | Also add information on how to contact you by electronic and paper mail. 672 | 673 | If the program is interactive, make it output a short notice like this 674 | when it starts in an interactive mode: 675 | 676 | Gnomovision version 69, Copyright (C) year name of author 677 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type 678 | `show w'. This is free software, and you are welcome to redistribute 679 | it under certain conditions; type `show c' for details. 680 | 681 | The hypothetical commands `show w' and `show c' should show the 682 | appropriate parts of the General Public License. Of course, the commands 683 | you use may be called something other than `show w' and `show c'; they 684 | could even be mouse-clicks or menu items--whatever suits your program. 685 | 686 | You should also get your employer (if you work as a programmer) or your 687 | school, if any, to sign a "copyright disclaimer" for the program, if 688 | necessary. Here is a sample; alter the names: 689 | 690 | Yoyodyne, Inc., hereby disclaims all copyright interest in the 691 | program `Gnomovision' (which makes passes at compilers) written by 692 | James Hacker. 693 | 694 | signature of Ty Coon, 1 April 1989 695 | Ty Coon, President of Vice 696 | 697 | This General Public License does not permit incorporating your program 698 | into proprietary programs. If your program is a subroutine library, you 699 | may consider it more useful to permit linking proprietary applications 700 | with the library. If this is what you want to do, use the GNU Library 701 | General Public License instead of this License. 702 | 703 | --- 704 | 705 | Certain source files distributed by Oracle America, Inc. and/or its 706 | affiliates are subject to the following clarification and special 707 | exception to the GPLv2, based on the GNU Project exception for its 708 | Classpath libraries, known as the GNU Classpath Exception, but only 709 | where Oracle has expressly included in the particular source file's 710 | header the words "Oracle designates this particular file as subject to 711 | the "Classpath" exception as provided by Oracle in the LICENSE file 712 | that accompanied this code." 713 | 714 | You should also note that Oracle includes multiple, independent 715 | programs in this software package. Some of those programs are provided 716 | under licenses deemed incompatible with the GPLv2 by the Free Software 717 | Foundation and others. For example, the package includes programs 718 | licensed under the Apache License, Version 2.0. Such programs are 719 | licensed to you under their original licenses. 720 | 721 | Oracle facilitates your further distribution of this package by adding 722 | the Classpath Exception to the necessary parts of its GPLv2 code, which 723 | permits you to use that code in combination with other independent 724 | modules not licensed under the GPLv2. However, note that this would 725 | not permit you to commingle code under an incompatible license with 726 | Oracle's GPLv2 licensed code by, for example, cutting and pasting such 727 | code into a file also containing Oracle's GPLv2 licensed code and then 728 | distributing the result. Additionally, if you were to remove the 729 | Classpath Exception from any of the files to which it applies and 730 | distribute the result, you would likely be required to license some or 731 | all of the other code in that distribution under the GPLv2 as well, and 732 | since the GPLv2 is incompatible with the license terms of some items 733 | included in the distribution by Oracle, removing the Classpath 734 | Exception could therefore effectively compromise your ability to 735 | further distribute the package. 736 | 737 | Proceed with caution and we recommend that you obtain the advice of a 738 | lawyer skilled in open source matters before removing the Classpath 739 | Exception or making modifications to this package which may 740 | subsequently be redistributed and/or involve the use of third party 741 | software. 742 | 743 | # CLASSPATH EXCEPTION 744 | Linking this library statically or dynamically with other modules is 745 | making a combined work based on this library. Thus, the terms and 746 | conditions of the GNU General Public License version 2 cover the whole 747 | combination. 748 | 749 | As a special exception, the copyright holders of this library give you 750 | permission to link this library with independent modules to produce an 751 | executable, regardless of the license terms of these independent 752 | modules, and to copy and distribute the resulting executable under 753 | terms of your choice, provided that you also meet, for each linked 754 | independent module, the terms and conditions of the license of that 755 | module. An independent module is a module which is not derived from or 756 | based on this library. If you modify this library, you may extend this 757 | exception to your version of the library, but you are not obligated to 758 | do so. If you do not wish to do so, delete this exception statement 759 | from your version. 760 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # BatchLab 2 | Batch API (JSR 352) Hands-on Lab 3 | 4 | This Lab was developed for JavaOne 2014. 5 | 6 | It starts with introducing the core concepts of JSR 352 (Job, Chunk, etc.) and then add features and concpets such as Batchlet, Multi-steps Job, Checkpoints, the JobOperator interface, Listeners and Job Partitioning. 7 | 8 | This Lab has been tested on GlassFish 4.0 & 4.1 but should work on any Java EE 7 compatible application server (full platform). 9 | 10 | To get started, download the project and check the masterLab.html file (generated from the .adoc files). 11 | -------------------------------------------------------------------------------- /chapters/exercice1.adoc: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////// 2 | Author : David Delabassee 3 | License : 4 | ////////////////////////////////////////// 5 | 6 | 7 | :imagesdir: ../pic 8 | 9 | == Lab: JSR 352 introduction 10 | 11 | This exercise will introduce you the main concepts of JSR 352 : Step, Job, Job Specification Language, batch runtime, etc. You will build a complete application that will run a simple batch job performing some hypothetical salary calculations. The application has been intentionally kept quite simple in order to focus on the key concepts of JSR 352. 12 | 13 | 14 | === Set the stage 15 | 16 | By nature Batch Job are long-lived and doesn't require human intervention. Nevertheless in our exercise, we will use a Servlet to interact with the Batch API (e.g. start the Job, get the status of the Job, etc.). 17 | 18 | 19 | ==== Create the project 20 | 21 | In the NetBeans Projects window, right click and select "New Project...". 22 | 23 | .NetBeans Project Windows 24 | image::E1.1.jpg[] 25 | 26 | ==== Create the Web Application 27 | 28 | We will now create a Web Application so select "Web Application" in the "Java Web" category. Note that a Web Application in NetBeans parlance is just the project structure of a typical Web Application. 29 | -- 30 | TIP: You can use the filter option at the top of the "New Project" window to filter out options from NetBeans, e.g. type "web" to easily find the "Web Application" project type. 31 | -- 32 | 33 | .Create a Project & NetBeans Filter 34 | image::E1.2.jpg[] 35 | 36 | 37 | Click "Next" and give your project a relevant name (e.g. "Lab1"). You can leave the other suggested values (Location & Folder) as they are. Click "Finish" and you should now have an empty Web Application (project structure and a single JSP page). 38 | 39 | .TO CHECK 40 | image::E1.3.jpg[] 41 | 42 | ==== Create the Package 43 | 44 | You should now create the package to host the application code. Right click in your project, select "New" and "Java Package" and name your package "org.glassfish.batch.lab1". All our codes will reside in this package. 45 | 46 | .Create a New Package 47 | image::E1.4.jpg[] 48 | -- 49 | TIP: It is possible that your menu is slightly different. If you don't find the "Java Package..." option, just select "Other..." at the bottom of the menu and use the filter. 50 | -- 51 | 52 | ==== Create the Servlet 53 | 54 | We will now create the Servlet itself. As usual, use NetBeans "New" menu and select "Servlet" from the "Web" category. Click "Next" and make sure to select, using the drop-down list, the package we have defined in the previous step (see Figure 6). You can click "Finish" as we are, for the rest, using the default values. 55 | 56 | 57 | .Create the Servlet 58 | image::E1.6.jpg[] 59 | 60 | .Select the right package for your Servlet 61 | image::E1.7.jpg[] 62 | 63 | -- 64 | TIP: You can now right click on your Servlet class and select "Run File". If everything goes well, your Servlet will be compiled and deployed to GlassFish. NetBeans will then invoke your web browser to connect to your Servlet. 65 | -- 66 | 67 | 68 | === Data and Data Store 69 | 70 | A typical enterprise application needs some data to consume. In real life, those data are high likely stored in a database, received over the network (eg. through a REST endpoint) or via a JMS Queue, etc. 71 | 72 | Our exercise also needs some data but for the sake of simplicity, we will mock a data producer behind a simple Singleton EJB as the focus of the Lab is really on the Batch API and not so much on other APIs such as JPA or JAX-RS. 73 | 74 | ==== Create the the Input Record 75 | 76 | Let's now create a simple class that will be used as input record for the application. 77 | This class is very simple, it holds an employee Id and some simple methods (e.g. get and set the employee salary). 78 | 79 | In the Project Window, select "New", "Java Class" from the "Java" category and click "Next". Name the class "PayrollInputRecord" and make sure it's in the correct package ("org.glassfish.batch.lab1"). Click "Finish" to actually create the class. 80 | 81 | .Create a new Java class 82 | image::E1.8.jpg[] 83 | 84 | Add the following code to the body of the class : 85 | [source, java] 86 | ---- 87 | private final int id; 88 | 89 | private String salary; 90 | 91 | public PayrollInputRecord(int id) { 92 | this.id = id; 93 | } 94 | 95 | public int getId() { 96 | return id; 97 | } 98 | 99 | public String getSalary() { 100 | return salary; 101 | } 102 | 103 | public void setSalary(String salary) { 104 | this.salary = salary; 105 | } 106 | 107 | @Override 108 | public int hashCode() { 109 | return id; 110 | } 111 | 112 | @Override 113 | public boolean equals(Object object) { 114 | if (object == null || !(object instanceof PayrollInputRecord)) { 115 | return false; 116 | } 117 | PayrollInputRecord other = (PayrollInputRecord) object; 118 | return this.id == other.id; 119 | } 120 | 121 | @Override 122 | public String toString() { 123 | return "PayrollInputRecord[ id=" + id + " ]"; 124 | } 125 | ---- 126 | 127 | -- 128 | TIP: When you save a class, NetBeans will try to recompile it. If it can't, you will easily then see where the errors are. 129 | -- 130 | 131 | ==== Create the the Output Record 132 | 133 | Similarly, we will now create a simple class that will be used as output record. 134 | This class adds some capabilities (set and get the employee social security number, his/her bonus, etc.) 135 | 136 | In the Project Window, select "New", "Java Class" from the "Java" category and click "Next". Name the class "PayrollOutputRecord", check the package ("org.glassfish.batch.lab1") and click "Finish". 137 | 138 | Add this code to the class : 139 | [source, java] 140 | ---- 141 | private final int empId; 142 | 143 | private float salary; 144 | 145 | private float socialSecurityTax; 146 | 147 | private float bonus = 0; 148 | 149 | private float net; 150 | 151 | public PayrollOutputRecord(int empID) { 152 | this.empId = empID; 153 | } 154 | 155 | public int getEmpId() { 156 | return empId; 157 | } 158 | 159 | public float getSalary() { 160 | return salary; 161 | } 162 | 163 | public void setSalary(float base) { 164 | this.salary = base; 165 | } 166 | 167 | public float getSocialSecurityTax() { 168 | return socialSecurityTax; 169 | } 170 | 171 | public void setSocialSecurityTax(float socialSecurityTax) { 172 | this.socialSecurityTax = socialSecurityTax; 173 | } 174 | 175 | public float getBonus() { 176 | return bonus; 177 | } 178 | 179 | public void setBonus(float bonus) { 180 | this.bonus = bonus; 181 | } 182 | 183 | public float getNet() { 184 | return net; 185 | } 186 | 187 | public void setNet(float net) { 188 | this.net = net; 189 | } 190 | 191 | @Override 192 | public int hashCode() { 193 | return getEmpId(); 194 | } 195 | 196 | @Override 197 | public boolean equals(Object object) { 198 | if (object == null || !(object instanceof PayrollOutputRecord)) { 199 | return false; 200 | } 201 | PayrollOutputRecord other = (PayrollOutputRecord) object; 202 | return getEmpId() == other.getEmpId(); 203 | } 204 | 205 | @Override 206 | public String toString() { 207 | return "PayrollOutputRecord[ id= [" + getEmpId() + "]"; 208 | } 209 | ---- 210 | 211 | 212 | ==== Create the EJB 213 | 214 | We will create a simple Java class. We will then use some annotations to turn this POJO (Plain Old Java Object) into the Enterprise Java Beans we need. 215 | 216 | In the Project Window, select "New", "Java Class" from the "Java" category and click "Next". Name the class "PayrollDataHolderBean" and make sure it's in the correct package ("org.glassfish.batch.lab1") 217 | 218 | .Create a java class 219 | image::E1.5.jpg[] 220 | 221 | Add the following 2 annotations at the class level : `@Singleton` & `@Startup` : 222 | 223 | * `@Singleton` is used to specify that this class will be implements a singleton session bean. You will have to import `javax.ejb.Singleton`. 224 | * `@Startup` is used to specify that this EJB will use eager initialization, i.e. the EJB container will initialise it upon application startup, before it can get any requests. This is useful, for example, to perform application startup tasks. 225 | ... 226 | 227 | .Notice the yellow light bulb on the left and the red waved underlined line of code. 228 | image::E1.9.jpg[] 229 | 230 | -- 231 | TIP: A waved red underlined line of code means that NetBeans is unable to compile that particular line. A light bulb on the left side of the code means that NetBeans has suggestions that could fix the issue. Right click on the magnifier to see and eventually select one of the proposed fix. 232 | -- 233 | 234 | Right click on the light bulb to fix the imports. Check to top of the class file and you should now see the that the classes corresponding to the 2 annotations have been added. 235 | 236 | [source, java] 237 | ---- 238 | import javax.ejb.Singleton; 239 | import javax.ejb.Startup; 240 | ---- 241 | 242 | 243 | 244 | 245 | Add the following code to the body of the class : 246 | [source, java] 247 | ---- 248 | private List payrollInputRecords = new ArrayList<>(); 249 | 250 | private Set payrollOutputRecords = new HashSet<>(); 251 | 252 | public PayrollDataHolderBean() { 253 | 254 | } 255 | 256 | @PostConstruct 257 | public void onApplicationStartup() { 258 | for (int empID=1; empID<6; empID++) { 259 | payrollInputRecords.add("" + empID + ", " + (80000 + empID*10000)); 260 | } 261 | } 262 | 263 | public List getPayrollInputData() { 264 | return Collections.unmodifiableList(payrollInputRecords); 265 | } 266 | 267 | public void addPayrollOutputRecord(PayrollOutputRecord data) { 268 | payrollOutputRecords.add(data); 269 | } 270 | 271 | public Set getPayrollOutputRecords() { 272 | return payrollOutputRecords; 273 | } 274 | ---- 275 | 276 | In this code, we define a `payrollInputRecords` list of strings. We use the `@PostConstruct` annotation to specify to the Application Server that the `onApplicationStartup()` method should be invoked after all injection has occurred and after all initializers have been called, i.e. before the EJB can handle client requests. This method basically fills the `payrollInputRecords` list with dummy employees data (an employee ID and numeric value, stored in a simple string). 277 | We also define a `PayrollOutputRecord` collection and some related methods (add an element, get the collection). 278 | 279 | Make sure to resolve any missing imports. The class `PayrollDataHolderBean.java` should now compile and looks like this. 280 | [source, java] 281 | ---- 282 | package org.glassfish.batch.lab1; 283 | 284 | import java.util.ArrayList; 285 | import java.util.Collections; 286 | import java.util.HashSet; 287 | import java.util.List; 288 | import java.util.Set; 289 | import javax.annotation.PostConstruct; 290 | import javax.ejb.Singleton; 291 | import javax.ejb.Startup; 292 | 293 | @Singleton 294 | @Startup 295 | public class PayrollDataHolderBean { 296 | private List payrollInputRecords = new ArrayList<>(); 297 | 298 | private Set payrollOutputRecords = new HashSet<>(); 299 | 300 | public PayrollDataHolderBean() { 301 | 302 | } 303 | 304 | @PostConstruct 305 | public void onApplicationStartup() { 306 | for (int empID=1; empID<6; empID++) { 307 | payrollInputRecords.add("" + empID + ", " + (80000 + empID*10000)); 308 | } 309 | } 310 | 311 | public List getPayrollInputData() { 312 | return Collections.unmodifiableList(payrollInputRecords); 313 | } 314 | 315 | public void addPayrollOutputRecord(PayrollOutputRecord data) { 316 | payrollOutputRecords.add(data); 317 | } 318 | 319 | public Set getPayrollOutputRecords() { 320 | return payrollOutputRecords; 321 | } 322 | 323 | } 324 | ---- 325 | 326 | 327 | === PayRoll Job : the Reader, the Processor, the Writer 328 | 329 | Now that we have everything set in place, we can tackle the main part of the exercise, i.e. create the batch job! 330 | 331 | A batch job uses a simple 'Read - Process - Write' pattern. A *Reader* is used to retrieve the input data, a *Processor* will then do some processing on those data and finally, a *Writer* will save the results somewhere. How the data are actually read (e.g. from a filesystem, from a database, from memory, etc.) is not specified so we are free to use, in a Reader, the mechanism we want. In our exercise, we will just read some data stored in an singleton EJB. 332 | 333 | 334 | The same is true for the output, for the Writer. The specification doesn't say how the output should be saved so we can use different approaches (e.g. send a mail, post to a JMS queue, update a Database via JPA or JBDC, etc.) 335 | 336 | -- 337 | TIP: The fundamental unit of a *Job* is a *Step*. A job is made of one or more steps. JSR 352 defines 2 types of steps: *Chunk* step used to work on data using the Read-Process-Write pattern and *Batchlet* step used to perform task(s) within a job (e.g. send via FTP the final result of a Job). 338 | -- 339 | 340 | A *chunk-style step* contains exactly one *ItemReader*, one *ItemProcessor*, and one *ItemWriter*. In this pattern, items are processed "chunk-size" at a time. The "chunk-size" is specified in the Job xml. 341 | 342 | -- 343 | TIP: JSR 352 also defines a XML based language called *JSL* (Job Specification Language). JSL is used to assemble together different steps to form a job, defines the flow between the different steps and also configure the behaviour of the Job itself (e.g. what to do in case of error). 344 | -- 345 | 346 | A chunk is processed as follows: The batch runtime starts a transaction and calls the ItemReader to read one item at a time. The batch runtime then passes this item to the ItemProcessor that processes the item based upon the business logic (such as "calculate net pay"), and returns the processed item to the batch runtime for aggregation. Once the "chunk-size" number of items are read and processed, they are given to an ItemWriter, which writes the data (for example, to a database table or a flat file). The transaction is then committed. The process repeats till the ItemReader finishes reading all items. 347 | 348 | To implement a batch Job, we will have implement at least one Chunked step. Implementing a Chunked step means developing in Java : a Reader, a Processor and a Writer. That is exactly what will do in the next few sections, we will develop a Reader, a Writer and a Processor. We will then define the Job itself using JSL. 349 | 350 | 351 | ==== Reader 352 | 353 | A Reader is class that extends the abstract `javax.batch.api.chunk.AbstractItemReader` class defined in JSR 352. 354 | 355 | Create, in the right package, a new class called PayrollInputRecordReader and in the class declaration, specify that this class should extends the `AbstractItemReader` class. 356 | 357 | .extends the `AbstractItemReader` class 358 | image::E1.11.jpg[] 359 | 360 | Make sure to fix the import for the `AbstractItemReader` class. 361 | You can see that NetBeans is still unable to compile the code, this is because the class we are extending is abstract. To fix this, just make sure to implements all the abstract methods (one in this case, the `readItem()` method). 362 | 363 | .Using NetBeans to implements the abstract methods 364 | image::E1.12.jpg[] 365 | 366 | The exercise data will be coming from the singleton EJB we have defined previously, so you can inject this EJB by adding the following declaration: 367 | 368 | [source, java] 369 | ---- 370 | @EJB 371 | PayrollDataHolderBean payrollDataHolderBean; 372 | ---- 373 | 374 | Let's create the `payrollInputRecordsIterator` Iterator 375 | 376 | [source, java] 377 | ---- 378 | Iterator payrollInputRecordsIterator; 379 | ---- 380 | 381 | Now we should initialize it with the data contained in the EJB. We will do this in the `open()` method defined in the `AbstractItemReader` class. As its name implies, this method is invoked by the Batch runtime to open ressources required by the Reader. 382 | [source, java] 383 | ---- 384 | public void open(Serializable e) throws Exception { 385 | payrollInputRecordsIterator = payrollDataHolderBean.getPayrollInputData().iterator(); 386 | } 387 | ---- 388 | 389 | We will now rewrite the `readItem()` method as follow : 390 | [source, java] 391 | ---- 392 | public Object readItem() throws Exception { 393 | String line = payrollInputRecordsIterator.hasNext() ? payrollInputRecordsIterator.next() : null; 394 | PayrollInputRecord record = null; 395 | if (line != null) { 396 | StringTokenizer tokenizer = new StringTokenizer(line, ", "); 397 | String empId = tokenizer.nextToken(); 398 | String salary = tokenizer.nextToken(); 399 | if (tokenizer.hasMoreTokens()) 400 | throw new IllegalArgumentException("Extra characters in input data: " + line); 401 | record = new PayrollInputRecord(Integer.valueOf(empId)); 402 | record.setSalary(salary); 403 | } 404 | 405 | return record; 406 | } 407 | ---- 408 | 409 | The `readItem()` method is invoked by the Batch runtime, the method will then return the next item. If there is no more item, it will return `null` instead. 410 | The code is fairly easy to understand, it iterates over all the employees and for each of them, it creates a `PayrollInputRecord` object with his/her details, object which is then returned by the `readItem()` method. 411 | 412 | 413 | We can use the `open()` method to initialize any ressources that is required by the Reader. In our case, the initialization is limited to copy the `payrollDataHolderBean` data to the `payrollInputRecordsIterator`. 414 | 415 | [source, java] 416 | ---- 417 | public void open(Serializable e) throws Exception { 418 | payrollInputRecordsIterator = payrollDataHolderBean.getPayrollInputData().iterator(); 419 | } 420 | ---- 421 | 422 | -- 423 | TIP: You should now know how to detect any missing import and how to solve this. 424 | -- 425 | 426 | 427 | We should also decorate the class with the `@Named` annotation. 428 | 429 | 430 | -- 431 | TIP: When running in Java EE environment, the Batch runtime uses CDI (Context and Dependency Injection) to instantiate Job artifacts (like Item{Reader, Writer, Procesor} etc.). The `@Named` annotation allows us to access a bean by using its bean name (with the first letter in lowercase). So annotating the ItemReader with `@Named` will allow us to reference the Reader in our Job XML just by using its bean name. 432 | -- 433 | 434 | Once you have resolved the missing imports, your `PayrollInputRecordReader.java` class should look similar to this: 435 | [source, java] 436 | ---- 437 | package org.glassfish.batch.lab1; 438 | 439 | import java.io.Serializable; 440 | import java.util.Iterator; 441 | import java.util.StringTokenizer; 442 | import javax.batch.api.chunk.AbstractItemReader; 443 | import javax.ejb.EJB; 444 | import javax.inject.Named; 445 | 446 | @Named 447 | public class PayrollInputRecordReader extends AbstractItemReader { 448 | 449 | @EJB 450 | PayrollDataHolderBean payrollDataHolderBean; 451 | 452 | Iterator payrollInputRecordsIterator; 453 | 454 | public Object readItem() throws Exception { 455 | String line = payrollInputRecordsIterator.hasNext() ? payrollInputRecordsIterator.next() : null; 456 | PayrollInputRecord record = null; 457 | if (line != null) { 458 | StringTokenizer tokenizer = new StringTokenizer(line, ", "); 459 | String empId = tokenizer.nextToken(); 460 | String salary = tokenizer.nextToken(); 461 | if (tokenizer.hasMoreTokens()) 462 | throw new IllegalArgumentException("Extra characters in input data: " + line); 463 | record = new PayrollInputRecord(Integer.valueOf(empId)); 464 | record.setSalary(salary); 465 | } 466 | 467 | return record; 468 | } 469 | 470 | public void open(Serializable e) throws Exception { 471 | payrollInputRecordsIterator = payrollDataHolderBean.getPayrollInputData().iterator(); 472 | } 473 | 474 | } 475 | ---- 476 | 477 | 478 | ==== Processor 479 | 480 | As its name implies, a Processor will handle, within a batch step, the actual data processing, data that is provided by the Reader. Technically, a Processor is a class that implements the `javax.batch.api.chunk.ItemProcessor` interface defined in the JSR 352 specification and has a `processItem()` method. The argument to this method is the item that was read by the ItemReader. The method must return a processed item. The processed item need not be the same type as the item read by the ItemReader. 481 | 482 | 483 | So, create a new class called `NetPayProcessor` and specify that it implements the `ItemProcessor` interface. Decorate the class with the `@Named` annotation, resolve the missing imports and ask NetBeans to implement the abstract method. 484 | 485 | We should now change the `processItem()` method to perform the actual data processing, so change this method as follow: 486 | [source, java] 487 | ---- 488 | public Object processItem(Object obj) throws Exception { 489 | PayrollInputRecord inputRecord = (PayrollInputRecord) obj; 490 | float salary = Integer.valueOf(inputRecord.getSalary()); 491 | float socialSecurityTax = 492 | salary > 117000 ? 117000 * 6.2f / 100 : salary * 6.2f / 100; 493 | 494 | PayrollOutputRecord outputRecord = new PayrollOutputRecord(inputRecord.getId()); 495 | outputRecord.setSalary(salary / 24.0f); 496 | outputRecord.setSocialSecurityTax(socialSecurityTax / 24.0f); 497 | outputRecord.setNet(outputRecord.getSalary() - outputRecord.getSocialSecurityTax()); 498 | 499 | return outputRecord; 500 | } 501 | ---- 502 | 503 | This method casts the received object to a `PayrollInputRecord`. It does some computations and then creates and initializes a `PayrollOutputRecord` object, compute and set a net salary. That `PayrollOutputRecord` object is then returned to the calling method. 504 | 505 | 506 | Your `NetPayProcessor.java` class should now look similar to this: 507 | [source, java] 508 | ---- 509 | package org.glassfish.javaee7.batch.lab1; 510 | 511 | import javax.batch.api.chunk.ItemProcessor; 512 | import javax.batch.runtime.context.JobContext; 513 | import javax.inject.Inject; 514 | import javax.inject.Named; 515 | 516 | @Named 517 | public class NetPayProcessor 518 | implements ItemProcessor { 519 | 520 | @Inject 521 | private JobContext jobContext; 522 | 523 | public Object processItem(Object obj) throws Exception { 524 | PayrollInputRecord inputRecord = (PayrollInputRecord) obj; 525 | float salary = Integer.valueOf(inputRecord.getSalary()); 526 | float socialSecurityTax = 527 | salary > 117000 ? 117000 * 6.2f / 100 : salary * 6.2f / 100; 528 | 529 | PayrollOutputRecord outputRecord = new PayrollOutputRecord(inputRecord.getId()); 530 | outputRecord.setSalary(salary / 24.0f); 531 | outputRecord.setSocialSecurityTax(socialSecurityTax / 24.0f); 532 | outputRecord.setNet(outputRecord.getSalary() - outputRecord.getSocialSecurityTax()); 533 | 534 | return outputRecord; 535 | } 536 | 537 | } 538 | ---- 539 | 540 | ==== Writer 541 | 542 | 543 | After the Reader and the Processor, we now need to develop the Writer to save our results. A Writer is a class that extends the `javax.batch.api.chunk.AbstractItemWriter` interface and implements the `writeItems()` method. Do note that the ItemWriter is given a list of items processed by the ItemWriter. 544 | 545 | As usual, create a class named `PayrollOutputRecordWriter` in the right package. Resolve the import and ask NetBeans to implement the abstract method. 546 | 547 | Remember that for the sake of simplicity, we will save the results in the Bean we have created earlier, so you need to inject that bean with the following code. 548 | 549 | We should also decorate the class with the `@Named` annotation and resolve the missing import. 550 | 551 | [source, java] 552 | ---- 553 | @EJB 554 | private PayrollDataHolderBean bean; 555 | ---- 556 | 557 | Now, we will change the `writeItems()` method to save the results, that is, to add the results to our bean. 558 | [source, java] 559 | ---- 560 | public void writeItems(List list) throws Exception { 561 | for (Object obj : list) { 562 | bean.addPayrollOutputRecord((PayrollOutputRecord) obj); 563 | } 564 | } 565 | ---- 566 | 567 | Your `PayrollOutputRecordWriter.java` class should now look similar to this: 568 | [source, java] 569 | ---- 570 | package org.glassfish.batch.lab1; 571 | 572 | import java.util.List; 573 | import javax.batch.api.chunk.AbstractItemWriter; 574 | import javax.ejb.EJB; 575 | import javax.inject.Named; 576 | 577 | @Named 578 | public class PayrollOutputRecordWriter extends AbstractItemWriter { 579 | @EJB 580 | private PayrollDataHolderBean bean; 581 | 582 | public void writeItems(List list) throws Exception { 583 | for (Object obj : list) { 584 | bean.addPayrollOutputRecord((PayrollOutputRecord) obj); 585 | } 586 | } 587 | 588 | } 589 | ---- 590 | 591 | === Putting all the pieces together : JSL 592 | 593 | In the previous section, we have defined a Chunk step with a Reader, a Processor and a Writer. Now, we need to wire together those elements to actually form a Job that will be executable by the JSR 352 runtime. For that, we will use a XML based language defined by the JSR 352 specification : the *Job Specification Language (JSL)*. 594 | 595 | 596 | Go to Files tab (usually, it is next to the Project tab). Expand your project "WEB-INF" directory ("web/WEB-INF") and with the NetBeans wizard (New "Folder" in the "Other" Category) create the following directory hierarchy : "classes/META-INF/batch-jobs" 597 | 598 | In the "batch-jobs" directory, create a XML file named `PayrollJob.xml` (New "XML Document" from the "XML" category). 599 | 600 | .Create the JSL file 601 | image::E1.14.jpg[] 602 | 603 | -- 604 | TIP: This XML file will be the JSL that will describe our Job. It will be needed to control the Batch itself in the next step so make sure to note its name. 605 | -- 606 | 607 | Edit the `PayrollJob.xml` as follow : 608 | [source, xml] 609 | ---- 610 | 611 | 612 | 613 | 614 | 615 | 616 | 617 | 618 | 619 | 620 | ---- 621 | 622 | We are defining a Job called "PayrollJob" made of a single chunk step called "process". 623 | We then define the Reader, the Processor and the Writer of the "process" step. Execution of the job commences by executing the first step listed in the Job XML. Our first step is a chunk style step with "chunk size" (item-count) of 3. The step also lists an ItemReader identified by the CDI bean name `payRollInputRecordReader`. Similarly, the step lists an ItemProcessor and a ItemWriter by the beans names `netPayProcessor` and `payRollOutputRecordWriter` respectively. In order to execute the step, the Batch runtime uses CDI to instantiate the specified ItemReader, ItemProcessor and ItemWriter. It then calls the ItemReader's `readItem()` and ItemProcessor's `processItem()` "item-count" times (3 in our sample). These processed items are then collected and passed to the ItemWriter's `writeItems()` method. 624 | 625 | 626 | === Executing the Job 627 | 628 | In the previous section, we have defined the implementations of our Step (Reader, Processor and Writer). Using JSL, we have then referenced those implementations to define the batch job. The last thing we need to do is to submit the job for execution. 629 | 630 | -- 631 | TIP: JSR 352 defines the `javax.batch.operations.JobOperator` interface to control jobs. Via this interface, it is possible to start, stop, and restart jobs. It is also possible to inspect job history, to discover what jobs are currently running, what jobs have previously run, etc. For more details, check the http://docs.oracle.com/javaee/7/api/javax/batch/operations/JobOperator.html[javadoc]. 632 | -- 633 | 634 | ==== Submitting the job for execution 635 | Edit the the `BatchJobSubmitter.java` servlet we have defined earlier, insert the following method: 636 | [source, java] 637 | ---- 638 | private long submitJobFromXML(String jobName) throws Exception { 639 | JobOperator jobOperator = BatchRuntime.getJobOperator(); 640 | Properties props = new Properties(); 641 | return jobOperator.start(jobName, props); 642 | } 643 | ---- 644 | This method gets a `jobOperator` instance using the `BatchRuntime.getJobOperator()` method. It then invokes the `jobOperator.start()` method to start the job. The first parameter passed to the `jobOperator.start()` method is the job xml name. This xml must reside under the "WEB-INF/classes/META-INF/batch-jobs" directory. 645 | 646 | -- 647 | TIP: Putting the JSL in a wrong directory or using a different name are frequent errors when starting with JSR 352. 648 | -- 649 | 650 | 651 | 652 | ==== Get the job details 653 | 654 | We will again leverage the `jobOperator` interface to get runtime details of job. We will write a few utility methods to gather data and display the results. First, add the following method to the servlet: 655 | 656 | [source, java] 657 | ---- 658 | private void displayJobDetails(PrintWriter pw, long executionId) { 659 | pw.println(""); 660 | pw.println(""); 661 | pw.println("
Status of Submitted Jobs
"); 662 | pw.println("" 663 | + "" 664 | + "" 665 | + ""); 666 | 667 | JobOperator jobOperator = BatchRuntime.getJobOperator(); 668 | try { 669 | for (JobInstance jobInstance : jobOperator.getJobInstances("PayrollJob", 0, Integer.MAX_VALUE-1)) { 670 | for (JobExecution jobExecution : jobOperator.getJobExecutions(jobInstance)) { 671 | StringBuilder sb = new StringBuilder(); 672 | if (executionId == jobExecution.getExecutionId()) { 673 | sb.append(""); 674 | } else { 675 | sb.append(""); 676 | } 677 | sb.append(""); 678 | sb.append(""); 679 | sb.append(""); 680 | sb.append(""); 681 | sb.append(""); 682 | sb.append(""); 683 | sb.append(""); 684 | pw.println(sb.toString()); 685 | } 686 | } 687 | } catch (Exception ex) { 688 | pw.println(ex.toString()); 689 | } 690 | pw.println("
Job NameInstance IdExecutionIDBatch StatusExit StatusStart Time StatusEnd Time
").append(jobExecution.getJobName()).append("").append(jobInstance.getInstanceId()).append("").append(jobExecution.getExecutionId()).append("").append(jobExecution.getBatchStatus()).append("").append(jobExecution.getExitStatus()).append("").append(jobExecution.getStartTime()).append("").append(jobExecution.getEndTime()).append("
"); 691 | pw.println(""); 692 | } 693 | ---- 694 | 695 | 696 | We use the `BatchRuntime.getJobOperator()` method to get a `JobOperator` instance. 697 | We then invoke the `getJobInstances()` method on this `JobOperator` instance to get the different job instances. 698 | And for all the job instances, we pass each instances to the `jobOperator.getJobExecutions()` method and get in return a `JobExecution` object. Once we have that object, we can query the different values we need (e.g. start time, etc.). 699 | The rest (and bulk) of this method generate HTML. 700 | 701 | 702 | -- 703 | IMPORTANT: Hard coding HTML directly in a servlet is not recommended for any serious application. 704 | -- 705 | 706 | You can also add the following method to display the input data used by the job: 707 | [source, java] 708 | ---- 709 | private void displayPayrollForm(PrintWriter pw) 710 | throws Exception { 711 | 712 | pw.println(""); 713 | for (String line : payrollDataHolderBean.getPayrollInputData()) { 714 | pw.println(""); 715 | } 716 | pw.println("
Payroll Input Records (Comma Separated Values)
" + line + "
"); 717 | } 718 | ---- 719 | 720 | NetBeans will complain about `payrollDataHolderBean` bean that is supposed to hold the data, so you should inject it: 721 | 722 | [source, java] 723 | ---- 724 | @EJB 725 | PayrollDataHolderBean payrollDataHolderBean; 726 | ---- 727 | 728 | You can now add the `displayProcessedPayrollRecords()` method: 729 | [source, java] 730 | ---- 731 | private void displayProcessedPayrollRecords(PrintWriter pw, long executionId) throws Exception { 732 | pw.println("
"); 733 | pw.println("Processed Payroll Records"); 734 | pw.println("" 735 | + ""); 736 | for (PayrollOutputRecord record : payrollDataHolderBean.getPayrollOutputRecords()) { 737 | pw.println("" 738 | + "" 739 | + "" 740 | + ""); 741 | } 742 | pw.println(""); 743 | pw.println(""); 744 | pw.println(""); 745 | pw.println("
Employee IDSalarySocial SecurityNet
" + record.getEmpId()+ "" + record.getSalary() + "" + record.getSocialSecurityTax()+ "" + record.getNet()+ "
"); 746 | pw.println("
"); 747 | } 748 | ---- 749 | 750 | This method displays, in a HTML form, a table containing the job results using the `payrollDataHolderBean` bean. Towards the end, you can also see that the method print raw HTML with the 2 buttons that the end user will use to control the application (e.g. "Calculate Payroll" & "Refresh"). 751 | 752 | 753 | Finally, we will rewrite the existing `processRequest()` servlet method to use those utilities methods: 754 | [source, java] 755 | ---- 756 | protected void processRequest(HttpServletRequest request, HttpServletResponse response) 757 | throws ServletException, IOException { 758 | response.setContentType("text/html;charset=UTF-8"); 759 | try (PrintWriter pw = response.getWriter()) { 760 | pw.println(""); 761 | pw.println("Servlet BatchJobSubmitter"); 762 | 763 | long executionId = -1; 764 | if (request.getParameter("executionId") != null) { 765 | executionId = Long.valueOf(request.getParameter("executionId")); 766 | } 767 | 768 | try { 769 | if (request.getParameter("calculatePayroll") != null) { 770 | executionId = submitJobFromXML("PayrollJob"); 771 | } 772 | pw.println(""); 773 | pw.println(""); 778 | pw.println("
"); 774 | displayPayrollForm(pw); 775 | pw.println(""); 776 | displayProcessedPayrollRecords(pw, executionId); 777 | pw.println("
"); 779 | displayJobDetails(pw, executionId); 780 | } catch (Exception ex) { 781 | throw new ServletException(ex); 782 | } 783 | pw.println(""); 784 | pw.println(""); 785 | } 786 | } 787 | ---- 788 | 789 | -- 790 | TIP: Make sure the string parameter you pass to the `submitJobFromXML()` method corresponds to the name of the JSL file describing your Job (without the .xml extension)! 791 | -- 792 | 793 | In this case, we are working with Explicit CDI Beans Archive so we need to create a bean.xml. For a Web Application, this beans.xml has to be in the WEB-INF directory so right click on the WEB-INF directory and create an empty file called "beans.xml". 794 | 795 | -- 796 | TIP: The CDI container is looking for a "beans.xml" file in the WEB-INF directory. If it's not there or present under a different name, the application will not work as it rely on some CDI features. 797 | -- 798 | 799 | 800 | 801 | === Testing the Payroll application 802 | 803 | To test the application, right click on the `BatchJobSubmitter.java` servlet in the "Project" tab and select "Run". This action will compile and deploy the application and invoke your local browser with the Servlet URL. The first time, you should will see the following screen. 804 | 805 | .Initial screen : no job submitted yet 806 | image::E1.15.jpg[] 807 | 808 | Now click on the "Calculate Payroll" button to submit a job for execution to the batch runtime. You can see that a job has been started but not yet completed (e.g. it has no end time). You can also see that the right column is empty at this stage. 809 | 810 | .A job has been started 811 | image::E1.16.jpg[] 812 | 813 | Finally, if you click on "refresh" the job will have had enough time to run completely. The results are displayed in the right column. You can also notice the end time of the job execution. 814 | Since the data set is minimal and the processing trivial, the batch execution is almost instantaneous. 815 | 816 | .The job is now completed 817 | image::E1.17.jpg[] 818 | 819 | === Summary 820 | 821 | In this Lab, we have learnt the core components of the batch processing architecture. 822 | 823 | * A job encapsulates the entire batch process. A job contains one or more steps. A job is put together using a *Job Specification Language* (JSL) that specifies the sequence in which the steps must be executed. In JSR 352, JSL is specified in an XML file called the job XML file. In short, *a job (with JSR 352) is basically a container for steps*. 824 | 825 | * A *step* is a domain object that encapsulates an *independent, sequential phase of the job*. A step contains all the necessary logic and data to perform the actual processing. The batch specification deliberately leaves the definition of a step vague because the content of a step is purely application-specific and can be as complex or simple as the developer desires. There are *two kinds of steps: chunk and batchlet*. 826 | 827 | * A *chunk-style* step contains exactly one *ItemReader*, *one ItemProcessor*, and *one ItemWriter*. In this pattern, ItemReader reads one item at a time, ItemProcessor processes the item based upon the business logic (such as "calculate account balance"), and hands it to the batch runtime for aggregation. Once the "chunk-size" number of items are read and processed, they are given to an ItemWriter, which writes the data (for example, to a database table or a flat file). The transaction is then committed. 828 | 829 | * JSR 352 also defines a roll-your-own kind of a step called a *batchlet*. A batchlet is free to use anything to accomplish the step, such as sending an e-mail. Batchlet will be discussed in the next section. 830 | 831 | * *JobOperator* provides an interface to manage all aspects of job processing, including operational commands, such as start, restart, and stop, as well as job repository commands, such as retrieval of job and step executions. See section 10.4 of the JSR 352 specification for more details about JobOperator. 832 | 833 | * *JobRepository* holds information about jobs currently running and jobs that ran in the past. JobOperator provides APIs to access this repository. A JobRepository could be implemented using, say, a database or a file system. 834 | 835 | 836 | ////////////////////////////////////////// 837 | 838 | icon:tags[role="black"] Test 839 | 840 | icon:taxi[role="black"] Taxi 841 | 842 | icon:star[role="black"] Star 843 | 844 | icon:comment[role="black"] Comment 845 | 846 | tip - icon-pushpin (or icon-star or icon-plus) 847 | note - icon-info-sign 848 | warning - icon-warning-sign 849 | important - icon-exclamation-sign 850 | caution - icon-bolt (or icon-minus) 851 | 852 | 853 | ////////////////////////////////////////// 854 | 855 | 856 | 857 | -------------------------------------------------------------------------------- /chapters/exercice2.adoc: -------------------------------------------------------------------------------- 1 | :imagesdir: ../pic 2 | 3 | == Lab: Batchlet and Multi-steps Job 4 | 5 | In the first exercise, we have developed a simple job made of a single step, a Chunk step. This exercise will introduce you to *Batchlet*, the second type of step supported by JSR 352. Chunk step are used to work on data while Batchlets are useful for performing a variety of tasks that are not item-oriented, such as executing a command or performing a task (like copying files, preparing reports etc.). 6 | 7 | To illustrate this, we will define a multi-steps job that combine 2 steps: a Chunk step and a Batchlet step. 8 | 9 | 10 | 11 | === Set the stage 12 | 13 | Open the "lab2" project in NetBeans ("File" , "Open Project" and select the "lab2" directory). If you run the project and access the "BatchJobSubmitter" servlet, you will see that it is very similar to what we have done in the previous exercise. 14 | 15 | It is a simple batch job made of a single Chunk step, the "prepare" step (check the JSL file describing the batch job). 16 | 17 | === Implement the Batchlet step 18 | 19 | A Batchlet is a class that extends and implements the `javax.batch.api.AbstractBatchlet` interface. So create, in the source package, a new Java class called "SummaryProcessor" that extends the `AbstractBatchlet` interface. Use NetBeans to resolve the missing import and implement the abstract `process()` method. 20 | 21 | Decorate the class with the `@Named` annotation and inject the `PayrollDataHolderBean` bean as follow : 22 | 23 | [source, java] 24 | ---- 25 | @EJB 26 | PayrollDataHolderBean payrollDataHolderBean; 27 | ---- 28 | 29 | The `process()` method is doing the work of the Batchlet is supposed to do so let's re-write it as follow : 30 | 31 | [source, java] 32 | ---- 33 | public String process() throws Exception { 34 | SummaryRecord summaryRecord = new SummaryRecord(); 35 | 36 | try { 37 | for (PayrollOutputRecord outputRecord : payrollDataHolderBean.getPayrollOutputRecords()) { 38 | summaryRecord.addBonus(outputRecord.getBonus()); 39 | summaryRecord.addNet(outputRecord.getNet()); 40 | summaryRecord.addSalary(outputRecord.getSalary()); 41 | summaryRecord.addSocialSecurityTax(outputRecord.getSocialSecurityTax()); 42 | } 43 | } catch (Exception ex) { 44 | return "FAILED"; 45 | } 46 | 47 | payrollDataHolderBean.setSummaryRecord(summaryRecord); 48 | return "COMPLETED"; 49 | } 50 | ---- 51 | 52 | This Batchlet computes the total net, total salary and total socialsecurity of all the payroll records processed by first step. Once the imports have been fixed, the final `SummaryProcessor` Batchlet should looks like this: 53 | [source, java] 54 | ---- 55 | package org.glassfish.javaee7.batch.lab2; 56 | // imports omitted ! 57 | 58 | @Named 59 | public class SummaryProcessor extends AbstractBatchlet { 60 | 61 | @EJB 62 | PayrollDataHolderBean payrollDataHolderBean; 63 | 64 | public String process() throws Exception { 65 | SummaryRecord summaryRecord = new SummaryRecord(); 66 | 67 | try { 68 | for (PayrollOutputRecord outputRecord : payrollDataHolderBean.getPayrollOutputRecords()) { 69 | summaryRecord.addBonus(outputRecord.getBonus()); 70 | summaryRecord.addNet(outputRecord.getNet()); 71 | summaryRecord.addSalary(outputRecord.getSalary()); 72 | summaryRecord.addSocialSecurityTax(outputRecord.getSocialSecurityTax()); 73 | } 74 | } catch (Exception ex) { 75 | return "FAILED"; 76 | } 77 | 78 | payrollDataHolderBean.setSummaryRecord(summaryRecord); 79 | return "COMPLETED"; 80 | } 81 | 82 | } 83 | ---- 84 | 85 | -- 86 | TIP: The return type of the `process()` method of a batchlet is the exit status of the Batchlet. 87 | -- 88 | 89 | 90 | === Update the JSL 91 | 92 | We now need to update the JSL file to make sure the Batchlet is part of the job. Open "PayRollJob.xml" (in "web/WEB-INF/classes/META-INF/batch-jobs") and add the Batch "summary" step to the job as follow: 93 | [source, xml] 94 | ---- 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | ---- 111 | 112 | As mentioned before, the execution commences by executing the first step listed in the job xml. If the step completes normally, then the step specified in the "next" attrinute will be executed. 113 | -- 114 | TIP: Be aware that if you don't specify the next attribute, the execution stops after the first step! 115 | -- 116 | 117 | === Testing the Payroll application 118 | 119 | If you run the job again, you should now see an additional "TOTAL" line in the right table. Those data are computed in in the Batchlet and displayed by the `displayProcessedPayrollRecords()` method when `summaryRecord` is not null. 120 | 121 | .Total values computed by the Batchlet step 122 | image::E2.3.jpg[] 123 | 124 | 125 | === Summary 126 | 127 | In this Lab, we learnt 128 | 129 | * how to write a Batchlet step 130 | * how to combine multiple steps within a single Job 131 | 132 | 133 | -------------------------------------------------------------------------------- /chapters/exercice3.adoc: -------------------------------------------------------------------------------- 1 | :imagesdir: ../pic 2 | 3 | == Lab: Checkpoints and the JobOperator interface 4 | 5 | This exercise is focusing on two additional JSR 352 aspects: checkpoint and the JobOperator interface. 6 | 7 | *JobOperator* provides an interface to manage all aspects of job processing, including operational commands, such as start, restart, and stop, as well as job repository commands. We have already used it in previous exercises to start jobs and also to get their execution status. In this exercise, we will see how we can resume the execution of a failed job. 8 | 9 | To avoid having to restart a failed job from the beginning, JSR 352 support the concept of checkpoint. A *checkpoint* allows a step to periodically bookmark its current progress to enable restart from the last point of consistency should this job be stopped (intentionally or unintentionally). 10 | 11 | 12 | === Set the stage 13 | 14 | Open and run the "Lab 3" project. This PayRoll application is again very similar. It has a single Chunk step. The only real difference is that this application let you update, delete and add Input Records. We will use this feature to intentionally introduce corrupt data to force our job to fail. We will finally use the JobOperator interface to resume the job execution where it has failed. 15 | 16 | 17 | The GlassFish console is a useful tool to understand what is going on. Go in the "Services" tab and locate the GlassFish instance (it's probably called "GlassFish 4.1" or "GlassFish Server"). Right click on it and select "View Domain Server Log", this action will open the GlassFish Logs in the NetBeans "Output" window. 18 | 19 | .GlassFish Server Log 20 | image::E2.2.jpg[] 21 | 22 | === Start a job 23 | 24 | Locate the `displayPayrollForm()` method in the `BatchJobSubmitter` servlet. This method uses a `switch` to handle the different commands: start a job to calculate a payroll, add, update and delete input records. 25 | 26 | If you look at the `submitJobFromXML()` method that is invoked via the "calculatePayroll" command, you will notice that starting a job is easy. 27 | [source, java] 28 | ---- 29 | JobOperator jobOperator = BatchRuntime.getJobOperator(); // get a jobOperator instance 30 | Properties props = new Properties(); // set some properties 31 | id = jobOperator.start(jobName, props); // and start to job 32 | ---- 33 | 34 | 35 | A `jobOperator` instance is used to interact with the batch runtime. Once you have that instance, all you have to do is to invoke its `start()` method and pass it the jobNanme and eventually some properties (see http://docs.oracle.com/javaee/7/api/javax/batch/operations/JobOperator.html#start[javadoc]). Note that the jobName parameter is the actual name of the JSL file describing the job (without the XML extension). The 'start()' method will return an execution ID that we can use to continue to interact with the job via the batch runtime (e.g. stop the job, query the status of the job, etc.). 36 | 37 | -- 38 | TIP: The location of the job xml is spec defined. It must be defined under "WEB-INF/classes/META-INF/batch-jobs" (for war files) or under "META-INF/batch-jobs" (for ejb jar files). 39 | -- 40 | 41 | 42 | === Break the job! 43 | 44 | We will now introduce some corrupt data to force our job to fail. For example, you can update the 5th record by replacing the "," with a space and click "update". You can now start the job and "if everything goes well", your job will fail with an "Exit status: FAILED". A "restart" button should also appear on the right side of the last failed job. 45 | 46 | .Break the job 47 | image::E3.1.jpg[] 48 | 49 | In the log, we can see that the Job fails at the fifth record and that there is a checkpoint every *2* records. This is defined in the Chunk step element in the JSL file. 50 | The "item-count" attribue (the size) of the "chunk" element specify the number of items to process per chunk (10 per default). At the end, a checkpoint will be performed since this is an obvious place for such action. 51 | 52 | [source] 53 | ---- 54 | ... 55 | ...[INFO]...[ ** Calculating net pay for empId: 1 ] 56 | ...[INFO]...[ ** Calculating net pay for empId: 2 ] 57 | ...[INFO]...[ PayrollInputRecordReader: Checkpointing reader position: 2 ] 58 | ...[INFO]...[ ** Calculating net pay for empId: 3 ] 59 | ...[INFO]...[ ** Calculating net pay for empId: 4 ] 60 | ...[INFO]...[ PayrollInputRecordReader: Checkpointing reader position: 4 ] 61 | ...[SEVERE]...[[ Failure in Read-Process-Write Loop com.ibm.jbatch.container.exception.BatchContainerRuntimeException: java.util.NoSuchElementException]] 62 | ... 63 | ---- 64 | 65 | .Defining the size of the chunk step 66 | image::E3.2.jpg[] 67 | 68 | -- 69 | TIP: Any real application would obviously implement more severe validation strategies. We haven't because it's not the purpose of this exercise and we are also using that weaknesses to demonstrate some of the JSR5352 features. 70 | -- 71 | 72 | 73 | === Resume a failed job 74 | 75 | We will now update the `displayPayrollForm()` method to also handle the "restart" command. In `switch' construction, add an extra `case` with the following logic to handle the "restart" command with the following logic. 76 | 77 | [source, java] 78 | ---- 79 | case "restart": 80 | executionId = restartJob(executionId); 81 | session.setAttribute("executionId", executionId); 82 | break; 83 | ---- 84 | Restarting a failed job is also done via the jobOperator interface and more particularly via its `restart()` method. We pass, to this method, the execution ID of the failed job and we get in return a new execution ID. 85 | 86 | -- 87 | TIP: JSR 352 allows only the most recent execution id to the restart method. Thats why our application attaches the restart button to the most recent job! 88 | -- 89 | 90 | If you fix and update the wrong input record and "restart" the job, the job should now exit with a "COMPLETED" status. 91 | 92 | If you check the GlassFish log, you will notice that job is restarted from the last known checkpint (i.e. 4) so it read and process the next item (5 in this case). A final checkpoint is performed after the last record. 93 | 94 | [source] 95 | ---- 96 | ...[INFO]...[ PayrollInputRecordReader: resuming from: 4 ] 97 | ...[INFO]...[ ** Calculating net pay for empId: 5 ] 98 | ...[INFO]...[ PayrollInputRecordReader: Checkpointing reader position: 5 ] 99 | ---- 100 | 101 | 102 | 103 | === Summary 104 | 105 | Job restarts (resumption of jobs rather) is possible due to the checkpointing mechanism. Execution of a check style step commences by the batch runtime calling the ItemReader's `open()` method. If the step is not due to a re-start (meaning a the job is being executed using `jobOperator.start()`) then a `null` value is passed to the `open()` method (else the previous checkpointed data is passed). 106 | Once every "item-count" (chunk size) number of items have been written out by the ItemWriter, the Batch runtime calls the `checkpointInfo()` method on the ItemReader. The item reader can return any Serializable data that captures its current state (like number of items read etc.). This Serializable data will be saved by the batch runtime in the JobRepository and allows the batch runtime to track the last known checkpointed state. 107 | If the job were to fail now (or before the next checkpoint), the Job can be resumed by calling the `JobOperator.restart()` method. Job restart processing begins by the batch runtime calling the ItemReader's `open()` method with the previous run's checkpointed data. This allows the ItemReader to resume reading from the previous successful point and thus allows the Job to resume rather than start from the beginning. 108 | 109 | 110 | 111 | 112 | -------------------------------------------------------------------------------- /chapters/exercice4.adoc: -------------------------------------------------------------------------------- 1 | :imagesdir: ../pic 2 | 3 | == Lab: Listeners 4 | 5 | In the first exercise, we have created the simple batch application from scratch. 6 | This exercise will build on that initial application and will introduce listeners. 7 | *Listeners* are used to intervene, at the different levels, during the life-cylcle of a batch job. 8 | 9 | A listener is configured to receive the execution control at some well defined phases during the execution of the job. 10 | They can be configured at different level (step level before or after, job level, ...) 11 | Technically, a listener is a class that that implements one of the listener interfaces defined in the JSR 352 specification. 12 | 13 | === Set the stage 14 | 15 | We will now start from a NetBeans project that already contains a simple batch application. So just open the "Lab4" project in NetBeans. 16 | As you explore the project files, you will notice the servlet that is used to control the batch, the reader, the processor and the writer, the JSL that defines the job, etc. 17 | In short, this application does almost what we developed in the first exercise. 18 | The only real difference is that it is now possible to add Payroll input records in the UI and restart the last executed job. Run the job and check the result in the GlassFish console. 19 | 20 | [source] 21 | ---- 22 | ... PayrollInputRecordReader: resuming from: 0 23 | ... ** Calculating net pay for empId: 1 24 | ... ** Calculating net pay for empId: 2 25 | ... ** Calculating net pay for empId: 3 26 | ... PayrollInputRecordReader: Checkpointing reader position: 3 27 | ... ** Calculating net pay for empId: 4 28 | ... ** Calculating net pay for empId: 5 29 | ... PayrollInputRecordReader: Checkpointing reader position: 5 30 | ---- 31 | 32 | 33 | === Defining a listener at the Job level 34 | 35 | Let's define a listener at the job level. 36 | For that, you should create a class called "PayrollJobListener" that implements the `javax.batch.api.listener.JobListener` interface. 37 | Make sure to decorate the class with the `@Named` annotation. 38 | NetBeans will help you to resolve the missing import and implement the abstract methods : `beforeJob()` and `afterJob()`. 39 | 40 | To use, in the listener, information related to the job instance, we need to inject the job context object. 41 | 42 | [source,java] 43 | ---- 44 | @Inject 45 | JobContext jobContext; 46 | ---- 47 | 48 | -- 49 | TIP: Since this is a Job level listener, there is no Step context. 50 | -- 51 | 52 | Rewrite the 2 methods as follow : 53 | [source,java] 54 | ---- 55 | @Override 56 | public void beforeJob() throws Exception { 57 | System.out.println("** PayrollJobListener:: Job started at: " + (new Date())); 58 | } 59 | 60 | @Override 61 | public void afterJob() throws Exception { 62 | System.out.println("** PayrollJobListener:: Job completed at: " + (new Date()) 63 | + "; exitStatus : " + jobContext.getExitStatus() + "; " + jobContext.getBatchStatus()); 64 | } 65 | ---- 66 | 67 | The last thing we need to do is to update the JSL to include this listener ans since it is a Job level listener, we should make sure to define it at the job level! 68 | [source,xml] 69 | ---- 70 | 71 | 72 | 73 | 74 | 75 | ... 76 | ---- 77 | 78 | If we run the batch once again, we can observer in the console that the job level listener has been invoked at the beginning (`beforeJob()` method) and at the end (`afterJob()` method). 79 | [source] 80 | ---- 81 | Info: ** PayrollJobListener:: Job started at: Tue Aug 12 82 | Info: ** PayrollStepListener:: Step started at: Tue Aug 12; stepContext: STARTED 83 | Info: PayrollInputRecordReader: resuming from: 0 84 | Info: ** Calculating net pay for empId: 1 85 | Info: ** Calculating net pay for empId: 2 86 | Info: ** Calculating net pay for empId: 3 87 | Info: PayrollInputRecordReader: Checkpointing reader position: 3 88 | Info: ** Calculating net pay for empId: 4 89 | Info: ** Calculating net pay for empId: 5 90 | Info: PayrollInputRecordReader: Checkpointing reader position: 5 91 | Info: ** PayrollStepListener:: Step ended at: Tue Aug 12; stepContext: STARTED 92 | Info: ** PayrollJobListener:: Job completed at: Tue Aug 12; exitStatus : null; STARTED 93 | ---- 94 | 95 | === Defining listener(s) at the Step level 96 | 97 | Setting listeners at the level of the job might be, in some cases, too coarse grained. 98 | Luckily, JSR 352 allows us to define listeners at the step level. 99 | 100 | In the project source directory, create a new java class called "PayrollStepListener". 101 | This class needs to implement the `javax.batch.api.listener.StepListener` interface. 102 | Use NetBeans to resolve the import and implements the abstract methods. 103 | 104 | You should now have 2 methods : `beforeStep()` and `afterStep()` 105 | 106 | In the previous listener, we used the Job context but this time, we have also the step context at our disposal. 107 | You can inject the step context in your listener. 108 | 109 | [source,java] 110 | ---- 111 | @Inject 112 | StepContext stepContext; 113 | ---- 114 | 115 | We will use this context to gather some information. 116 | Update the `beforeStep()` and `afterStep()` methods as follow (make the necessary changes for the 2nd method). 117 | 118 | [source,java] 119 | ---- 120 | System.out.println("\t** PayrollStepListener:: Step started at: " + (new Date()) 121 | + "; stepContext: " + stepContext.getBatchStatus()); 122 | ---- 123 | 124 | -- 125 | TIP: Make sure to annotate the class declaration with the `@Named` annotation. 126 | -- 127 | 128 | Now that we have defined the implementation of the listener, we need to update the batch JSL to reference it. 129 | Update the step defined in the JSL as follow: 130 | 131 | [source,xml] 132 | ---- 133 | ... 134 | 135 | 136 | 137 | 138 | ... 139 | ---- 140 | 141 | If you run the batch, you will see that our 2 listeners are correctly invoked. 142 | You can also notice the listener invokation chain order : _job before_, _step before_, _step after_, _job after_. 143 | [source] 144 | ---- 145 | Info: ** PayrollJobListener:: Job started at: Thu Jul 31 04:06:39 CEST 2014 146 | Info: ** PayrollStepListener:: Step started at: Thu Jul 31 04:06:39 CEST 2014; stepContext: STARTED 147 | Info: ** Calculating net pay for empId: 1 148 | ... 149 | Info: ** Calculating net pay for empId: 5 150 | Info: ** PayrollStepListener:: Step completed at: Thu Jul 31 04:06:39 CEST 2014; stepContext: STARTED 151 | Info: ** PayrollJobListener:: Job completed at: Thu Jul 31 04:06:39 CEST 2014; exitStatus : null; STARTED 152 | ---- 153 | 154 | === Defining listener(s) within a Step 155 | 156 | We saw that we can define listeners at the level of a Job and at the level of a Step but this might still be too coarse grained. 157 | JSR 352 also allows to define listeners within a step itself. 158 | 159 | Before adding this listener, let's simulate a use case in the application by adding a record. 160 | Make sure to respect the format expected by the application : int,salary. 161 | For example, fill in "6,10000" and click "add". 162 | You can now launch the job. After you have hit "refresh", the displayed results should includes the record you have just added. 163 | 164 | .Adding a record 165 | image::E2.1.png[] 166 | 167 | Let's now pretend we did a mistake and add a record using an incorrect format (e.g. "61000"). 168 | If you now run the batch again, GlassFish will throw some exceptions as clearly the application can only handle record correctly formated. 169 | 170 | [source] 171 | ---- 172 | Info: ** Calculating net pay for empId: 4 173 | Info: ** Calculating net pay for empId: 5 174 | Severe: Failure in Read-Process-Write Loop 175 | com.ibm.jbatch.container.exception.BatchContainerRuntimeException: java.lang.IllegalArgumentException: Salary cannot be null 176 | ... 177 | Warning: Caught throwable in chunk processing. Attempting to close all readers and writers. 178 | Warning: Caught exception executing step: com.ibm.jbatch.container.exception.BatchContainerRuntimeException: Failure in Read-Process-Write Loop 179 | ... 180 | Caused by: com.ibm.jbatch.container.exception.BatchContainerRuntimeException: java.lang.IllegalArgumentException: Salary cannot be null 181 | ... 182 | Caused by: java.lang.IllegalArgumentException: Salary cannot be null 183 | ... 184 | ---- 185 | 186 | Our step is made of a reader, a processor and a writer. 187 | JSR 352 allows to also define listener at this level, i.e. within a step. 188 | In this example, we will define a listener at the reader level. 189 | Typically, such a listener would be used to intervene and handle any misread data by the reader. 190 | 191 | In the source directory, create a new java class called "PayrollInputRecordReadListener" and decorate it with the `@Named` annotation. 192 | As we want a reader at the reader level, we need to implements the `javax.batch.api.chunk.listener.ItemReadListener` interface, so update your class definition accordingly. 193 | Use NetBeans to implement the abstract methods of the interface. 194 | 195 | We can inject, in our listener, contexts: the job and the step context. 196 | 197 | [source,java] 198 | ---- 199 | @Inject 200 | JobContext jobContext; 201 | 202 | @Inject 203 | StepContext stepContext; 204 | ---- 205 | 206 | You can remove the body of the `beforeRead()` and the `afterRead()` methods as we won't use them. 207 | Change the `onReadError()` method as follows: 208 | [source,java] 209 | ---- 210 | @Override 211 | public void onReadError(Exception ex) throws Exception { 212 | System.out.println("\t** PayrollInputRecordReadListener:: onReadError : " 213 | + stepContext.getTransientUserData() + "; Exception: " + ex); 214 | } 215 | ---- 216 | 217 | Your `PayrollInputRecordReadListener.java` listener should now looks like this. 218 | [source,java] 219 | ---- 220 | package org.glassfish.javaee7.batch.lab4; 221 | import javax.batch.api.chunk.listener.ItemReadListener; 222 | import javax.batch.runtime.context.JobContext; 223 | import javax.batch.runtime.context.StepContext; 224 | import javax.inject.Inject; 225 | import javax.inject.Named; 226 | 227 | @Named 228 | public class PayrollInputRecordReadListener 229 | implements ItemReadListener { 230 | 231 | @Inject 232 | JobContext jobContext; 233 | 234 | @Inject 235 | StepContext stepContext; 236 | 237 | @Override 238 | public void beforeRead() throws Exception { 239 | } 240 | 241 | @Override 242 | public void afterRead(Object item) throws Exception { 243 | } 244 | 245 | @Override 246 | public void onReadError(Exception ex) throws Exception { 247 | System.out.println("\t** PayrollInputRecordReadListener:: onReadError : " 248 | + stepContext.getTransientUserData() + "; Exception: " + ex); 249 | } 250 | } 251 | ---- 252 | 253 | Now that we have defined the listener implementation, we need to configure our job JSL file as follow: 254 | 255 | [source,xml] 256 | ---- 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | ---- 270 | 271 | If you test the batch with a incorrect record, you will notice that the Listener is invoked but you can also see that exceptions are still thrown. 272 | [source] 273 | ---- 274 | ... 275 | Info: ** Calculating net pay for empId: 4 276 | Info: ** Calculating net pay for empId: 5 277 | Info: ** PayrollInputRecordReadListener:: onReadError : null; Exception: java.lang.IllegalArgumentException 278 | Severe: Failure in Read-Process-Write Loop 279 | com.ibm.jbatch.container.exception.BatchContainerRuntimeException: java.util.NoSuchElementException... 280 | ... 281 | ---- 282 | 283 | To avoid that, we can define a set of exceptions that can be skipped if they are thrown during the execution of the step. 284 | To do that, define at the step level in the JSL which exception(s) can be skipped. 285 | [source,xml] 286 | ---- 287 | 288 | 289 | 290 | 291 | ---- 292 | 293 | 294 | The updated JSL should now looks like this (previous listeners have been removed for shortness, you can keep them): 295 | [source,xml] 296 | ---- 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | ---- 315 | 316 | If you try again to run the batch job with an incorrect record, you should get the following output in the GlassFish console. 317 | [source] 318 | ---- 319 | Info: ** Calculating net pay for empId: 1 320 | Info: ** Calculating net pay for empId: 2 321 | Info: ** Calculating net pay for empId: 3 322 | Info: ** Calculating net pay for empId: 4 323 | Info: ** Calculating net pay for empId: 5 324 | Info: ** PayrollInputRecordReadListener:: onReadError : null; Exception: java.lang.IllegalArgumentException: Salary cannot be null 325 | ---- 326 | 327 | === Summary 328 | 329 | In this Lab, we learnt how to define and use listener to intervene within the life-cycle of a batch job. 330 | -------------------------------------------------------------------------------- /chapters/exercice5.adoc: -------------------------------------------------------------------------------- 1 | :imagesdir: ../pic 2 | 3 | == Lab: Job Partitioning 4 | 5 | By default, all steps in a job run on the same thread. Multi-threading can be leveraged to increase throughput and better utilize underlying hardware, that is what *partitioned step* brings. A serially processed step can be broken it into *partitions* that will run on different threads. Once we have defined the partition strategy, the batch runtime will manage the threads and will handle all aspects of checkpoints. 6 | 7 | 8 | === Set the stage 9 | 10 | We will start from an usual payroll batch job and will enhance it to support partition. Open Lab 5 and launch the `PartitionedJobSubmitterServlet.java` servlet. In this application, you can select for which month the payroll should be calculated. Don't run a batch job at this stage, as it will fails. 11 | 12 | 13 | 14 | === Define the partition strategy 15 | 16 | JSR 352 defines an interface called `PartitionMapper` (http://docs.oracle.com/javaee/7/api/javax/batch/api/partition/PartitionMapper.html[javadoc]) that provides a programmatic means for calculating the number of partitions and threads for a partitioned step. 17 | 18 | So create a java classes called "PayrollPartitionMapper", implements the PartitionMapper interface. And as usual, decorate the class with the `@Named("PayrollPartitionMapper)` annotation, resolve any missing imports and implements the abstract methods imposed by the interface. 19 | 20 | 21 | Inject the JobConext and the SampleDataHolderBean as we will need them. 22 | 23 | [source, java] 24 | ---- 25 | @Inject 26 | private JobContext jobContext; 27 | 28 | @EJB 29 | private SampleDataHolderBean bean; 30 | ---- 31 | 32 | 33 | The `mapPartitions()` method return a `PartitionPlan` object, so let's modify the body of the method as follow : 34 | [source, java] 35 | ---- 36 | @Override 37 | public PartitionPlan mapPartitions() throws Exception { 38 | 39 | return new PartitionPlanImpl() { 40 | @Override 41 | public int getPartitions() { 42 | return 5; 43 | } 44 | 45 | @Override 46 | public Properties[] getPartitionProperties() { 47 | Properties jobParameters = BatchRuntime.getJobOperator().getParameters(jobContext.getExecutionId()); 48 | 49 | String monthYear = (String) jobParameters.get("monthYear"); 50 | int partitionSize = bean.getMaxEmployees() / getPartitions(); 51 | 52 | System.out.println("**[PayrollPartitionMapper] jobParameters: " + jobParameters 53 | + "; executionId: " + jobContext.getExecutionId() + "; partitionSize = " + partitionSize); 54 | 55 | Properties[] props = new Properties[getPartitions()]; 56 | for (int i=0; i 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | ---- 128 | 129 | 130 | 131 | === Test the partitioned execution 132 | 133 | If you now run the job for a particular month, you will see in the GlassFish logs that data are spread across 5 threads as defined by the `getPartitions()` method of the partition mapper. You can also see the data range that each partition is assigned. 134 | 135 | [source] 136 | ---- 137 | Info: ** JobSubmitterServlet: JAN-2013 138 | Info: **[PayrollPartitionMapper] jobParameters: {monthYear=JAN-2013}; executionId: 79; partitionSize = 6 139 | Info: **[PayrollPartitionMapper[0/5] : {endEmpID=6, partitionNumber=0, startEmpID=0, monthYear=JAN-2013} 140 | Info: **[PayrollPartitionMapper[1/5] : {endEmpID=12, partitionNumber=1, startEmpID=6, monthYear=JAN-2013} 141 | Info: **[PayrollPartitionMapper[2/5] : {endEmpID=18, partitionNumber=2, startEmpID=12, monthYear=JAN-2013} 142 | Info: **[PayrollPartitionMapper[3/5] : {endEmpID=24, partitionNumber=3, startEmpID=18, monthYear=JAN-2013} 143 | Info: **[PayrollPartitionMapper[4/5] : {endEmpID=30, partitionNumber=4, startEmpID=24, monthYear=JAN-2013} 144 | Info: SimpleItemReader[partition #2 will process from employeeId: 12 to 18 for the month of JAN-2013 145 | Info: SimpleItemReader[partition #0 will process from employeeId: 0 to 6 for the month of JAN-2013 146 | Info: SimpleItemReader[partition #1 will process from employeeId: 6 to 12 for the month of JAN-2013 147 | Info: SimpleItemReader[partition #4 will process from employeeId: 24 to 30 for the month of JAN-2013 148 | Info: SimpleItemReader[partition #3 will process from employeeId: 18 to 24 for the month of JAN-2013 149 | ---- 150 | 151 | 152 | 153 | 154 | 155 | === Summary 156 | 157 | In this Lab, we learnt how to use Partition Mapper to distribute batch processing on different threads. 158 | 159 | 160 | //////////////////////////// -------------------------------------------------------------------------------- /chapters/introduction.adoc: -------------------------------------------------------------------------------- 1 | :imagesdir: ../pic 2 | 3 | == Introduction 4 | 5 | Batch processing is used in many industries for tasks ranging from payroll processing; statement generation; end-of-day jobs such as interest calculation, ETL (extract, load, and transform) in a data warehouse; and many more. Typically, batch processing is bulk-oriented, non-interactive, and long running and might be data or computation-intensive. Batch jobs can be run on schedule or initiated on demand. Also, since batch jobs are typically long-running jobs, check-pointing and restarting are common features found in batch jobs. 6 | 7 | JSR 352 (Batch Processing for Java Platform), part of the Java EE 7 platform, defines the programming model for batch applications and the runtime to run and manage batch jobs. This Hands-on Lab will take you through the key concepts of JSR352. 8 | 9 | === Software Requirements 10 | 11 | The following software are needed for this Lab. 12 | 13 | -- 14 | TIP: JavaOne attendees, everything has been installed and pre-configured for you! 15 | -- 16 | 17 | * *Java SE*: JDK 7 or JDK 8 is required. The JDK can be downloaded from 18 | http://www.oracle.com/technetwork/java/javase/downloads/index.html[http://www.oracle.com/technetwork/java/javase/downloads/index.html]. 19 | * *Java EE 7 Application Server*: This Lab uses the latest release of GlassFish, i.e. GlassFish Server Open Source Edition 4.1 (GF 4.0 should also work). Any other Java EE 7 (Full Platform) Application Server should work as well. Since JSR 352 is part of the Full Platform, this lab will not run on a Java EE 7 Web Profile Application Server. 20 | 21 | * *IDE*: This Lab uses NetBeans 8.0 but any IDE supporting Java EE 7 should work. 22 | 23 | 24 | === Lab Overview 25 | 26 | This Lab is divided in 5 exercises : 27 | 28 | * *Lab 1* will introduce you the main concepts of JSR 352 such as Step, Job, JSL, etc. In this exercise, you will be guided to build from scratch a complete application that will run a simple batch job to perform some hypothetical payroll calculations. 29 | 30 | * *Lab 2* will enhance the first exercise and introduce mutli-steps jobs combining Chunk step with a Batchlet step.. 31 | 32 | * *Lab 3* will cover checkpoint and the JobOperator interface which can be used to resume failed job. 33 | 34 | * *Lab 4* will build introduce you to listeners, a mechanism that can be used to intervene within the life-cycle of a batch job (e.g. to catch errors). 35 | 36 | * *Lab 5* will introduce the concept of Job Partitioning, a more advanced feature of JSR 352. 37 | 38 | Unless you are already familiar with the Batch API, it is recommended to follow the suggested exercises order. 39 | 40 | 41 | === Where to get help 42 | 43 | Here are some advices if you are stuck during the Lab... 44 | 45 | * Check that your imports are correct, e.g. a `java.util.list` is not really a `java.awt.list` ! 46 | 47 | * Make sure that the code you have copy/pasted is correct and complete. 48 | 49 | * If your code doesn't compile, NetBeans will show where the error is and will also provide some suggestions on how it could be fixed. 50 | 51 | * It is sometime useful to re-read a section from the beginning. 52 | 53 | * The solutions should be used as a final resort to to pinpoints hard to find issues. 54 | 55 | 56 | At any time, feel free to ask a JavaOne Proctor, they are here to help you! 57 | 58 | === Important note 59 | 60 | WARNING: The sample applications and the code may not always be following best practices (e.g. data validation, correct error handling, leverage the lastest Java SE features, etc.). This is intentional such as to stay focused on explaining JSR 352. It is highly recommended to make sure that the code copied from this lab is updated to meet the requirements of any production application! 61 | 62 | //// 63 | === TO DO 64 | 65 | * Copyright / License to use? 66 | * How to start GF 67 | * Add a key map in the Help (Fix import, Reformat, ...) 68 | * Add info about expected audience, assumptions and timing 69 | //// 70 | -------------------------------------------------------------------------------- /lab1 solution/Lab1.txt: -------------------------------------------------------------------------------- 1 | Objective: 2 | 3 | To Learn: 4 | 5 | Structure of a Batch Job 6 | ItemReader, ItemProcessor, ItemWriter 7 | Job XML 8 | Steps 9 | Specifying the Item{Reader, Processor, Writer} for a Step. 10 | 11 | Packaging requirements 12 | Placing Job XMl under META-INF/batch-jobs 13 | Multiple Job xmls can be placed under this directory. 14 | 15 | Using JobOperator APIs 16 | How to submit a Batch Job 17 | Using JobOperator APIs to query Job status 18 | 19 | Difference between executionId and instanceId 20 | 21 | 22 | About the application used in lab1 23 | 24 | Mimics a rudimentary Payroll processing system. 25 | Input data comes from a EJB Singleton as coma separated records. 26 | The Job XML has only one step. 27 | ItemReader: 28 | Reads list of CSV from the Singleton bean and converts each line into a 29 | PayrollInputRecord. This shields the rest of the application from 30 | knowing the source of the input data. By providing appropriate ItemReader 31 | the rest of the application need not worry about the source of input data. 32 | ItemProcessor: 33 | Processes the input data (PayrollInputRecord) and computes the social security 34 | tax and net pay. It produces a PayrollOutputRecord for each processed 35 | input record. 36 | ItemWriter: 37 | Writes / Saves the processed data into the Singleton bean itself. Different 38 | ItemWriters can be written to store the processed data in a variety of 39 | stores. 40 | 41 | Summary: 42 | 43 | We learnt about Job XML structure and packaging requirements. 44 | 45 | We learnt about how to write Item{Reader, Processor, Writer} for a Step. 46 | 47 | We learnt how to: Start and Query the Batch jobs using JobOperator APIs. 48 | -------------------------------------------------------------------------------- /lab1 solution/build.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Builds, tests, and runs the project lab1 solution. 12 | 13 | 71 | 72 | -------------------------------------------------------------------------------- /lab1 solution/nbproject/ant-deploy.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 102 | 103 | 104 | 105 | 106 | 107 | 109 | 110 | 111 | 112 | -------------------------------------------------------------------------------- /lab1 solution/nbproject/genfiles.properties: -------------------------------------------------------------------------------- 1 | build.xml.data.CRC32=90c7a06d 2 | build.xml.script.CRC32=eb434d5d 3 | build.xml.stylesheet.CRC32=651128d4@1.69.0.1 4 | # This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. 5 | # Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. 6 | nbproject/build-impl.xml.data.CRC32=90c7a06d 7 | nbproject/build-impl.xml.script.CRC32=0f48d970 8 | nbproject/build-impl.xml.stylesheet.CRC32=99ea4b56@1.69.0.1 9 | -------------------------------------------------------------------------------- /lab1 solution/nbproject/private/private.properties: -------------------------------------------------------------------------------- 1 | deploy.ant.properties.file=/Users/davidd/Library/Application Support/NetBeans/dev/config/GlassFishEE6/Properties/gfv3743454947.properties 2 | j2ee.platform.is.jsr109=true 3 | j2ee.server.domain=/work/gf/41/08-10/glassfish4/glassfish/domains/domain1 4 | j2ee.server.home=/work/gf/41/08-10/glassfish4/glassfish 5 | j2ee.server.instance=[/work/gf/41/08-10/glassfish4/glassfish:/work/gf/41/08-10/glassfish4/glassfish/domains/domain1]deployer:gfv3ee6wc:localhost:4848 6 | j2ee.server.middleware=/work/gf/41/08-10/glassfish4 7 | javac.debug=true 8 | javadoc.preview=true 9 | selected.browser=default 10 | user.properties.file=/Users/davidd/Library/Application Support/NetBeans/dev/build.properties 11 | -------------------------------------------------------------------------------- /lab1 solution/nbproject/private/private.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | file:/work/j1/hol/dd/lab1/src/java/org/glassfish/javaee7/batch/lab1/BatchJobSubmitter.java 7 | file:/work/j1/hol/dd/lab1/web/WEB-INF/classes/META-INF/batch-jobs/PayrollJob.xml 8 | file:/work/j1/hol/dd/lab1/src/java/org/glassfish/javaee7/batch/lab1/NetPayProcessor.java 9 | file:/work/j1/hol/dd/lab1/src/java/org/glassfish/javaee7/batch/lab1/PayrollDataHolderBean.java 10 | file:/work/j1/hol/dd/lab1/src/java/org/glassfish/javaee7/batch/lab1/PayrollInputRecord.java 11 | file:/work/j1/hol/dd/lab1/src/java/org/glassfish/javaee7/batch/lab1/PayrollInputRecordReader.java 12 | file:/work/j1/hol/dd/lab1/src/java/org/glassfish/javaee7/batch/lab1/PayrollOutputRecord.java 13 | file:/work/j1/hol/dd/lab1/src/java/org/glassfish/javaee7/batch/lab1/PayrollOutputRecordWriter.java 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /lab1 solution/nbproject/private/retriever/catalog.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /lab1 solution/nbproject/private/retriever/www.oracle.com/webfolder/technetwork/jsc/xml/ns/javaee/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Java EE: XML Schemas for Java EE Deployment Descriptors 6 | 20 | 21 | 22 | 23 |
24 | 25 |
26 | 27 | 28 | 29 |

Java EE: XML Schemas for Java EE Deployment Descriptors

30 | 31 | 32 | 33 | 34 | 35 | 39 |
36 | By Bill Shannon, 37 | Java EE Spec Lead, Oracle, April 30, 2013 38 |
40 |

41 |

Latest Version: http://xmlns.jcp.org/xml/ns/javaee/

42 |
Contents
43 |  
44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 |
Introduction
Using Java EE Schemas
Java EE 7 Schema Resources
Java EE 6 Schema Resources
Java EE 5 Schema Resources
J2EE 1.4 XML Schemas
J2EE 1.3 DTDs
J2EE 1.2 DTDs
54 |  
55 | 56 |
Introduction
57 |
58 |

59 |

60 | This document lists the document formats that will be used by the 61 | 62 | Java Platform, Enterprise Edition (Java EE) 63 | deployment descriptors described by Java EE 5 and later specifications. 64 | Prior to the J2EE 1.4 specifications, each Deployment Descriptor was required 65 | to be valid with respect to a specific DTD 66 | that describes the Deployment Descriptor. 67 | The DTDs are found in the J2EE section of 68 | this document. 69 | Starting with 70 | the J2EE 1.4 specification, each specification requires its Deployment 71 | Descriptor be validated with respect to an XML Schema that is listed in 72 | the J2EE 1.4 document 73 | and this document. 74 | Note that deployment descriptors defined by previous 75 | versions of the Java EE specification must also be supported by all current 76 | Java EE products, and must 77 | continue to be validated against the corresponding DTD or schema. 78 | Note that not all deployment descriptors are updated for every 79 | release of Java EE, in which case the deployment descriptor from 80 | the previous version is used. 81 |

82 |

83 | The Java EE specification also requires support for the Java Persistence API. 84 | The Java Persistence API Schemas are available at 85 | http://xmlns.jcp.org/xml/ns/persistence/ 86 |

87 |

88 | This document describes how to use the Java EE schemas 89 | and provides a list of XML Schemas for each 90 | deployment descriptor. 91 |

92 | 93 |
Using Java EE Schemas
94 |
95 |

96 |

All Java EE 7 and newer Deployment Descriptor Schemas share the namespace 97 | http://xmlns.jcp.org/xml/ns/javaee/. 98 | Each schema 99 | document contains a version attribute that contains the version of the 100 | specification. For example, the XML Schema document for the Servlet 101 | specification contains the version attribute value "3.1", pertaining to 102 | the specific version of the specification as well as the schema 103 | document itself. 104 |

105 |

106 | Each Java EE XML Schema document's file name contains the specific version 107 | of the related specification. This is introduced for convenience to 108 | locate specific versions of the schema documents. However, Deployment 109 | Descriptor instances are not required to refer to a specific file. 110 | Instead, an instance must specify the version of the corresponding 111 | specification by using the version attribute. For example, servlet 112 | Deployment Descriptor instances that must be processed with the 113 | servlet 114 | 3.1 version must indicate the version within the version attribute of 115 | the instance document, for example, "3.1". The Deployment Descriptor 116 | processors use the version information to choose the appropriate 117 | version of the schema document(s) to process the Deployment Descriptor 118 | instances. 119 |

120 |

121 | A specific version of the Java EE specification contains a set of 122 | deployment descriptor schemas to constitute the Java EE Schema. The common 123 | definitions are contained in the javaee_<version>.xsd 124 | document that may be included by several Java EE Deployment Descriptor 125 | schemas. 126 |

127 | 128 |
Java EE 7 Schema Resources
129 |
130 |

131 |

132 | This table contains the XML Schema components for Java EE 7 schema. 133 | All new schemas are in the 134 | http://xmlns.jcp.org/xml/ns/javaee/ 135 | namespace. 136 | Most older schemas remain in the 137 | http://java.sun.com/xml/ns/javaee/ 138 | namespace. 139 |

140 |

141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 |
Date PublishedFile NameDescriptionStatus
April 30, 2013application_7.xsdApplication schema Final Release
April 30, 2013application-client_7.xsdApplication Client schema Final Release
April 30, 2013batchXML_1_0.xsdSchema for batch.xml-based artifact loading in Java BatchFinal Release
April 30, 2013beans_1_1.xsdContexts and Dependency Injection schemaFinal Release
April 30, 2013connector_1_7.xsdJava EE Connector schemaFinal Release
April 30, 2013ejb-jar_3_2.xsdEnterprise JavaBeans Deployment Descriptor SchemaFinal Release
April 30, 2013javaee_7.xsdJava EE 7 definitions file that contains common schema componentsFinal Release
April 30, 2013javaee_web_services_1_4.xsdWeb services schemaFinal Release
April 30, 2013javaee_web_services_client_1_4.xsdWeb services client schemaFinal Release
April 30, 2013jobXML_1_0.xsdBatch Job Specification Language (JSL) schemaFinal Release
April 30, 2013jsp_2_3.xsdJavaServer Pages Deployment Descriptor schemaFinal Release
April 30, 2013permissions_7.xsdJava EE application permissions schemaFinal Release
April 30, 2013web-app_3_1.xsdWeb Application Deployment Descriptor schemaFinal Release
April 30, 2013web-common_3_1.xsdWeb Application Deployment Descriptor common definitions schemaFinal Release
April 30, 2013web-fragment_3_1.xsdWeb Application Deployment Descriptor fragment schemaFinal Release
April 30, 2013web-facelettaglibrary_2_2.xsdJavaServer Faces Facelet Tag Library schema 243 | Final Release
April 30, 2013web-facesconfig_2_2.xsdJavaServer Faces Application Configuration File schemaFinal Release
April 30, 2013web-partialresponse_2_2.xsdJavaServer Faces partial response schemaFinal Release
July 1, 2009web-facesuicomponent_2_0.xsdJavaServer Faces UI Component Configuration schemaFinal Release
December 10, 2009web-jsptaglibrary_2_1.xsdJSP Taglibrary Deployment Descriptor schemaFinal Release
November 21, 2007javaee_web_services_metadata_handler_2_0.xsdWeb services schemaFinal Release
-http://www.w3.org/2001/xml.xsdThe Java EE schemas use some common definitions provided and published by W3C-
283 |

284 |
285 |
286 | 287 |
Java EE 6 Schema Resources
288 |
289 |

290 |

291 | This table contains the XML Schema components for Java EE 6 schema. 292 | All of these schemas are in the 293 | http://java.sun.com/xml/ns/javaee 294 | namespace. 295 |

296 | 297 |

298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 311 | 312 | 313 | 314 | 315 | 317 | 319 | 320 | 321 | 322 | 323 | 325 | 327 | 328 | 329 | 330 | 331 | 333 | 335 | 336 | 337 | 338 | 339 | 341 | 342 | 343 | 344 | 345 | 346 | 349 | 350 | 351 | 352 | 353 | 355 | 357 | 358 | 359 | 360 | 361 | 363 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | 391 | 392 | 393 | 395 | 396 | 397 | 398 | 399 | 400 | 402 | 403 | 404 | 405 | 406 | 407 | 409 | 410 | 411 | 412 | 413 | 414 | 416 | 417 | 418 | 419 | 420 | 422 | 423 | 424 | 425 | 426 | 427 | 429 | 431 | 432 | 433 | 434 | 435 | 436 | 439 | 440 | 441 |
Date PublishedFile NameDescriptionStatus
December 10, 2009application_6.xsdApplication schema 310 | Final Release
December 10, 2009application-client_6.xsdApplication Client schema 318 | Final Release
December 10, 2009beans_1_0.xsdContexts and Dependency Injection schema 326 | Final Release
December 10, 2009connector_1_6.xsdJava EE Connector schema 334 | Final Release
December 10, 2009ejb-jar_3_1.xsdEnterprise JavaBeans Deployment Descriptor 340 | SchemaFinal Release
December 10, 2009javaee_6.xsdJava EE 6 definitions file that 347 | contains common schema components 348 | Final Release
December 10, 2009javaee_web_services_1_3.xsdWeb services schema 356 | Final Release
December 10, 2009javaee_web_services_client_1_3.xsdWeb services client schema 364 | Final Release
December 10, 2009jsp_2_2.xsdJavaServer Pages Deployment Descriptor schemaFinal Release
December 10, 2009web-app_3_0.xsdWeb Application Deployment Descriptor schemaFinal Release
December 10, 2009web-common_3_0.xsdWeb Application Deployment Descriptor common definitions schemaFinal Release
December 10, 2009web-fragment_3_0.xsdWeb Application Deployment Descriptor fragment schemaFinal Release
July 1, 2009web-facelettaglibrary_2_0.xsdJavaServer Faces Facelet Tag Library schema 394 | Final Release
July 1, 2009web-facesconfig_2_0.xsdJavaServer Faces Application Configuration File schema 401 | Final Release
July 1, 2009web-facesuicomponent_2_0.xsdJavaServer Faces UI Component Configuration schema 408 | Final Release
July 1, 2009web-partialresponse_2_0.xsdJavaServer Faces partial response schema 415 | Final Release
December 10, 2009web-jsptaglibrary_2_1.xsdJSP Taglibrary Deployment Descriptor schemaFinal Release
November 21, 2007javaee_web_services_metadata_handler_2_0.xsdWeb services schema 430 | Final Release
-http://www.w3.org/2001/xml.xsdThe Java EE schemas use some 437 | common definitions provided and published by W3C 438 | -
442 |

443 |
444 |
445 | 446 |
Java EE 5 Schema Resources
447 |
448 |

449 |

450 | This table contains the XML Schema components for Java EE 5 schema. 451 | All of these schemas are in the 452 | http://java.sun.com/xml/ns/javaee 453 | namespace. 454 |

455 | 456 |

457 | 458 | 459 | 460 | 461 | 462 | 463 | 464 | 465 | 466 | 467 | 468 | 470 | 471 | 472 | 473 | 474 | 476 | 478 | 479 | 480 | 481 | 482 | 484 | 485 | 486 | 487 | 488 | 489 | 492 | 493 | 494 | 495 | 496 | 498 | 500 | 501 | 502 | 503 | 504 | 506 | 508 | 509 | 510 | 511 | 512 | 514 | 515 | 516 | 517 | 518 | 519 | 520 | 521 | 522 | 523 | 524 | 526 | 527 | 528 | 529 | 530 | 532 | 533 | 534 | 535 | 536 | 537 | 539 | 540 | 541 | 542 | 543 | 544 | 545 | 548 | 549 | 550 |
Date PublishedFile NameDescriptionStatus
May 2, 2006application_5.xsdApplication schema 469 | Final Release
May 2, 2006application-client_5.xsdApplication Client schema 477 | Final Release
May 2, 2006ejb-jar_3_0.xsdEnterprise JavaBeans Deployment Descriptor 483 | SchemaFinal Release
May 2, 2006javaee_5.xsdJava EE 5 definitions file that 490 | contains common schema components 491 | Final Release
May 2, 2006javaee_web_services_1_2.xsdWeb services schema 499 | Final Release
May 2, 2006javaee_web_services_client_1_2.xsdWeb services client schema 507 | Final Release
May 2, 2006jsp_2_1.xsdJavaServer Pages Deployment Descriptor 513 | SchemaFinal Release
May 2, 2006web-app_2_5.xsdServlet Deployment Descriptor SchemaFinal Release
July 1, 2008web-facesconfig_1_2.xsdJavaServer Faces Application Configuration File schema 525 | Final Release
May 2, 2006web-jsptaglibrary_2_1.xsdJSP Taglibrary Deployment Descriptor SchemaFinal Release
November 21, 2007javaee_web_services_metadata_handler_2_0.xsdJava EE Web Services Metadata Handler Chain SchemaFinal Release
-http://www.w3.org/2001/xml.xsdThe Java EE schemas use some 546 | common definitions provided and published by W3C 547 | -
551 |

552 |
553 |
554 | 555 |
J2EE 1.4 XML Schemas
556 |
557 |

558 |

XML Schemas specified by the J2EE 1.4 specification are 559 | available at http://java.sun.com/xml/ns/j2ee/.

560 | 561 |
J2EE 1.3 DTDs
562 |
563 |

564 |

DTDs specified by the J2EE 1.3 specification are 565 | available at http://java.sun.com/dtd/.

566 | 567 |
J2EE 1.2 DTDs
568 |
569 |

570 |

DTDs specified by the J2EE 1.2 specification are 571 | available at http://java.sun.com/j2ee/dtds/.

572 | 573 | 574 | 575 | 576 | 577 | -------------------------------------------------------------------------------- /lab1 solution/nbproject/project.properties: -------------------------------------------------------------------------------- 1 | annotation.processing.enabled=true 2 | annotation.processing.enabled.in.editor=true 3 | annotation.processing.processors.list= 4 | annotation.processing.run.all.processors=true 5 | annotation.processing.source.output=${build.generated.sources.dir}/ap-source-output 6 | build.classes.dir=${build.web.dir}/WEB-INF/classes 7 | build.classes.excludes=**/*.java,**/*.form 8 | build.dir=build 9 | build.generated.dir=${build.dir}/generated 10 | build.generated.sources.dir=${build.dir}/generated-sources 11 | build.test.classes.dir=${build.dir}/test/classes 12 | build.test.results.dir=${build.dir}/test/results 13 | build.web.dir=${build.dir}/web 14 | build.web.excludes=${build.classes.excludes} 15 | client.urlPart= 16 | compile.jsps=false 17 | conf.dir=${source.root}/conf 18 | debug.classpath=${build.classes.dir}:${javac.classpath} 19 | debug.test.classpath=\ 20 | ${run.test.classpath} 21 | display.browser=true 22 | # Files to be excluded from distribution war 23 | dist.archive.excludes= 24 | dist.dir=dist 25 | dist.ear.war=${dist.dir}/${war.ear.name} 26 | dist.javadoc.dir=${dist.dir}/javadoc 27 | dist.war=${dist.dir}/${war.name} 28 | endorsed.classpath=\ 29 | ${libs.javaee-endorsed-api-6.0.classpath} 30 | excludes= 31 | includes=** 32 | j2ee.compile.on.save=true 33 | j2ee.copy.static.files.on.save=true 34 | j2ee.deploy.on.save=true 35 | j2ee.platform=1.7-web 36 | j2ee.platform.classpath=${j2ee.server.home}/modules/endorsed/javax.annotation-api.jar:${j2ee.server.home}/modules/endorsed/jaxb-api.jar:${j2ee.server.home}/modules/endorsed/webservices-api-osgi.jar:${j2ee.server.home}/modules/bean-validator.jar:${j2ee.server.home}/modules/javax.batch-api.jar:${j2ee.server.home}/modules/javax.ejb-api.jar:${j2ee.server.home}/modules/javax.el.jar:${j2ee.server.home}/modules/javax.enterprise.concurrent-api.jar:${j2ee.server.home}/modules/javax.enterprise.concurrent.jar:${j2ee.server.home}/modules/javax.enterprise.deploy-api.jar:${j2ee.server.home}/modules/javax.faces.jar:${j2ee.server.home}/modules/javax.inject.jar:${j2ee.server.home}/modules/javax.interceptor-api.jar:${j2ee.server.home}/modules/javax.jms-api.jar:${j2ee.server.home}/modules/javax.json.jar:${j2ee.server.home}/modules/javax.mail.jar:${j2ee.server.home}/modules/javax.management.j2ee-api.jar:${j2ee.server.home}/modules/javax.persistence.jar:${j2ee.server.home}/modules/javax.resource-api.jar:${j2ee.server.home}/modules/javax.security.auth.message-api.jar:${j2ee.server.home}/modules/javax.security.jacc-api.jar:${j2ee.server.home}/modules/javax.servlet-api.jar:${j2ee.server.home}/modules/javax.servlet.jsp-api.jar:${j2ee.server.home}/modules/javax.servlet.jsp.jar:${j2ee.server.home}/modules/javax.servlet.jsp.jstl-api.jar:${j2ee.server.home}/modules/javax.servlet.jsp.jstl.jar:${j2ee.server.home}/modules/javax.transaction-api.jar:${j2ee.server.home}/modules/javax.websocket-api.jar:${j2ee.server.home}/modules/javax.ws.rs-api.jar:${j2ee.server.home}/modules/javax.xml.registry-api.jar:${j2ee.server.home}/modules/javax.xml.rpc-api.jar:${j2ee.server.home}/modules/jaxb-osgi.jar:${j2ee.server.home}/modules/webservices-osgi.jar:${j2ee.server.home}/modules/weld-osgi-bundle.jar:${j2ee.server.middleware}/mq/lib/jaxm-api.jar 37 | j2ee.platform.embeddableejb.classpath=${j2ee.server.home}/lib/embedded/glassfish-embedded-static-shell.jar 38 | j2ee.platform.wscompile.classpath=${j2ee.server.home}/modules/webservices-osgi.jar 39 | j2ee.platform.wsgen.classpath=${j2ee.server.home}/modules/webservices-osgi.jar:${j2ee.server.home}/modules/endorsed/webservices-api-osgi.jar:${j2ee.server.home}/modules/jaxb-osgi.jar:${j2ee.server.home}/modules/endorsed/jaxb-api.jar 40 | j2ee.platform.wsimport.classpath=${j2ee.server.home}/modules/webservices-osgi.jar:${j2ee.server.home}/modules/endorsed/webservices-api-osgi.jar:${j2ee.server.home}/modules/jaxb-osgi.jar:${j2ee.server.home}/modules/endorsed/jaxb-api.jar 41 | j2ee.platform.wsit.classpath= 42 | j2ee.server.type=gfv3ee6 43 | jar.compress=false 44 | javac.classpath= 45 | # Space-separated list of extra javac options 46 | javac.compilerargs= 47 | javac.debug=true 48 | javac.deprecation=false 49 | javac.processorpath=\ 50 | ${javac.classpath} 51 | javac.source=1.7 52 | javac.target=1.7 53 | javac.test.classpath=\ 54 | ${javac.classpath}:\ 55 | ${build.classes.dir} 56 | javac.test.processorpath=\ 57 | ${javac.test.classpath} 58 | javadoc.additionalparam= 59 | javadoc.author=false 60 | javadoc.encoding=${source.encoding} 61 | javadoc.noindex=false 62 | javadoc.nonavbar=false 63 | javadoc.notree=false 64 | javadoc.preview=true 65 | javadoc.private=false 66 | javadoc.splitindex=true 67 | javadoc.use=true 68 | javadoc.version=false 69 | javadoc.windowtitle= 70 | lib.dir=${web.docbase.dir}/WEB-INF/lib 71 | persistence.xml.dir=${conf.dir} 72 | platform.active=default_platform 73 | resource.dir=setup 74 | run.test.classpath=\ 75 | ${javac.test.classpath}:\ 76 | ${build.test.classes.dir} 77 | # Space-separated list of JVM arguments used when running a class with a main method or a unit test 78 | # (you may also define separate properties like run-sys-prop.name=value instead of -Dname=value): 79 | runmain.jvmargs= 80 | source.encoding=UTF-8 81 | source.root=src 82 | src.dir=${source.root}/java 83 | test.src.dir=test 84 | war.content.additional= 85 | war.ear.name=${war.name} 86 | war.name=lab1_solution.war 87 | web.docbase.dir=web 88 | webinf.dir=web/WEB-INF 89 | -------------------------------------------------------------------------------- /lab1 solution/nbproject/project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | org.netbeans.modules.web.project 4 | 5 | 6 | lab1 solution 7 | 1.6.5 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /lab1 solution/src/conf/MANIFEST.MF: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | 3 | -------------------------------------------------------------------------------- /lab1 solution/src/java/org/glassfish/javaee7/batch/lab1/BatchJobSubmitter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 3 | * 4 | * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. 5 | * 6 | * The contents of this file are subject to the terms of either the GNU 7 | * General Public License Version 2 only ("GPL") or the Common Development 8 | * and Distribution License("CDDL") (collectively, the "License"). You 9 | * may not use this file except in compliance with the License. You can 10 | * obtain a copy of the License at 11 | * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html 12 | * or packager/legal/LICENSE.txt. See the License for the specific 13 | * language governing permissions and limitations under the License. 14 | * 15 | * When distributing the software, include this License Header Notice in each 16 | * file and include the License file at packager/legal/LICENSE.txt. 17 | * 18 | * GPL Classpath Exception: 19 | * Oracle designates this particular file as subject to the "Classpath" 20 | * exception as provided by Oracle in the GPL Version 2 section of the License 21 | * file that accompanied this code. 22 | * 23 | * Modifications: 24 | * If applicable, add the following below the License Header, with the fields 25 | * enclosed by brackets [] replaced by your own identifying information: 26 | * "Portions Copyright [year] [name of copyright owner]" 27 | * 28 | * Contributor(s): 29 | * If you wish your version of this file to be governed by only the CDDL or 30 | * only the GPL Version 2, indicate your decision by adding "[Contributor] 31 | * elects to include this software in this distribution under the [CDDL or GPL 32 | * Version 2] license." If you don't indicate a single choice of license, a 33 | * recipient has the option to distribute your version of this file under 34 | * either the CDDL, the GPL Version 2 or to extend the choice of license to 35 | * its licensees as provided above. However, if you add GPL Version 2 code 36 | * and therefore, elected the GPL Version 2 license, then the option applies 37 | * only if the new code is made subject to such option by the copyright 38 | * holder. 39 | */ 40 | package org.glassfish.javaee7.batch.lab1; 41 | 42 | import java.io.IOException; 43 | import java.io.PrintWriter; 44 | import java.util.Properties; 45 | import javax.batch.operations.JobOperator; 46 | import javax.batch.runtime.BatchRuntime; 47 | import javax.batch.runtime.JobExecution; 48 | import javax.batch.runtime.JobInstance; 49 | import javax.ejb.EJB; 50 | import javax.servlet.ServletException; 51 | import javax.servlet.annotation.WebServlet; 52 | import javax.servlet.http.HttpServlet; 53 | import javax.servlet.http.HttpServletRequest; 54 | import javax.servlet.http.HttpServletResponse; 55 | 56 | /** 57 | * 58 | * @author makannan 59 | */ 60 | @WebServlet(urlPatterns = {"/BatchJobSubmitter"}) 61 | public class BatchJobSubmitter extends HttpServlet { 62 | 63 | @EJB 64 | PayrollDataHolderBean payrollDataHolderBean; 65 | 66 | /** 67 | * Processes requests for both HTTP GET and POST 68 | * methods. 69 | * 70 | * @param request servlet request 71 | * @param response servlet response 72 | * @throws ServletException if a servlet-specific error occurs 73 | * @throws IOException if an I/O error occurs 74 | */ 75 | protected void processRequest(HttpServletRequest request, HttpServletResponse response) 76 | throws ServletException, IOException { 77 | response.setContentType("text/html;charset=UTF-8"); 78 | try (PrintWriter pw = response.getWriter()) { 79 | /* TODO output your page here. You may use following sample code. */ 80 | pw.println(""); 81 | pw.println(""); 82 | pw.println(""); 83 | pw.println("TEST Servlet BatchJobSubmitter"); 84 | pw.println(""); 85 | pw.println(""); 86 | 87 | long executionId = -1; 88 | if (request.getParameter("executionId") != null) { 89 | executionId = Long.valueOf(request.getParameter("executionId")); 90 | } 91 | 92 | try { 93 | if (request.getParameter("calculatePayroll") != null) { 94 | executionId = submitJobFromXML("PayrollJob"); 95 | } 96 | pw.println(""); 97 | pw.println(""); 102 | pw.println("
"); 98 | displayPayrollForm(pw); 99 | pw.println(""); 100 | displayProcessedPayrollRecords(pw, executionId); 101 | pw.println("
"); 103 | 104 | displayJobDetails(pw, executionId); 105 | } catch (Exception ex) { 106 | throw new ServletException(ex); 107 | } 108 | 109 | pw.println(""); 110 | pw.println(""); 111 | } 112 | } 113 | 114 | private void displayProcessedPayrollRecords(PrintWriter pw, long executionId) 115 | throws Exception { 116 | 117 | pw.println("
"); 118 | pw.println("Processed Payroll Records"); 119 | pw.println("" 120 | + ""); 121 | for (PayrollOutputRecord record : payrollDataHolderBean.getPayrollOutputRecords()) { 122 | pw.println("" 123 | + "" 124 | + "" 125 | + ""); 126 | } 127 | pw.println(""); 128 | pw.println(""); 129 | pw.println(""); 130 | pw.println("
Employee IDSalarySocial SecurityNet
" + record.getEmpId()+ "" + record.getSalary() + "" + record.getSocialSecurityTax()+ "" + record.getNet()+ "
"); 131 | pw.println("
"); 132 | } 133 | private void displayPayrollForm(PrintWriter pw) 134 | throws Exception { 135 | 136 | pw.println(""); 137 | for (String line : payrollDataHolderBean.getPayrollInputData()) { 138 | pw.println(""); 139 | } 140 | pw.println("
Payroll Input Records (Comma Separated Values)
" + line + "
"); 141 | } 142 | 143 | private long submitJobFromXML(String jobName) 144 | throws Exception { 145 | JobOperator jobOperator = BatchRuntime.getJobOperator(); 146 | 147 | Properties props = new Properties(); 148 | return jobOperator.start(jobName, props); 149 | } 150 | 151 | private void displayJobDetails(PrintWriter pw, long executionId) { 152 | pw.println(""); 153 | pw.println(""); 154 | pw.println("
Status of Submitted Jobs
"); 155 | pw.println("" 156 | + "" 157 | + "" 158 | + ""); 159 | 160 | 161 | JobOperator jobOperator = BatchRuntime.getJobOperator(); 162 | try { 163 | for (JobInstance jobInstance : jobOperator.getJobInstances("PayrollJob", 0, Integer.MAX_VALUE-1)) { 164 | for (JobExecution jobExecution : jobOperator.getJobExecutions(jobInstance)) { 165 | StringBuilder sb = new StringBuilder(); 166 | if (executionId == jobExecution.getExecutionId()) { 167 | sb.append(""); 168 | } else { 169 | sb.append(""); 170 | } 171 | sb.append(""); 172 | sb.append(""); 173 | sb.append(""); 174 | sb.append(""); 175 | sb.append(""); 176 | sb.append(""); 177 | sb.append(""); 178 | pw.println(sb.toString()); 179 | } 180 | } 181 | } catch (Exception ex) { 182 | pw.println(ex.toString()); 183 | } 184 | pw.println("
Job NameInstance IdExecutionIDBatch StatusExit StatusStart Time StatusEnd Time
").append(jobExecution.getJobName()).append("").append(jobInstance.getInstanceId()).append("").append(jobExecution.getExecutionId()).append("").append(jobExecution.getBatchStatus()).append("").append(jobExecution.getExitStatus()).append("").append(jobExecution.getStartTime()).append("").append(jobExecution.getEndTime()).append("
"); 185 | pw.println(""); 186 | } 187 | 188 | // 189 | /** 190 | * Handles the HTTP GET method. 191 | * 192 | * @param request servlet request 193 | * @param response servlet response 194 | * @throws ServletException if a servlet-specific error occurs 195 | * @throws IOException if an I/O error occurs 196 | */ 197 | @Override 198 | protected void doGet(HttpServletRequest request, HttpServletResponse response) 199 | throws ServletException, IOException { 200 | processRequest(request, response); 201 | } 202 | 203 | /** 204 | * Handles the HTTP POST method. 205 | * 206 | * @param request servlet request 207 | * @param response servlet response 208 | * @throws ServletException if a servlet-specific error occurs 209 | * @throws IOException if an I/O error occurs 210 | */ 211 | @Override 212 | protected void doPost(HttpServletRequest request, HttpServletResponse response) 213 | throws ServletException, IOException { 214 | processRequest(request, response); 215 | } 216 | 217 | /** 218 | * Returns a short description of the servlet. 219 | * 220 | * @return a String containing servlet description 221 | */ 222 | @Override 223 | public String getServletInfo() { 224 | return "Short description"; 225 | }// 226 | 227 | } 228 | -------------------------------------------------------------------------------- /lab1 solution/src/java/org/glassfish/javaee7/batch/lab1/NetPayProcessor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 3 | * 4 | * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. 5 | * 6 | * The contents of this file are subject to the terms of either the GNU 7 | * General Public License Version 2 only ("GPL") or the Common Development 8 | * and Distribution License("CDDL") (collectively, the "License"). You 9 | * may not use this file except in compliance with the License. You can 10 | * obtain a copy of the License at 11 | * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html 12 | * or packager/legal/LICENSE.txt. See the License for the specific 13 | * language governing permissions and limitations under the License. 14 | * 15 | * When distributing the software, include this License Header Notice in each 16 | * file and include the License file at packager/legal/LICENSE.txt. 17 | * 18 | * GPL Classpath Exception: 19 | * Oracle designates this particular file as subject to the "Classpath" 20 | * exception as provided by Oracle in the GPL Version 2 section of the License 21 | * file that accompanied this code. 22 | * 23 | * Modifications: 24 | * If applicable, add the following below the License Header, with the fields 25 | * enclosed by brackets [] replaced by your own identifying information: 26 | * "Portions Copyright [year] [name of copyright owner]" 27 | * 28 | * Contributor(s): 29 | * If you wish your version of this file to be governed by only the CDDL or 30 | * only the GPL Version 2, indicate your decision by adding "[Contributor] 31 | * elects to include this software in this distribution under the [CDDL or GPL 32 | * Version 2] license." If you don't indicate a single choice of license, a 33 | * recipient has the option to distribute your version of this file under 34 | * either the CDDL, the GPL Version 2 or to extend the choice of license to 35 | * its licensees as provided above. However, if you add GPL Version 2 code 36 | * and therefore, elected the GPL Version 2 license, then the option applies 37 | * only if the new code is made subject to such option by the copyright 38 | * holder. 39 | */ 40 | package org.glassfish.javaee7.batch.lab1; 41 | 42 | import javax.batch.api.chunk.ItemProcessor; 43 | import javax.batch.runtime.context.JobContext; 44 | import javax.inject.Inject; 45 | import javax.inject.Named; 46 | 47 | @Named 48 | public class NetPayProcessor 49 | implements ItemProcessor { 50 | 51 | @Inject 52 | private JobContext jobContext; 53 | 54 | 55 | public Object processItem(Object obj) throws Exception { 56 | PayrollInputRecord inputRecord = (PayrollInputRecord) obj; 57 | float salary = Integer.valueOf(inputRecord.getSalary()); 58 | float socialSecurityTax = 59 | salary > 117000 ? 117000 * 6.2f / 100 : salary * 6.2f / 100; 60 | 61 | PayrollOutputRecord outputRecord = new PayrollOutputRecord(inputRecord.getId()); 62 | outputRecord.setSalary(salary / 24.0f); 63 | outputRecord.setSocialSecurityTax(socialSecurityTax / 24.0f); 64 | outputRecord.setNet(outputRecord.getSalary() - outputRecord.getSocialSecurityTax()); 65 | 66 | return outputRecord; 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /lab1 solution/src/java/org/glassfish/javaee7/batch/lab1/PayrollDataHolderBean.java: -------------------------------------------------------------------------------- 1 | /* 2 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 3 | * 4 | * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. 5 | * 6 | * The contents of this file are subject to the terms of either the GNU 7 | * General Public License Version 2 only ("GPL") or the Common Development 8 | * and Distribution License("CDDL") (collectively, the "License"). You 9 | * may not use this file except in compliance with the License. You can 10 | * obtain a copy of the License at 11 | * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html 12 | * or packager/legal/LICENSE.txt. See the License for the specific 13 | * language governing permissions and limitations under the License. 14 | * 15 | * When distributing the software, include this License Header Notice in each 16 | * file and include the License file at packager/legal/LICENSE.txt. 17 | * 18 | * GPL Classpath Exception: 19 | * Oracle designates this particular file as subject to the "Classpath" 20 | * exception as provided by Oracle in the GPL Version 2 section of the License 21 | * file that accompanied this code. 22 | * 23 | * Modifications: 24 | * If applicable, add the following below the License Header, with the fields 25 | * enclosed by brackets [] replaced by your own identifying information: 26 | * "Portions Copyright [year] [name of copyright owner]" 27 | * 28 | * Contributor(s): 29 | * If you wish your version of this file to be governed by only the CDDL or 30 | * only the GPL Version 2, indicate your decision by adding "[Contributor] 31 | * elects to include this software in this distribution under the [CDDL or GPL 32 | * Version 2] license." If you don't indicate a single choice of license, a 33 | * recipient has the option to distribute your version of this file under 34 | * either the CDDL, the GPL Version 2 or to extend the choice of license to 35 | * its licensees as provided above. However, if you add GPL Version 2 code 36 | * and therefore, elected the GPL Version 2 license, then the option applies 37 | * only if the new code is made subject to such option by the copyright 38 | * holder. 39 | */ 40 | package org.glassfish.javaee7.batch.lab1; 41 | 42 | import java.util.ArrayList; 43 | import java.util.Collections; 44 | import java.util.HashSet; 45 | import java.util.List; 46 | import java.util.Set; 47 | import javax.annotation.PostConstruct; 48 | import javax.ejb.Singleton; 49 | import javax.ejb.Startup; 50 | 51 | /** 52 | * Note: In a typical payroll processing system, the payroll records would come 53 | * from a database, But for simplicity we are using this singleton bean to 54 | * cache the payroll records. 55 | */ 56 | @Singleton 57 | @Startup 58 | public class PayrollDataHolderBean { 59 | 60 | private List payrollInputRecords 61 | = new ArrayList<>(); 62 | 63 | private Set payrollOutputRecords 64 | = new HashSet<>(); 65 | 66 | public PayrollDataHolderBean() { 67 | 68 | } 69 | 70 | @PostConstruct 71 | public void onApplicationStartup() { 72 | for (int empID=1; empID<6; empID++) { 73 | payrollInputRecords.add("" + empID + ", " + (80000 + empID*10000)); 74 | } 75 | } 76 | 77 | public List getPayrollInputData() { 78 | return Collections.unmodifiableList(payrollInputRecords); 79 | } 80 | 81 | public void addPayrollOutputRecord(PayrollOutputRecord data) { 82 | payrollOutputRecords.add(data); 83 | } 84 | 85 | public Set getPayrollOutputRecords() { 86 | return payrollOutputRecords; 87 | } 88 | 89 | } 90 | -------------------------------------------------------------------------------- /lab1 solution/src/java/org/glassfish/javaee7/batch/lab1/PayrollInputRecord.java: -------------------------------------------------------------------------------- 1 | /* 2 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 3 | * 4 | * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. 5 | * 6 | * The contents of this file are subject to the terms of either the GNU 7 | * General Public License Version 2 only ("GPL") or the Common Development 8 | * and Distribution License("CDDL") (collectively, the "License"). You 9 | * may not use this file except in compliance with the License. You can 10 | * obtain a copy of the License at 11 | * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html 12 | * or packager/legal/LICENSE.txt. See the License for the specific 13 | * language governing permissions and limitations under the License. 14 | * 15 | * When distributing the software, include this License Header Notice in each 16 | * file and include the License file at packager/legal/LICENSE.txt. 17 | * 18 | * GPL Classpath Exception: 19 | * Oracle designates this particular file as subject to the "Classpath" 20 | * exception as provided by Oracle in the GPL Version 2 section of the License 21 | * file that accompanied this code. 22 | * 23 | * Modifications: 24 | * If applicable, add the following below the License Header, with the fields 25 | * enclosed by brackets [] replaced by your own identifying information: 26 | * "Portions Copyright [year] [name of copyright owner]" 27 | * 28 | * Contributor(s): 29 | * If you wish your version of this file to be governed by only the CDDL or 30 | * only the GPL Version 2, indicate your decision by adding "[Contributor] 31 | * elects to include this software in this distribution under the [CDDL or GPL 32 | * Version 2] license." If you don't indicate a single choice of license, a 33 | * recipient has the option to distribute your version of this file under 34 | * either the CDDL, the GPL Version 2 or to extend the choice of license to 35 | * its licensees as provided above. However, if you add GPL Version 2 code 36 | * and therefore, elected the GPL Version 2 license, then the option applies 37 | * only if the new code is made subject to such option by the copyright 38 | * holder. 39 | */ 40 | package org.glassfish.javaee7.batch.lab1; 41 | 42 | /** 43 | * A class that serves as input record for a simple payroll 44 | * processing system 45 | */ 46 | public class PayrollInputRecord { 47 | 48 | private final int id; 49 | 50 | private String salary; 51 | 52 | public PayrollInputRecord(int id) { 53 | this.id = id; 54 | } 55 | 56 | public int getId() { 57 | return id; 58 | } 59 | 60 | public String getSalary() { 61 | return salary; 62 | } 63 | 64 | public void setSalary(String salary) { 65 | this.salary = salary; 66 | } 67 | 68 | @Override 69 | public int hashCode() { 70 | return id; 71 | } 72 | 73 | @Override 74 | public boolean equals(Object object) { 75 | if (object == null || !(object instanceof PayrollInputRecord)) { 76 | return false; 77 | } 78 | PayrollInputRecord other = (PayrollInputRecord) object; 79 | return this.id == other.id; 80 | } 81 | 82 | @Override 83 | public String toString() { 84 | return "PayrollInputRecord[ id=" + id + " ]"; 85 | } 86 | 87 | } 88 | -------------------------------------------------------------------------------- /lab1 solution/src/java/org/glassfish/javaee7/batch/lab1/PayrollInputRecordReader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 3 | * 4 | * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. 5 | * 6 | * The contents of this file are subject to the terms of either the GNU 7 | * General Public License Version 2 only ("GPL") or the Common Development 8 | * and Distribution License("CDDL") (collectively, the "License"). You 9 | * may not use this file except in compliance with the License. You can 10 | * obtain a copy of the License at 11 | * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html 12 | * or packager/legal/LICENSE.txt. See the License for the specific 13 | * language governing permissions and limitations under the License. 14 | * 15 | * When distributing the software, include this License Header Notice in each 16 | * file and include the License file at packager/legal/LICENSE.txt. 17 | * 18 | * GPL Classpath Exception: 19 | * Oracle designates this particular file as subject to the "Classpath" 20 | * exception as provided by Oracle in the GPL Version 2 section of the License 21 | * file that accompanied this code. 22 | * 23 | * Modifications: 24 | * If applicable, add the following below the License Header, with the fields 25 | * enclosed by brackets [] replaced by your own identifying information: 26 | * "Portions Copyright [year] [name of copyright owner]" 27 | * 28 | * Contributor(s): 29 | * If you wish your version of this file to be governed by only the CDDL or 30 | * only the GPL Version 2, indicate your decision by adding "[Contributor] 31 | * elects to include this software in this distribution under the [CDDL or GPL 32 | * Version 2] license." If you don't indicate a single choice of license, a 33 | * recipient has the option to distribute your version of this file under 34 | * either the CDDL, the GPL Version 2 or to extend the choice of license to 35 | * its licensees as provided above. However, if you add GPL Version 2 code 36 | * and therefore, elected the GPL Version 2 license, then the option applies 37 | * only if the new code is made subject to such option by the copyright 38 | * holder. 39 | */ 40 | package org.glassfish.javaee7.batch.lab1; 41 | 42 | import java.io.Serializable; 43 | import java.util.Iterator; 44 | import java.util.StringTokenizer; 45 | import javax.batch.api.chunk.AbstractItemReader; 46 | import javax.ejb.EJB; 47 | import javax.inject.Named; 48 | 49 | /** 50 | * Reads PayrollInputRecords. In a typical payroll processing system, the data 51 | * would come come from a database, but for this lab this ItemReader will 52 | * simply retrieve data records from the EJB Singleton bean. 53 | * 54 | * This also demonstrates that an ItemReader can read data from any source. 55 | * 56 | */ 57 | @Named 58 | public class PayrollInputRecordReader 59 | extends AbstractItemReader { 60 | 61 | @EJB 62 | PayrollDataHolderBean payrollDataHolderBean; 63 | 64 | Iterator payrollInputRecordsIterator; 65 | 66 | public void open(Serializable e) throws Exception { 67 | payrollInputRecordsIterator = payrollDataHolderBean.getPayrollInputData().iterator(); 68 | } 69 | 70 | public Object readItem() throws Exception { 71 | String line = payrollInputRecordsIterator.hasNext() ? payrollInputRecordsIterator.next() : null; 72 | PayrollInputRecord record = null; 73 | if (line != null) { 74 | StringTokenizer tokenizer = new StringTokenizer(line, ", "); 75 | String empId = tokenizer.nextToken(); 76 | String salary = tokenizer.nextToken(); 77 | if (tokenizer.hasMoreTokens()) 78 | throw new IllegalArgumentException("Extra characters in input data: " + line); 79 | record = new PayrollInputRecord(Integer.valueOf(empId)); 80 | record.setSalary(salary); 81 | } 82 | 83 | return record; 84 | } 85 | 86 | } 87 | -------------------------------------------------------------------------------- /lab1 solution/src/java/org/glassfish/javaee7/batch/lab1/PayrollOutputRecord.java: -------------------------------------------------------------------------------- 1 | /* 2 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 3 | * 4 | * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. 5 | * 6 | * The contents of this file are subject to the terms of either the GNU 7 | * General Public License Version 2 only ("GPL") or the Common Development 8 | * and Distribution License("CDDL") (collectively, the "License"). You 9 | * may not use this file except in compliance with the License. You can 10 | * obtain a copy of the License at 11 | * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html 12 | * or packager/legal/LICENSE.txt. See the License for the specific 13 | * language governing permissions and limitations under the License. 14 | * 15 | * When distributing the software, include this License Header Notice in each 16 | * file and include the License file at packager/legal/LICENSE.txt. 17 | * 18 | * GPL Classpath Exception: 19 | * Oracle designates this particular file as subject to the "Classpath" 20 | * exception as provided by Oracle in the GPL Version 2 section of the License 21 | * file that accompanied this code. 22 | * 23 | * Modifications: 24 | * If applicable, add the following below the License Header, with the fields 25 | * enclosed by brackets [] replaced by your own identifying information: 26 | * "Portions Copyright [year] [name of copyright owner]" 27 | * 28 | * Contributor(s): 29 | * If you wish your version of this file to be governed by only the CDDL or 30 | * only the GPL Version 2, indicate your decision by adding "[Contributor] 31 | * elects to include this software in this distribution under the [CDDL or GPL 32 | * Version 2] license." If you don't indicate a single choice of license, a 33 | * recipient has the option to distribute your version of this file under 34 | * either the CDDL, the GPL Version 2 or to extend the choice of license to 35 | * its licensees as provided above. However, if you add GPL Version 2 code 36 | * and therefore, elected the GPL Version 2 license, then the option applies 37 | * only if the new code is made subject to such option by the copyright 38 | * holder. 39 | */ 40 | package org.glassfish.javaee7.batch.lab1; 41 | 42 | public class PayrollOutputRecord { 43 | private final int empId; 44 | 45 | private float salary; 46 | 47 | private float socialSecurityTax; 48 | 49 | private float bonus = 0; 50 | 51 | private float net; 52 | 53 | public PayrollOutputRecord(int empID) { 54 | this.empId = empID; 55 | } 56 | 57 | public int getEmpId() { 58 | return empId; 59 | } 60 | 61 | public float getSalary() { 62 | return salary; 63 | } 64 | 65 | public void setSalary(float base) { 66 | this.salary = base; 67 | } 68 | 69 | public float getSocialSecurityTax() { 70 | return socialSecurityTax; 71 | } 72 | 73 | public void setSocialSecurityTax(float socialSecurityTax) { 74 | this.socialSecurityTax = socialSecurityTax; 75 | } 76 | 77 | public float getBonus() { 78 | return bonus; 79 | } 80 | 81 | public void setBonus(float bonus) { 82 | this.bonus = bonus; 83 | } 84 | 85 | public float getNet() { 86 | return net; 87 | } 88 | 89 | public void setNet(float net) { 90 | this.net = net; 91 | } 92 | 93 | @Override 94 | public int hashCode() { 95 | return getEmpId(); 96 | } 97 | 98 | @Override 99 | public boolean equals(Object object) { 100 | // TODO: Warning - this method won't work in the case the id fields are not set 101 | if (object == null || !(object instanceof PayrollOutputRecord)) { 102 | return false; 103 | } 104 | PayrollOutputRecord other = (PayrollOutputRecord) object; 105 | return getEmpId() == other.getEmpId(); 106 | } 107 | 108 | @Override 109 | public String toString() { 110 | return "PayrollOutputRecord[ id= [" + getEmpId() + "]"; 111 | } 112 | 113 | } 114 | -------------------------------------------------------------------------------- /lab1 solution/src/java/org/glassfish/javaee7/batch/lab1/PayrollOutputRecordWriter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 3 | * 4 | * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. 5 | * 6 | * The contents of this file are subject to the terms of either the GNU 7 | * General Public License Version 2 only ("GPL") or the Common Development 8 | * and Distribution License("CDDL") (collectively, the "License"). You 9 | * may not use this file except in compliance with the License. You can 10 | * obtain a copy of the License at 11 | * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html 12 | * or packager/legal/LICENSE.txt. See the License for the specific 13 | * language governing permissions and limitations under the License. 14 | * 15 | * When distributing the software, include this License Header Notice in each 16 | * file and include the License file at packager/legal/LICENSE.txt. 17 | * 18 | * GPL Classpath Exception: 19 | * Oracle designates this particular file as subject to the "Classpath" 20 | * exception as provided by Oracle in the GPL Version 2 section of the License 21 | * file that accompanied this code. 22 | * 23 | * Modifications: 24 | * If applicable, add the following below the License Header, with the fields 25 | * enclosed by brackets [] replaced by your own identifying information: 26 | * "Portions Copyright [year] [name of copyright owner]" 27 | * 28 | * Contributor(s): 29 | * If you wish your version of this file to be governed by only the CDDL or 30 | * only the GPL Version 2, indicate your decision by adding "[Contributor] 31 | * elects to include this software in this distribution under the [CDDL or GPL 32 | * Version 2] license." If you don't indicate a single choice of license, a 33 | * recipient has the option to distribute your version of this file under 34 | * either the CDDL, the GPL Version 2 or to extend the choice of license to 35 | * its licensees as provided above. However, if you add GPL Version 2 code 36 | * and therefore, elected the GPL Version 2 license, then the option applies 37 | * only if the new code is made subject to such option by the copyright 38 | * holder. 39 | */ 40 | package org.glassfish.javaee7.batch.lab1; 41 | 42 | import java.io.Serializable; 43 | import java.util.List; 44 | import javax.batch.api.chunk.AbstractItemWriter; 45 | import javax.ejb.EJB; 46 | import javax.inject.Named; 47 | 48 | @Named 49 | public class PayrollOutputRecordWriter 50 | extends AbstractItemWriter { 51 | 52 | @EJB 53 | private PayrollDataHolderBean bean; 54 | 55 | @Override 56 | public void open(Serializable checkpoint) throws Exception { 57 | 58 | } 59 | 60 | public void writeItems(List list) throws Exception { 61 | for (Object obj : list) { 62 | bean.addPayrollOutputRecord((PayrollOutputRecord) obj); 63 | } 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /lab1 solution/web/WEB-INF/beans.xml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javaee/batchlab/ed95ed5c245fefab8cb721ab8f256350bf414270/lab1 solution/web/WEB-INF/beans.xml -------------------------------------------------------------------------------- /lab1 solution/web/WEB-INF/classes/META-INF/batch-jobs/PayrollJob.xml: -------------------------------------------------------------------------------- 1 | 2 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /lab1 solution/web/WEB-INF/glassfish-web.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | /dd_lab1 5 | 6 | 7 | 8 | Keep a copy of the generated servlet class' java code. 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /lab1 solution/web/index.html: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | Lab 1 10 | 11 | 12 | 13 | 14 |
Lab 1
15 | 16 | 17 | -------------------------------------------------------------------------------- /lab1-solution.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javaee/batchlab/ed95ed5c245fefab8cb721ab8f256350bf414270/lab1-solution.zip -------------------------------------------------------------------------------- /lab2-solution.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javaee/batchlab/ed95ed5c245fefab8cb721ab8f256350bf414270/lab2-solution.zip -------------------------------------------------------------------------------- /lab2.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javaee/batchlab/ed95ed5c245fefab8cb721ab8f256350bf414270/lab2.zip -------------------------------------------------------------------------------- /lab3-solution.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javaee/batchlab/ed95ed5c245fefab8cb721ab8f256350bf414270/lab3-solution.zip -------------------------------------------------------------------------------- /lab3.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javaee/batchlab/ed95ed5c245fefab8cb721ab8f256350bf414270/lab3.zip -------------------------------------------------------------------------------- /lab4-solution.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javaee/batchlab/ed95ed5c245fefab8cb721ab8f256350bf414270/lab4-solution.zip -------------------------------------------------------------------------------- /lab4.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javaee/batchlab/ed95ed5c245fefab8cb721ab8f256350bf414270/lab4.zip -------------------------------------------------------------------------------- /lab5-solution.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javaee/batchlab/ed95ed5c245fefab8cb721ab8f256350bf414270/lab5-solution.zip -------------------------------------------------------------------------------- /lab5.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javaee/batchlab/ed95ed5c245fefab8cb721ab8f256350bf414270/lab5.zip -------------------------------------------------------------------------------- /masterLab.adoc: -------------------------------------------------------------------------------- 1 | = Introduction to the Batch API (JSR 352) 2 | David Delabassee 3 | v1.0, Aug 27, 2014 4 | :doctype: book 5 | :toc: 6 | :toc-placement: preamble 7 | :toclevels: 2 8 | :icons: font 9 | 10 | image::cover.jpg[] 11 | 12 | :numbered!: 13 | include::chapters/introduction.adoc[] 14 | :numbered: 15 | include::chapters/exercice1.adoc[] 16 | include::chapters/exercice2.adoc[] 17 | include::chapters/exercice3.adoc[] 18 | include::chapters/exercice4.adoc[] 19 | include::chapters/exercice5.adoc[] 20 | -------------------------------------------------------------------------------- /pic/E1.1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javaee/batchlab/ed95ed5c245fefab8cb721ab8f256350bf414270/pic/E1.1.jpg -------------------------------------------------------------------------------- /pic/E1.1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javaee/batchlab/ed95ed5c245fefab8cb721ab8f256350bf414270/pic/E1.1.png -------------------------------------------------------------------------------- /pic/E1.10.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javaee/batchlab/ed95ed5c245fefab8cb721ab8f256350bf414270/pic/E1.10.jpg -------------------------------------------------------------------------------- /pic/E1.10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javaee/batchlab/ed95ed5c245fefab8cb721ab8f256350bf414270/pic/E1.10.png -------------------------------------------------------------------------------- /pic/E1.11.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javaee/batchlab/ed95ed5c245fefab8cb721ab8f256350bf414270/pic/E1.11.jpg -------------------------------------------------------------------------------- /pic/E1.11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javaee/batchlab/ed95ed5c245fefab8cb721ab8f256350bf414270/pic/E1.11.png -------------------------------------------------------------------------------- /pic/E1.12.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javaee/batchlab/ed95ed5c245fefab8cb721ab8f256350bf414270/pic/E1.12.jpg -------------------------------------------------------------------------------- /pic/E1.12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javaee/batchlab/ed95ed5c245fefab8cb721ab8f256350bf414270/pic/E1.12.png -------------------------------------------------------------------------------- /pic/E1.14.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javaee/batchlab/ed95ed5c245fefab8cb721ab8f256350bf414270/pic/E1.14.jpg -------------------------------------------------------------------------------- /pic/E1.14.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javaee/batchlab/ed95ed5c245fefab8cb721ab8f256350bf414270/pic/E1.14.png -------------------------------------------------------------------------------- /pic/E1.15.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javaee/batchlab/ed95ed5c245fefab8cb721ab8f256350bf414270/pic/E1.15.jpg -------------------------------------------------------------------------------- /pic/E1.15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javaee/batchlab/ed95ed5c245fefab8cb721ab8f256350bf414270/pic/E1.15.png -------------------------------------------------------------------------------- /pic/E1.16.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javaee/batchlab/ed95ed5c245fefab8cb721ab8f256350bf414270/pic/E1.16.jpg -------------------------------------------------------------------------------- /pic/E1.16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javaee/batchlab/ed95ed5c245fefab8cb721ab8f256350bf414270/pic/E1.16.png -------------------------------------------------------------------------------- /pic/E1.17.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javaee/batchlab/ed95ed5c245fefab8cb721ab8f256350bf414270/pic/E1.17.jpg -------------------------------------------------------------------------------- /pic/E1.17.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javaee/batchlab/ed95ed5c245fefab8cb721ab8f256350bf414270/pic/E1.17.png -------------------------------------------------------------------------------- /pic/E1.2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javaee/batchlab/ed95ed5c245fefab8cb721ab8f256350bf414270/pic/E1.2.jpg -------------------------------------------------------------------------------- /pic/E1.2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javaee/batchlab/ed95ed5c245fefab8cb721ab8f256350bf414270/pic/E1.2.png -------------------------------------------------------------------------------- /pic/E1.3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javaee/batchlab/ed95ed5c245fefab8cb721ab8f256350bf414270/pic/E1.3.jpg -------------------------------------------------------------------------------- /pic/E1.3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javaee/batchlab/ed95ed5c245fefab8cb721ab8f256350bf414270/pic/E1.3.png -------------------------------------------------------------------------------- /pic/E1.4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javaee/batchlab/ed95ed5c245fefab8cb721ab8f256350bf414270/pic/E1.4.jpg -------------------------------------------------------------------------------- /pic/E1.4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javaee/batchlab/ed95ed5c245fefab8cb721ab8f256350bf414270/pic/E1.4.png -------------------------------------------------------------------------------- /pic/E1.5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javaee/batchlab/ed95ed5c245fefab8cb721ab8f256350bf414270/pic/E1.5.jpg -------------------------------------------------------------------------------- /pic/E1.5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javaee/batchlab/ed95ed5c245fefab8cb721ab8f256350bf414270/pic/E1.5.png -------------------------------------------------------------------------------- /pic/E1.6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javaee/batchlab/ed95ed5c245fefab8cb721ab8f256350bf414270/pic/E1.6.jpg -------------------------------------------------------------------------------- /pic/E1.6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javaee/batchlab/ed95ed5c245fefab8cb721ab8f256350bf414270/pic/E1.6.png -------------------------------------------------------------------------------- /pic/E1.7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javaee/batchlab/ed95ed5c245fefab8cb721ab8f256350bf414270/pic/E1.7.jpg -------------------------------------------------------------------------------- /pic/E1.7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javaee/batchlab/ed95ed5c245fefab8cb721ab8f256350bf414270/pic/E1.7.png -------------------------------------------------------------------------------- /pic/E1.8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javaee/batchlab/ed95ed5c245fefab8cb721ab8f256350bf414270/pic/E1.8.jpg -------------------------------------------------------------------------------- /pic/E1.8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javaee/batchlab/ed95ed5c245fefab8cb721ab8f256350bf414270/pic/E1.8.png -------------------------------------------------------------------------------- /pic/E1.9.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javaee/batchlab/ed95ed5c245fefab8cb721ab8f256350bf414270/pic/E1.9.jpg -------------------------------------------------------------------------------- /pic/E1.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javaee/batchlab/ed95ed5c245fefab8cb721ab8f256350bf414270/pic/E1.9.png -------------------------------------------------------------------------------- /pic/E2.1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javaee/batchlab/ed95ed5c245fefab8cb721ab8f256350bf414270/pic/E2.1.jpg -------------------------------------------------------------------------------- /pic/E2.1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javaee/batchlab/ed95ed5c245fefab8cb721ab8f256350bf414270/pic/E2.1.png -------------------------------------------------------------------------------- /pic/E2.2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javaee/batchlab/ed95ed5c245fefab8cb721ab8f256350bf414270/pic/E2.2.jpg -------------------------------------------------------------------------------- /pic/E2.2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javaee/batchlab/ed95ed5c245fefab8cb721ab8f256350bf414270/pic/E2.2.png -------------------------------------------------------------------------------- /pic/E2.3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javaee/batchlab/ed95ed5c245fefab8cb721ab8f256350bf414270/pic/E2.3.jpg -------------------------------------------------------------------------------- /pic/E2.3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javaee/batchlab/ed95ed5c245fefab8cb721ab8f256350bf414270/pic/E2.3.png -------------------------------------------------------------------------------- /pic/E3.1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javaee/batchlab/ed95ed5c245fefab8cb721ab8f256350bf414270/pic/E3.1.jpg -------------------------------------------------------------------------------- /pic/E3.1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javaee/batchlab/ed95ed5c245fefab8cb721ab8f256350bf414270/pic/E3.1.png -------------------------------------------------------------------------------- /pic/E3.2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javaee/batchlab/ed95ed5c245fefab8cb721ab8f256350bf414270/pic/E3.2.jpg -------------------------------------------------------------------------------- /pic/E3.2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javaee/batchlab/ed95ed5c245fefab8cb721ab8f256350bf414270/pic/E3.2.png -------------------------------------------------------------------------------- /pic/cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javaee/batchlab/ed95ed5c245fefab8cb721ab8f256350bf414270/pic/cover.jpg -------------------------------------------------------------------------------- /pic/originals/E1.1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javaee/batchlab/ed95ed5c245fefab8cb721ab8f256350bf414270/pic/originals/E1.1.png -------------------------------------------------------------------------------- /pic/originals/E1.10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javaee/batchlab/ed95ed5c245fefab8cb721ab8f256350bf414270/pic/originals/E1.10.png -------------------------------------------------------------------------------- /pic/originals/E1.11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javaee/batchlab/ed95ed5c245fefab8cb721ab8f256350bf414270/pic/originals/E1.11.png -------------------------------------------------------------------------------- /pic/originals/E1.12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javaee/batchlab/ed95ed5c245fefab8cb721ab8f256350bf414270/pic/originals/E1.12.png -------------------------------------------------------------------------------- /pic/originals/E1.14.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javaee/batchlab/ed95ed5c245fefab8cb721ab8f256350bf414270/pic/originals/E1.14.png -------------------------------------------------------------------------------- /pic/originals/E1.15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javaee/batchlab/ed95ed5c245fefab8cb721ab8f256350bf414270/pic/originals/E1.15.png -------------------------------------------------------------------------------- /pic/originals/E1.16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javaee/batchlab/ed95ed5c245fefab8cb721ab8f256350bf414270/pic/originals/E1.16.png -------------------------------------------------------------------------------- /pic/originals/E1.17.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javaee/batchlab/ed95ed5c245fefab8cb721ab8f256350bf414270/pic/originals/E1.17.png -------------------------------------------------------------------------------- /pic/originals/E1.2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javaee/batchlab/ed95ed5c245fefab8cb721ab8f256350bf414270/pic/originals/E1.2.png -------------------------------------------------------------------------------- /pic/originals/E1.3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javaee/batchlab/ed95ed5c245fefab8cb721ab8f256350bf414270/pic/originals/E1.3.png -------------------------------------------------------------------------------- /pic/originals/E1.4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javaee/batchlab/ed95ed5c245fefab8cb721ab8f256350bf414270/pic/originals/E1.4.png -------------------------------------------------------------------------------- /pic/originals/E1.5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javaee/batchlab/ed95ed5c245fefab8cb721ab8f256350bf414270/pic/originals/E1.5.png -------------------------------------------------------------------------------- /pic/originals/E1.6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javaee/batchlab/ed95ed5c245fefab8cb721ab8f256350bf414270/pic/originals/E1.6.png -------------------------------------------------------------------------------- /pic/originals/E1.7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javaee/batchlab/ed95ed5c245fefab8cb721ab8f256350bf414270/pic/originals/E1.7.png -------------------------------------------------------------------------------- /pic/originals/E1.8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javaee/batchlab/ed95ed5c245fefab8cb721ab8f256350bf414270/pic/originals/E1.8.png -------------------------------------------------------------------------------- /pic/originals/E1.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javaee/batchlab/ed95ed5c245fefab8cb721ab8f256350bf414270/pic/originals/E1.9.png --------------------------------------------------------------------------------