├── LICENSE ├── README.md ├── core-java └── conversions │ ├── .gitignore │ ├── README.md │ └── src │ └── Main.java ├── nodejs ├── crypto │ ├── .gitignore │ ├── README.md │ ├── crypto-buffer.js │ ├── crypto-stream.js │ ├── crypto-text.js │ ├── crypto.js │ ├── file.out.txt │ ├── file.txt │ └── package.json ├── csv-to-json │ ├── .gitignore │ ├── README.md │ ├── app-async.js │ ├── app.js │ ├── package-lock.json │ ├── package.json │ ├── users.csv │ └── users.json ├── express-multer │ ├── .gitignore │ ├── README.md │ ├── index.js │ ├── package-lock.json │ └── package.json ├── files-upload │ ├── .gitignore │ ├── README.md │ ├── index.js │ ├── package-lock.json │ └── package.json ├── json-to-csv │ ├── .gitignore │ ├── README.md │ ├── app-async.js │ ├── app-file.js │ ├── app-promise.js │ ├── app.js │ ├── package-lock.json │ ├── package.json │ ├── todos.csv │ └── todos.json ├── mongodb-local-connect │ ├── .gitignore │ ├── README.md │ ├── connect-mongo-client.js │ ├── connect-mongoose.js │ ├── package-lock.json │ └── package.json ├── ses-nodejs │ ├── .gitignore │ ├── README.md │ ├── config.js │ ├── package-lock.json │ ├── package.json │ ├── server.js │ └── ses-client.js └── xml-to-json │ ├── .gitignore │ ├── README.md │ ├── app-async.js │ ├── app-file.js │ ├── app-promise.js │ ├── app.js │ ├── package-lock.json │ ├── package.json │ ├── user.json │ └── user.xml ├── others ├── anchor-links │ ├── .gitignore │ ├── README.md │ ├── anchor-javascript.html │ └── anchor-jquery.html └── axios-js │ ├── README.md │ ├── index.html │ └── script.js ├── spring-boot ├── console-app │ ├── .gitignore │ ├── README.md │ ├── build.gradle │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ ├── settings.gradle │ └── src │ │ └── main │ │ ├── java │ │ └── com │ │ │ └── attacomsian │ │ │ └── console │ │ │ ├── ConsoleApplication.java │ │ │ └── services │ │ │ └── HelloService.java │ │ └── resources │ │ └── application.properties ├── cookies │ ├── .gitignore │ ├── README.md │ ├── build.gradle │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ ├── settings.gradle │ └── src │ │ └── main │ │ ├── java │ │ └── com │ │ │ └── attacomsian │ │ │ └── cookies │ │ │ ├── Application.java │ │ │ └── controllers │ │ │ └── CookieController.java │ │ └── resources │ │ └── application.properties ├── export-data-csv │ ├── .gitignore │ ├── README.md │ ├── build.gradle │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ ├── settings.gradle │ └── src │ │ └── main │ │ ├── java │ │ └── com │ │ │ └── attacomsian │ │ │ └── exportcsv │ │ │ ├── Application.java │ │ │ ├── controllers │ │ │ └── UserController.java │ │ │ └── data │ │ │ ├── User.java │ │ │ └── UserService.java │ │ └── resources │ │ └── application.properties ├── jackson │ ├── .gitignore │ ├── README.md │ ├── build.gradle │ ├── customer.json │ ├── customer2.json │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ ├── settings.gradle │ └── src │ │ └── main │ │ └── java │ │ └── com │ │ └── attacomsian │ │ └── jackson │ │ ├── Address.java │ │ ├── Customer.java │ │ └── JacksonApplication.java ├── parse-data-csv │ ├── .gitignore │ ├── README.md │ ├── build.gradle │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ ├── settings.gradle │ ├── src │ │ └── main │ │ │ ├── java │ │ │ └── com │ │ │ │ └── attacomsian │ │ │ │ └── parsecsv │ │ │ │ ├── Application.java │ │ │ │ ├── controllers │ │ │ │ └── UploadController.java │ │ │ │ └── domains │ │ │ │ └── User.java │ │ │ └── resources │ │ │ ├── application.properties │ │ │ └── templates │ │ │ └── index.html │ └── users.csv ├── rest-template │ ├── .gitignore │ ├── README.md │ ├── build.gradle │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ ├── settings.gradle │ └── src │ │ └── main │ │ ├── java │ │ └── com │ │ │ └── attacomsian │ │ │ └── rest │ │ │ ├── Application.java │ │ │ ├── models │ │ │ └── Post.java │ │ │ └── services │ │ │ └── RestService.java │ │ └── resources │ │ └── application.properties ├── scheduling │ ├── .gitignore │ ├── README.md │ ├── build.gradle │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ ├── settings.gradle │ └── src │ │ └── main │ │ ├── java │ │ └── com │ │ │ └── attacomsian │ │ │ └── scheduling │ │ │ ├── Application.java │ │ │ ├── ScheduledTasks.java │ │ │ └── SchedulerConfig.java │ │ └── resources │ │ └── application.properties ├── ses-spring-boot │ ├── .gitignore │ ├── LICENSE │ ├── README.md │ ├── build.gradle │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ ├── settings.gradle │ └── src │ │ ├── main │ │ ├── java │ │ │ └── app │ │ │ │ ├── AppController.java │ │ │ │ ├── Application.java │ │ │ │ └── ses │ │ │ │ ├── AmazonAttachment.java │ │ │ │ ├── AmazonEmail.java │ │ │ │ ├── SESFrom.java │ │ │ │ ├── SESProcessor.java │ │ │ │ └── SESWorker.java │ │ └── resources │ │ │ ├── AwsCredentials.properties │ │ │ └── application.properties │ │ └── test │ │ └── java │ │ └── app │ │ └── ApplicationTests.java ├── stripe-example │ ├── .gitignore │ ├── README.md │ ├── build.gradle │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ ├── settings.gradle │ └── src │ │ └── main │ │ ├── java │ │ └── com │ │ │ └── attacomsian │ │ │ └── stripe │ │ │ ├── StripeApplication.java │ │ │ ├── commons │ │ │ └── Response.java │ │ │ ├── controllers │ │ │ └── PaymentController.java │ │ │ └── services │ │ │ └── StripeService.java │ │ └── resources │ │ ├── application.properties │ │ └── templates │ │ ├── charge.html │ │ ├── homepage.html │ │ └── subscription.html ├── upload-files │ ├── .gitignore │ ├── README.md │ ├── build.gradle │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ ├── settings.gradle │ └── src │ │ └── main │ │ ├── java │ │ └── com │ │ │ └── attacomsian │ │ │ └── uploadfiles │ │ │ ├── Application.java │ │ │ ├── commons │ │ │ └── FileResponse.java │ │ │ ├── controllers │ │ │ └── FileController.java │ │ │ └── storage │ │ │ ├── FileNotFoundException.java │ │ │ ├── FileSystemStorageService.java │ │ │ ├── StorageException.java │ │ │ ├── StorageProperties.java │ │ │ └── StorageService.java │ │ └── resources │ │ ├── application.properties │ │ └── templates │ │ └── listFiles.html └── xml-response-parser │ ├── .gitignore │ ├── README.md │ ├── build.gradle │ ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ ├── settings.gradle │ └── src │ └── main │ ├── java │ └── com │ │ └── attacomsian │ │ └── xml │ │ ├── XmlParserApplication.java │ │ ├── models │ │ ├── Course.java │ │ └── Student.java │ │ └── services │ │ └── XMLService.java │ └── resources │ └── application.properties ├── spring-data-jpa ├── jpa-auditing │ ├── .gitignore │ ├── README.md │ ├── build.gradle │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ ├── settings.gradle │ └── src │ │ └── main │ │ ├── java │ │ └── com │ │ │ └── attacomsian │ │ │ └── jpa │ │ │ ├── Application.java │ │ │ ├── config │ │ │ └── AuditConfiguration.java │ │ │ ├── domains │ │ │ ├── Auditable.java │ │ │ ├── EntityAuditorAware.java │ │ │ └── Todo.java │ │ │ └── repositories │ │ │ └── TodoRepository.java │ │ └── resources │ │ └── application.properties ├── jpa-getting-started │ ├── .gitignore │ ├── README.md │ ├── build.gradle │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ ├── settings.gradle │ └── src │ │ └── main │ │ ├── java │ │ └── com │ │ │ └── attacomsian │ │ │ └── jpa │ │ │ ├── Application.java │ │ │ ├── domains │ │ │ └── User.java │ │ │ └── repositories │ │ │ └── UserRepository.java │ │ └── resources │ │ └── application.properties ├── jpa-h2 │ ├── .gitignore │ ├── README.md │ ├── build.gradle │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ ├── settings.gradle │ └── src │ │ └── main │ │ ├── java │ │ └── com │ │ │ └── attacomsian │ │ │ └── jpa │ │ │ ├── Application.java │ │ │ ├── domains │ │ │ └── Book.java │ │ │ └── repositories │ │ │ └── BookRepository.java │ │ └── resources │ │ └── application.properties ├── jpa-mappings │ ├── .gitignore │ ├── README.md │ ├── build.gradle │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ ├── settings.gradle │ └── src │ │ └── main │ │ ├── java │ │ └── com │ │ │ └── attacomsian │ │ │ └── jpa │ │ │ ├── Application.java │ │ │ ├── composite │ │ │ ├── domains │ │ │ │ ├── Account.java │ │ │ │ ├── AccountId.java │ │ │ │ ├── Employee.java │ │ │ │ └── EmployeeId.java │ │ │ └── repositories │ │ │ │ ├── AccountRepository.java │ │ │ │ └── EmployeeRepository.java │ │ │ ├── many2many │ │ │ ├── domains │ │ │ │ ├── Course.java │ │ │ │ └── Student.java │ │ │ └── repositories │ │ │ │ ├── CourseRepository.java │ │ │ │ └── StudentRepository.java │ │ │ ├── one2many │ │ │ ├── domains │ │ │ │ ├── Book.java │ │ │ │ └── Page.java │ │ │ └── repositories │ │ │ │ ├── BookRepository.java │ │ │ │ └── PageRepository.java │ │ │ └── one2one │ │ │ ├── domains │ │ │ ├── Address.java │ │ │ └── User.java │ │ │ └── repositories │ │ │ ├── AddressRepository.java │ │ │ └── UserRepository.java │ │ └── resources │ │ └── application.properties ├── jpa-mysql │ ├── .gitignore │ ├── README.md │ ├── build.gradle │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ ├── settings.gradle │ └── src │ │ └── main │ │ ├── java │ │ └── com │ │ │ └── attacomsian │ │ │ └── jpa │ │ │ ├── Application.java │ │ │ ├── domains │ │ │ └── Note.java │ │ │ └── repositories │ │ │ └── NoteRepository.java │ │ └── resources │ │ └── application.properties ├── jpa-pagination │ ├── .gitignore │ ├── README.md │ ├── build.gradle │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ ├── settings.gradle │ └── src │ │ └── main │ │ ├── java │ │ └── com │ │ │ └── attacomsian │ │ │ └── jpa │ │ │ ├── Application.java │ │ │ ├── domains │ │ │ └── Person.java │ │ │ └── repositories │ │ │ └── PersonRepository.java │ │ └── resources │ │ └── application.properties ├── jpa-queries │ ├── .gitignore │ ├── README.md │ ├── build.gradle │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ ├── settings.gradle │ └── src │ │ └── main │ │ ├── java │ │ └── com │ │ │ └── attacomsian │ │ │ └── jpa │ │ │ ├── Application.java │ │ │ ├── custom │ │ │ ├── domains │ │ │ │ └── Note.java │ │ │ └── repositories │ │ │ │ └── NoteRepository.java │ │ │ ├── derived │ │ │ ├── domains │ │ │ │ └── User.java │ │ │ └── repositories │ │ │ │ └── UserRepository.java │ │ │ └── named │ │ │ ├── domains │ │ │ └── Book.java │ │ │ └── repositories │ │ │ └── BookRepository.java │ │ └── resources │ │ ├── META-INF │ │ ├── jpa-named-queries.properties │ │ └── orm.xml │ │ └── application.properties ├── jpa-sorting │ ├── .gitignore │ ├── README.md │ ├── build.gradle │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ ├── settings.gradle │ └── src │ │ └── main │ │ ├── java │ │ └── com │ │ │ └── attacomsian │ │ │ └── jpa │ │ │ ├── Application.java │ │ │ ├── domains │ │ │ └── Employee.java │ │ │ └── repositories │ │ │ └── EmployeeRepository.java │ │ └── resources │ │ └── application.properties └── jpa-specifications │ ├── .gitignore │ ├── README.md │ ├── build.gradle │ ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ ├── settings.gradle │ └── src │ └── main │ ├── java │ └── com │ │ └── attacomsian │ │ └── jpa │ │ ├── Application.java │ │ ├── domains │ │ └── Movie.java │ │ └── repositories │ │ ├── MovieRepository.java │ │ └── specs │ │ ├── MovieSpecification.java │ │ ├── SearchCriteria.java │ │ └── SearchOperation.java │ └── resources │ └── application.properties └── thymeleaf ├── get-started ├── .gitignore ├── README.md ├── build.gradle ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── settings.gradle └── src │ └── main │ ├── java │ └── com │ │ └── attacomsian │ │ └── getstarted │ │ ├── Application.java │ │ └── controllers │ │ └── IndexController.java │ └── resources │ ├── application.properties │ └── templates │ └── index.html ├── thymeleaf-forms ├── .gitignore ├── README.md ├── build.gradle ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── settings.gradle └── src │ └── main │ ├── java │ └── com │ │ └── attacmosian │ │ └── thymeleaf │ │ └── forms │ │ ├── Application.java │ │ ├── controllers │ │ └── ProjectController.java │ │ └── domains │ │ └── Project.java │ └── resources │ ├── application.properties │ └── templates │ ├── create-project.html │ └── result.html └── thymeleaf-layouts ├── .gitignore ├── README.md ├── build.gradle ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── settings.gradle └── src └── main ├── java └── com │ └── attacomsian │ └── thymeleaf │ └── layouts │ ├── Application.java │ └── controllers │ └── IndexController.java └── resources ├── application.properties └── templates ├── about.html ├── contact.html ├── index.html └── layout.html /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Atta Ur Rehman Shah 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Example Projects 2 | 3 | Example projects for https://attacomsian.com/blog/ website. 4 | 5 | All codes are released under [MIT](https://github.com/attacomsian/code-examples/blob/master/LICENSE) license unless otherwise specified. 6 | -------------------------------------------------------------------------------- /core-java/conversions/.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /build/ 3 | !gradle/wrapper/gradle-wrapper.jar 4 | 5 | ### STS ### 6 | .apt_generated 7 | .classpath 8 | .factorypath 9 | .project 10 | .settings 11 | .springBeans 12 | .sts4-cache 13 | 14 | ### IntelliJ IDEA ### 15 | .idea 16 | *.iws 17 | *.iml 18 | *.ipr 19 | /out/ 20 | 21 | ### NetBeans ### 22 | /nbproject/private/ 23 | /nbbuild/ 24 | /dist/ 25 | /nbdist/ 26 | /.nb-gradle/ 27 | -------------------------------------------------------------------------------- /core-java/conversions/README.md: -------------------------------------------------------------------------------- 1 | # Date Type Conversions in Java 2 | 3 | For step-by-step instructions, please visit the [blog post](https://attacomsian.com/blog/data-type-conversions-java). 4 | -------------------------------------------------------------------------------- /nodejs/crypto/.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /build/ 3 | !gradle/wrapper/gradle-wrapper.jar 4 | 5 | ### STS ### 6 | .apt_generated 7 | .classpath 8 | .factorypath 9 | .project 10 | .settings 11 | .springBeans 12 | .sts4-cache 13 | 14 | ### IntelliJ IDEA ### 15 | .idea 16 | *.iws 17 | *.iml 18 | *.ipr 19 | /out/ 20 | 21 | ### NetBeans ### 22 | /nbproject/private/ 23 | /nbbuild/ 24 | /dist/ 25 | /nbdist/ 26 | /.nb-gradle/ 27 | 28 | ### Node ### 29 | node_modules 30 | 31 | # Extras 32 | /uploads/ 33 | -------------------------------------------------------------------------------- /nodejs/crypto/README.md: -------------------------------------------------------------------------------- 1 | # How to encrypt and decrypt data in Node.js 2 | 3 | For step-by-step instructions, please visit the [blog post](https://attacomsian.com/blog/nodejs-encrypt-decrypt-data). 4 | -------------------------------------------------------------------------------- /nodejs/crypto/crypto-buffer.js: -------------------------------------------------------------------------------- 1 | const { encrypt, decrypt } = require('./crypto'); 2 | 3 | const hash = encrypt(Buffer.from('Hello World!', 'utf8')); 4 | 5 | console.log(hash); 6 | 7 | // { 8 | // iv: '692e44dbbea073fc1a8d1c37ea68dffa', 9 | // content: 'bbffd902d55d7a00f3a0504e' 10 | // } 11 | 12 | const text = decrypt(hash); 13 | 14 | console.log(text); // Hello World! -------------------------------------------------------------------------------- /nodejs/crypto/crypto-stream.js: -------------------------------------------------------------------------------- 1 | const crypto = require('crypto'); 2 | const fs = require('fs'); 3 | 4 | const algorithm = 'aes-256-ctr'; 5 | const secretKey = 'vOVH6sdmpNWjRRIqCc7rdxs01lwHzfr3'; 6 | const iv = crypto.randomBytes(16); 7 | 8 | // input file 9 | const r = fs.createReadStream('file.txt'); 10 | 11 | // encrypt content 12 | const encrypt = crypto.createCipheriv(algorithm, secretKey, iv); 13 | 14 | // decrypt content 15 | const decrypt = crypto.createDecipheriv(algorithm, secretKey, iv); 16 | 17 | // write file 18 | const w = fs.createWriteStream('file.out.txt'); 19 | 20 | // start pipe 21 | r.pipe(encrypt) 22 | .pipe(decrypt) 23 | .pipe(w); -------------------------------------------------------------------------------- /nodejs/crypto/crypto-text.js: -------------------------------------------------------------------------------- 1 | const { encrypt, decrypt } = require('./crypto'); 2 | 3 | const hash = encrypt('Hello World!'); 4 | 5 | console.log(hash); 6 | 7 | // { 8 | // iv: '237f306841bd23a418878792252ff6c8', 9 | // content: 'e2da5c6073dd978991d8c7cd' 10 | // } 11 | 12 | const text = decrypt(hash); 13 | 14 | console.log(text); // Hello World! -------------------------------------------------------------------------------- /nodejs/crypto/crypto.js: -------------------------------------------------------------------------------- 1 | const crypto = require('crypto'); 2 | 3 | const algorithm = 'aes-256-ctr'; 4 | const secretKey = 'vOVH6sdmpNWjRRIqCc7rdxs01lwHzfr3'; 5 | const iv = crypto.randomBytes(16); 6 | 7 | const encrypt = (text) => { 8 | 9 | const cipher = crypto.createCipheriv(algorithm, secretKey, iv); 10 | 11 | const encrypted = Buffer.concat([cipher.update(text), cipher.final()]); 12 | 13 | return { 14 | iv: iv.toString('hex'), 15 | content: encrypted.toString('hex') 16 | }; 17 | }; 18 | 19 | const decrypt = (hash) => { 20 | 21 | const decipher = crypto.createDecipheriv(algorithm, secretKey, Buffer.from(hash.iv, 'hex')); 22 | 23 | const decrpyted = Buffer.concat([decipher.update(Buffer.from(hash.content, 'hex')), decipher.final()]); 24 | 25 | return decrpyted.toString(); 26 | }; 27 | 28 | module.exports = { 29 | encrypt, 30 | decrypt 31 | }; -------------------------------------------------------------------------------- /nodejs/crypto/file.out.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/attacomsian/code-examples/e48ae7eb3ff05aeb5f47016fe8e44c6341e7d005/nodejs/crypto/file.out.txt -------------------------------------------------------------------------------- /nodejs/crypto/file.txt: -------------------------------------------------------------------------------- 1 | Hello World! -------------------------------------------------------------------------------- /nodejs/crypto/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "crypto", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "crypto-text.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC" 12 | } 13 | -------------------------------------------------------------------------------- /nodejs/csv-to-json/.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /build/ 3 | !gradle/wrapper/gradle-wrapper.jar 4 | 5 | ### STS ### 6 | .apt_generated 7 | .classpath 8 | .factorypath 9 | .project 10 | .settings 11 | .springBeans 12 | .sts4-cache 13 | 14 | ### IntelliJ IDEA ### 15 | .idea 16 | *.iws 17 | *.iml 18 | *.ipr 19 | /out/ 20 | 21 | ### NetBeans ### 22 | /nbproject/private/ 23 | /nbbuild/ 24 | /dist/ 25 | /nbdist/ 26 | /.nb-gradle/ 27 | 28 | ### Node ### 29 | node_modules 30 | 31 | # Extras 32 | /uploads/ 33 | -------------------------------------------------------------------------------- /nodejs/csv-to-json/README.md: -------------------------------------------------------------------------------- 1 | # How to convert CSV to JSON in Node.js 2 | 3 | For step-by-step instructions, please visit the [blog post](https://attacomsian.com/blog/nodejs-convert-csv-to-json). 4 | -------------------------------------------------------------------------------- /nodejs/csv-to-json/app-async.js: -------------------------------------------------------------------------------- 1 | // require csvtojson module 2 | const CSVToJSON = require('csvtojson'); 3 | 4 | // convert users.csv file to JSON array 5 | (async () => { 6 | try { 7 | const users = await CSVToJSON().fromFile('users.csv'); 8 | 9 | // log the JSON array 10 | console.log(users); 11 | 12 | } catch (err) { 13 | console.log(err); 14 | } 15 | })(); -------------------------------------------------------------------------------- /nodejs/csv-to-json/app.js: -------------------------------------------------------------------------------- 1 | // require csvtojson module 2 | const CSVToJSON = require('csvtojson'); 3 | const fs = require('fs'); 4 | 5 | // convert users.csv file to JSON array 6 | CSVToJSON().fromFile('users.csv') 7 | .then(users => { 8 | 9 | // users is a JSON array 10 | // log the JSON array 11 | console.log(users); 12 | 13 | // Write JSON array to a file 14 | fs.writeFile('users.json', JSON.stringify(users, null, 4), (err) => { 15 | if (err) { 16 | throw err; 17 | } 18 | console.log("JSON array is saved."); 19 | }); 20 | 21 | }).catch(err => { 22 | // log error if any 23 | console.log(err); 24 | }); -------------------------------------------------------------------------------- /nodejs/csv-to-json/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "csv-to-json", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "bluebird": { 8 | "version": "3.7.2", 9 | "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", 10 | "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" 11 | }, 12 | "csvtojson": { 13 | "version": "2.0.10", 14 | "resolved": "https://registry.npmjs.org/csvtojson/-/csvtojson-2.0.10.tgz", 15 | "integrity": "sha512-lUWFxGKyhraKCW8Qghz6Z0f2l/PqB1W3AO0HKJzGIQ5JRSlR651ekJDiGJbBT4sRNNv5ddnSGVEnsxP9XRCVpQ==", 16 | "requires": { 17 | "bluebird": "^3.5.1", 18 | "lodash": "^4.17.3", 19 | "strip-bom": "^2.0.0" 20 | } 21 | }, 22 | "is-utf8": { 23 | "version": "0.2.1", 24 | "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", 25 | "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=" 26 | }, 27 | "lodash": { 28 | "version": "4.17.19", 29 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz", 30 | "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==" 31 | }, 32 | "strip-bom": { 33 | "version": "2.0.0", 34 | "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", 35 | "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", 36 | "requires": { 37 | "is-utf8": "^0.2.0" 38 | } 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /nodejs/csv-to-json/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "csv-to-json", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "csvtojson": "^2.0.10" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /nodejs/csv-to-json/users.csv: -------------------------------------------------------------------------------- 1 | id,name,email,country,age 2 | 100,Atta Shah,atta@example.com,PK,30 3 | 101,Alex Jones,alex@example.com,DE,35 4 | 102,Jovan Lee,jovan@example.com,FR,25 5 | 103,Greg Hover,greg@example.com,US,45 -------------------------------------------------------------------------------- /nodejs/csv-to-json/users.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": "100", 4 | "name": "Atta Shah", 5 | "email": "atta@example.com", 6 | "country": "PK", 7 | "age": "30" 8 | }, 9 | { 10 | "id": "101", 11 | "name": "Alex Jones", 12 | "email": "alex@example.com", 13 | "country": "DE", 14 | "age": "35" 15 | }, 16 | { 17 | "id": "102", 18 | "name": "Jovan Lee", 19 | "email": "jovan@example.com", 20 | "country": "FR", 21 | "age": "25" 22 | }, 23 | { 24 | "id": "103", 25 | "name": "Greg Hover", 26 | "email": "greg@example.com", 27 | "country": "US", 28 | "age": "45" 29 | } 30 | ] -------------------------------------------------------------------------------- /nodejs/express-multer/.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /build/ 3 | !gradle/wrapper/gradle-wrapper.jar 4 | 5 | ### STS ### 6 | .apt_generated 7 | .classpath 8 | .factorypath 9 | .project 10 | .settings 11 | .springBeans 12 | .sts4-cache 13 | 14 | ### IntelliJ IDEA ### 15 | .idea 16 | *.iws 17 | *.iml 18 | *.ipr 19 | /out/ 20 | 21 | ### NetBeans ### 22 | /nbproject/private/ 23 | /nbbuild/ 24 | /dist/ 25 | /nbdist/ 26 | /.nb-gradle/ 27 | 28 | ### Node ### 29 | node_modules 30 | 31 | # Extras 32 | /uploads/ 33 | -------------------------------------------------------------------------------- /nodejs/express-multer/README.md: -------------------------------------------------------------------------------- 1 | # Express File Upload with Multer in Node.js 2 | 3 | For step-by-step instructions, please visit the [blog post](https://attacomsian.com/blog/express-file-upload-multer). 4 | -------------------------------------------------------------------------------- /nodejs/express-multer/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "express-multer", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "start": "node index.js" 9 | }, 10 | "keywords": [], 11 | "author": "", 12 | "license": "ISC", 13 | "dependencies": { 14 | "body-parser": "^1.19.0", 15 | "cors": "^2.8.5", 16 | "express": "^4.17.1", 17 | "morgan": "^1.9.1", 18 | "multer": "^1.4.2" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /nodejs/files-upload/.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /build/ 3 | !gradle/wrapper/gradle-wrapper.jar 4 | 5 | ### STS ### 6 | .apt_generated 7 | .classpath 8 | .factorypath 9 | .project 10 | .settings 11 | .springBeans 12 | .sts4-cache 13 | 14 | ### IntelliJ IDEA ### 15 | .idea 16 | *.iws 17 | *.iml 18 | *.ipr 19 | /out/ 20 | 21 | ### NetBeans ### 22 | /nbproject/private/ 23 | /nbbuild/ 24 | /dist/ 25 | /nbdist/ 26 | /.nb-gradle/ 27 | 28 | ### Node ### 29 | node_modules 30 | 31 | # Extras 32 | /uploads/ 33 | -------------------------------------------------------------------------------- /nodejs/files-upload/README.md: -------------------------------------------------------------------------------- 1 | # Uploading Files in Node.js and Express 2 | 3 | For step-by-step instructions, please visit the [blog post](https://attacomsian.com/blog/uploading-files-nodejs-express). 4 | -------------------------------------------------------------------------------- /nodejs/files-upload/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "files-upload", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "start": "node index.js" 9 | }, 10 | "keywords": [], 11 | "author": "", 12 | "license": "ISC", 13 | "dependencies": { 14 | "body-parser": "^1.18.3", 15 | "cors": "^2.8.5", 16 | "express": "^4.16.4", 17 | "express-fileupload": "^1.1.9", 18 | "lodash": "^4.17.19", 19 | "morgan": "^1.9.1" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /nodejs/json-to-csv/.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /build/ 3 | !gradle/wrapper/gradle-wrapper.jar 4 | 5 | ### STS ### 6 | .apt_generated 7 | .classpath 8 | .factorypath 9 | .project 10 | .settings 11 | .springBeans 12 | .sts4-cache 13 | 14 | ### IntelliJ IDEA ### 15 | .idea 16 | *.iws 17 | *.iml 18 | *.ipr 19 | /out/ 20 | 21 | ### NetBeans ### 22 | /nbproject/private/ 23 | /nbbuild/ 24 | /dist/ 25 | /nbdist/ 26 | /.nb-gradle/ 27 | 28 | ### Node ### 29 | node_modules 30 | 31 | # Extras 32 | /uploads/ 33 | -------------------------------------------------------------------------------- /nodejs/json-to-csv/README.md: -------------------------------------------------------------------------------- 1 | # How to convert JSON to CSV in Node.js 2 | 3 | For step-by-step instructions, please visit the [blog post](https://attacomsian.com/blog/nodejs-convert-json-to-csv). 4 | -------------------------------------------------------------------------------- /nodejs/json-to-csv/app-async.js: -------------------------------------------------------------------------------- 1 | // require json-2-csv module 2 | const converter = require('json-2-csv'); 3 | const fs = require('fs'); 4 | 5 | // read JSON from a file 6 | const todos = JSON.parse(fs.readFileSync('todos.json')); 7 | 8 | // convert JSON array to CSV string 9 | (async () => { 10 | try { 11 | const csv = await converter.json2csvAsync(todos); 12 | 13 | // print CSV string 14 | console.log(csv); 15 | 16 | // write CSV to a file 17 | fs.writeFileSync('todos.csv', csv); 18 | 19 | } catch (err) { 20 | console.log(err); 21 | } 22 | })(); -------------------------------------------------------------------------------- /nodejs/json-to-csv/app-file.js: -------------------------------------------------------------------------------- 1 | // require json-2-csv module 2 | const converter = require('json-2-csv'); 3 | const fs = require('fs'); 4 | 5 | // read JSON from a file 6 | const todos = JSON.parse(fs.readFileSync('todos.json')); 7 | 8 | // convert JSON array to CSV string 9 | converter.json2csv(todos, (err, csv) => { 10 | if (err) { 11 | throw err; 12 | } 13 | 14 | // print CSV string 15 | console.log(csv); 16 | 17 | // write CSV to a file 18 | fs.writeFileSync('todos.csv', csv); 19 | 20 | }); -------------------------------------------------------------------------------- /nodejs/json-to-csv/app-promise.js: -------------------------------------------------------------------------------- 1 | // require json-2-csv module 2 | const converter = require('json-2-csv'); 3 | const fs = require('fs'); 4 | 5 | // read JSON from a file 6 | const todos = JSON.parse(fs.readFileSync('todos.json')); 7 | 8 | // convert JSON array to CSV string 9 | converter.json2csvAsync(todos).then(csv => { 10 | 11 | // print CSV string 12 | console.log(csv); 13 | 14 | // write CSV to a file 15 | fs.writeFileSync('todos.csv', csv); 16 | 17 | }).catch(err => console.log(err)); -------------------------------------------------------------------------------- /nodejs/json-to-csv/app.js: -------------------------------------------------------------------------------- 1 | // require json-2-csv module 2 | const converter = require('json-2-csv'); 3 | const fs = require('fs'); 4 | 5 | // declare a JSON array 6 | const todos = [ 7 | { 8 | "id": 1, 9 | "title": "delectus aut autem", 10 | "completed": false 11 | }, 12 | { 13 | "id": 2, 14 | "title": "quis ut nam facilis et officia qui", 15 | "completed": false 16 | }, 17 | { 18 | "id": 3, 19 | "title": "fugiat veniam minus", 20 | "completed": false 21 | }]; 22 | 23 | // Convert JSON array to CSV string 24 | converter.json2csv(todos, (err, csv) => { 25 | if (err) { 26 | throw err; 27 | } 28 | 29 | // print CSV string 30 | console.log(csv); 31 | 32 | // write CSV to a file 33 | fs.writeFileSync('todos.csv', csv); 34 | 35 | }); -------------------------------------------------------------------------------- /nodejs/json-to-csv/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "json-to-csv", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "deeks": { 8 | "version": "2.2.4", 9 | "resolved": "https://registry.npmjs.org/deeks/-/deeks-2.2.4.tgz", 10 | "integrity": "sha512-T8HtfilZeYvVRmTx9J6Nk4e0ayb/RqHx/XBOJpUybQyedRRtVw0I21pezA+OjXoCnL5YkkjCAM2TFvSJt0NwWw==" 11 | }, 12 | "doc-path": { 13 | "version": "2.0.2", 14 | "resolved": "https://registry.npmjs.org/doc-path/-/doc-path-2.0.2.tgz", 15 | "integrity": "sha512-7KAEFeGh+xlqATVLXywN6g2U6RF7CW1la80BdtRF3BaiP1rz3r1UCewUeOnwpJ9A44LX66u32dYaU9zIqC1/TQ==" 16 | }, 17 | "json-2-csv": { 18 | "version": "3.6.2", 19 | "resolved": "https://registry.npmjs.org/json-2-csv/-/json-2-csv-3.6.2.tgz", 20 | "integrity": "sha512-aJGagjPIZj9iqAO8UVcNggVuRpxbMvG3WspGntcGm1Kxb3TFCwWC4U36qoybVkkm7n4ivDaVjwBd4PPlQJkP3Q==", 21 | "requires": { 22 | "deeks": "2.2.4", 23 | "doc-path": "2.0.2" 24 | } 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /nodejs/json-to-csv/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "json-to-csv", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "json-2-csv": "^3.6.2" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /nodejs/json-to-csv/todos.csv: -------------------------------------------------------------------------------- 1 | id,title,completed 2 | 1,delectus aut autem,false 3 | 2,quis ut nam facilis et officia qui,false 4 | 3,fugiat veniam minus,false -------------------------------------------------------------------------------- /nodejs/json-to-csv/todos.json: -------------------------------------------------------------------------------- 1 | [{ 2 | "id": 1, 3 | "title": "delectus aut autem", 4 | "completed": false 5 | }, 6 | { 7 | "id": 2, 8 | "title": "quis ut nam facilis et officia qui", 9 | "completed": false 10 | }, 11 | { 12 | "id": 3, 13 | "title": "fugiat veniam minus", 14 | "completed": false 15 | } 16 | ] -------------------------------------------------------------------------------- /nodejs/mongodb-local-connect/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | 9 | # Diagnostic reports (https://nodejs.org/api/report.html) 10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 11 | 12 | # Runtime data 13 | pids 14 | *.pid 15 | *.seed 16 | *.pid.lock 17 | 18 | # Directory for instrumented libs generated by jscoverage/JSCover 19 | lib-cov 20 | 21 | # Coverage directory used by tools like istanbul 22 | coverage 23 | *.lcov 24 | 25 | # nyc test coverage 26 | .nyc_output 27 | 28 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 29 | .grunt 30 | 31 | # Bower dependency directory (https://bower.io/) 32 | bower_components 33 | 34 | # node-waf configuration 35 | .lock-wscript 36 | 37 | # Compiled binary addons (https://nodejs.org/api/addons.html) 38 | build/Release 39 | 40 | # Dependency directories 41 | node_modules/ 42 | jspm_packages/ 43 | 44 | # Snowpack dependency directory (https://snowpack.dev/) 45 | web_modules/ 46 | 47 | # TypeScript cache 48 | *.tsbuildinfo 49 | 50 | # Optional npm cache directory 51 | .npm 52 | 53 | # Optional eslint cache 54 | .eslintcache 55 | 56 | # Microbundle cache 57 | .rpt2_cache/ 58 | .rts2_cache_cjs/ 59 | .rts2_cache_es/ 60 | .rts2_cache_umd/ 61 | 62 | # Optional REPL history 63 | .node_repl_history 64 | 65 | # Output of 'npm pack' 66 | *.tgz 67 | 68 | # Yarn Integrity file 69 | .yarn-integrity 70 | 71 | # dotenv environment variables file 72 | .env 73 | .env.test 74 | 75 | # parcel-bundler cache (https://parceljs.org/) 76 | .cache 77 | .parcel-cache 78 | 79 | # Next.js build output 80 | .next 81 | out 82 | 83 | # Nuxt.js build / generate output 84 | .nuxt 85 | dist 86 | 87 | # Gatsby files 88 | .cache/ 89 | # Comment in the public line in if your project uses Gatsby and not Next.js 90 | # https://nextjs.org/blog/next-9-1#public-directory-support 91 | # public 92 | 93 | # vuepress build output 94 | .vuepress/dist 95 | 96 | # Serverless directories 97 | .serverless/ 98 | 99 | # FuseBox cache 100 | .fusebox/ 101 | 102 | # DynamoDB Local files 103 | .dynamodb/ 104 | 105 | # TernJS port file 106 | .tern-port 107 | 108 | # Stores VSCode versions used for testing VSCode extensions 109 | .vscode-test 110 | 111 | # yarn v2 112 | .yarn/cache 113 | .yarn/unplugged 114 | .yarn/build-state.yml 115 | .yarn/install-state.gz 116 | .pnp.* 117 | -------------------------------------------------------------------------------- /nodejs/mongodb-local-connect/README.md: -------------------------------------------------------------------------------- 1 | # Setting up a local MongoDB connection in Node.js 2 | 3 | For step-by-step instructions, please visit the [blog post](https://attacomsian.com/blog/nodejs-mongodb-local-connection). 4 | -------------------------------------------------------------------------------- /nodejs/mongodb-local-connect/connect-mongo-client.js: -------------------------------------------------------------------------------- 1 | const MongoClient = require('mongodb').MongoClient; 2 | 3 | // Connect URL 4 | const url = 'mongodb://127.0.0.1:27017'; 5 | 6 | // Connec to MongoDB 7 | MongoClient.connect(url, { 8 | useNewUrlParser: true, 9 | useUnifiedTopology: true 10 | }, (err, client) => { 11 | if (err) { 12 | return console.log(err); 13 | } 14 | 15 | // Specify database you want to access 16 | const db = client.db('school'); 17 | 18 | console.log(`MongoDB Connected: ${url}`); 19 | 20 | // Create a collection 21 | const courses = db.collection('courses'); 22 | 23 | // Insert single document 24 | courses.insertOne({ name: 'Web Security' }, (err, result) => { }); 25 | 26 | // Insert multiple docoments 27 | courses.insertMany([ 28 | { name: 'Web Design' }, 29 | { name: 'Distributed Database' }, 30 | { name: 'Artificial Intelligence' } 31 | ], (err, results) => { }); 32 | 33 | // Find all documents 34 | courses.find().toArray((err, results) => { 35 | console.log(results); 36 | }); 37 | 38 | // Find single document 39 | courses.find({ name: 'Web Design' }).toArray((err, result) => { 40 | console.log(result); 41 | }); 42 | 43 | // Find first document 44 | courses.findOne({ name: 'Web Design' }, (err, result) => { 45 | console.log(result); 46 | }); 47 | 48 | // Update a document 49 | courses.updateOne({ name: 'Web Design' }, { $set: { name: 'Web Analytics' } }, 50 | (err, result) => { 51 | console.log(result); 52 | }); 53 | 54 | // Delete a document 55 | courses.deleteOne({ name: 'Distributed Database' }, (err, result) => { 56 | console.log(result); 57 | }); 58 | 59 | // Close connection 60 | // client.close(); 61 | }); -------------------------------------------------------------------------------- /nodejs/mongodb-local-connect/connect-mongoose.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose'); 2 | 3 | // Connect URL 4 | const url = 'mongodb://127.0.0.1:27017/school'; 5 | 6 | // Connect to MongoDB 7 | (async () => { 8 | try { 9 | await mongoose.connect(url, { 10 | useNewUrlParser: true, 11 | useUnifiedTopology: true, 12 | useFindAndModify: false, 13 | useCreateIndex: true 14 | }); 15 | console.log(`MongoDB Connected: ${url}`); 16 | } catch (err) { 17 | console.error(err); 18 | } 19 | })(); -------------------------------------------------------------------------------- /nodejs/mongodb-local-connect/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mongodb-local-connect", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "mongodb": "^3.6.3", 14 | "mongoose": "^5.11.6" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /nodejs/ses-nodejs/.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /build/ 3 | !gradle/wrapper/gradle-wrapper.jar 4 | 5 | ### STS ### 6 | .apt_generated 7 | .classpath 8 | .factorypath 9 | .project 10 | .settings 11 | .springBeans 12 | .sts4-cache 13 | 14 | ### IntelliJ IDEA ### 15 | .idea 16 | *.iws 17 | *.iml 18 | *.ipr 19 | /out/ 20 | 21 | ### NetBeans ### 22 | /nbproject/private/ 23 | /nbbuild/ 24 | /dist/ 25 | /nbdist/ 26 | /.nb-gradle/ 27 | 28 | ### Node ### 29 | node_modules 30 | -------------------------------------------------------------------------------- /nodejs/ses-nodejs/README.md: -------------------------------------------------------------------------------- 1 | # Sending Emails using Amazon SES in Node.js 2 | 3 | For step-by-step instructions, please visit the [blog post](https://attacomsian.com/blog/amazon-ses-integration-nodejs). 4 | -------------------------------------------------------------------------------- /nodejs/ses-nodejs/config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | 'aws': { 3 | 'key': 'YOUR_ACCESS_KEY', 4 | 'secret': 'YOUR_ACCESS_SECRET', 5 | 'ses': { 6 | 'from': { 7 | // replace with actual email address 8 | 'default': '"Example.com" ', 9 | }, 10 | // e.g. us-west-2 11 | 'region': 'YOUR_ACCESS_REGION' 12 | } 13 | } 14 | }; 15 | -------------------------------------------------------------------------------- /nodejs/ses-nodejs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ses-nodejs", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "aws-sdk": "^2.395.0", 14 | "body-parser": "^1.18.3", 15 | "express": "^4.16.4" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /nodejs/ses-nodejs/server.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const bodyParser = require('body-parser'); 3 | const app = express(); 4 | 5 | const sesClient = require('./ses-client'); 6 | 7 | app.use(bodyParser.urlencoded({ extended: false })); 8 | app.use(bodyParser.json()); 9 | 10 | app.get('/', (req, res) => { 11 | // call sesClient to send an email 12 | sesClient.sendEmail('user@example.com', "Hey! Welcome", "This is the body of email"); 13 | 14 | res.send('Email is sent!'); 15 | }); 16 | 17 | app.listen(3000, () => { 18 | console.log('App is listening on port 3000'); 19 | }); 20 | -------------------------------------------------------------------------------- /nodejs/ses-nodejs/ses-client.js: -------------------------------------------------------------------------------- 1 | const AWS = require('aws-sdk'); 2 | 3 | const config = require('./config'); // load configurations file 4 | 5 | AWS.config.update({ 6 | accessKeyId: config.aws.key, 7 | secretAccessKey: config.aws.secret, 8 | region: config.aws.ses.region 9 | }); 10 | 11 | const ses = new AWS.SES({apiVersion: '2010-12-01'}); 12 | 13 | const sendEmail = (to, subject, message, from) => { 14 | const params = { 15 | Destination: { 16 | ToAddresses: [to] 17 | }, 18 | Message: { 19 | Body: { 20 | Html: { 21 | Charset: 'UTF-8', 22 | Data: message 23 | }, 24 | /* replace Html attribute with the following if you want to send plain text emails. 25 | Text: { 26 | Charset: "UTF-8", 27 | Data: message 28 | } 29 | */ 30 | }, 31 | Subject: { 32 | Charset: 'UTF-8', 33 | Data: subject 34 | } 35 | }, 36 | ReturnPath: from ? from : config.aws.ses.from.default, 37 | Source: from ? from : config.aws.ses.from.default, 38 | }; 39 | 40 | ses.sendEmail(params, (err, data) => { 41 | if (err) { 42 | return console.log(err, err.stack); 43 | } else { 44 | console.log("Email sent.", data); 45 | } 46 | }); 47 | }; 48 | 49 | module.exports = {sendEmail}; 50 | -------------------------------------------------------------------------------- /nodejs/xml-to-json/.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /build/ 3 | !gradle/wrapper/gradle-wrapper.jar 4 | 5 | ### STS ### 6 | .apt_generated 7 | .classpath 8 | .factorypath 9 | .project 10 | .settings 11 | .springBeans 12 | .sts4-cache 13 | 14 | ### IntelliJ IDEA ### 15 | .idea 16 | *.iws 17 | *.iml 18 | *.ipr 19 | /out/ 20 | 21 | ### NetBeans ### 22 | /nbproject/private/ 23 | /nbbuild/ 24 | /dist/ 25 | /nbdist/ 26 | /.nb-gradle/ 27 | 28 | ### Node ### 29 | node_modules 30 | 31 | # Extras 32 | /uploads/ 33 | -------------------------------------------------------------------------------- /nodejs/xml-to-json/README.md: -------------------------------------------------------------------------------- 1 | # How to convert XML to JSON in Node.js 2 | 3 | For step-by-step instructions, please visit the [blog post](https://attacomsian.com/blog/nodejs-convert-xml-to-json). 4 | -------------------------------------------------------------------------------- /nodejs/xml-to-json/app-async.js: -------------------------------------------------------------------------------- 1 | const xml2js = require('xml2js'); 2 | const fs = require('fs'); 3 | 4 | // read XML from a file 5 | const xml = fs.readFileSync('user.xml'); 6 | 7 | // convert XML to JSON 8 | (async () => { 9 | try { 10 | const result = await xml2js.parseStringPromise(xml, { mergeAttrs: true }); 11 | 12 | // convert it to a JSON string 13 | const json = JSON.stringify(result, null, 4); 14 | 15 | // save JSON in a file 16 | fs.writeFileSync('user.json', json); 17 | 18 | } catch (err) { 19 | console.log(err); 20 | } 21 | })(); -------------------------------------------------------------------------------- /nodejs/xml-to-json/app-file.js: -------------------------------------------------------------------------------- 1 | const xml2js = require('xml2js'); 2 | const fs = require('fs'); 3 | 4 | // read XML from a file 5 | const xml = fs.readFileSync('user.xml'); 6 | 7 | // convert XML to JSON 8 | xml2js.parseString(xml, { mergeAttrs: true }, (err, result) => { 9 | if (err) { 10 | throw err; 11 | } 12 | 13 | // `result` is a JavaScript object 14 | // convert it to a JSON string 15 | const json = JSON.stringify(result, null, 4); 16 | 17 | // save JSON in a file 18 | fs.writeFileSync('user.json', json); 19 | 20 | }); -------------------------------------------------------------------------------- /nodejs/xml-to-json/app-promise.js: -------------------------------------------------------------------------------- 1 | const xml2js = require('xml2js'); 2 | const fs = require('fs'); 3 | 4 | // read XML from a file 5 | const xml = fs.readFileSync('user.xml'); 6 | 7 | // convert XML to JSON 8 | xml2js.parseStringPromise(xml, { mergeAttrs: true }) 9 | .then(result => { 10 | // convert it to a JSON string 11 | const json = JSON.stringify(result, null, 4); 12 | 13 | // save JSON in a file 14 | fs.writeFileSync('user.json', json); 15 | 16 | }).catch(err => console.log(err)); 17 | -------------------------------------------------------------------------------- /nodejs/xml-to-json/app.js: -------------------------------------------------------------------------------- 1 | const xml2js = require('xml2js'); 2 | const fs = require('fs'); 3 | 4 | // XML string to be parsed to JSON 5 | const xml = ` 6 | 7 | John Doe 8 | john.doe@example.com 9 | 10 | Member 11 | Admin 12 | 13 | true 14 | `; 15 | 16 | // convert XML to JSON 17 | xml2js.parseString(xml, { mergeAttrs: true }, (err, result) => { 18 | if (err) { 19 | throw err; 20 | } 21 | 22 | // `result` is a JavaScript object 23 | // convert it to a JSON string 24 | const json = JSON.stringify(result, null, 4); 25 | 26 | // save JSON in a file 27 | fs.writeFileSync('user.json', json); 28 | 29 | }); -------------------------------------------------------------------------------- /nodejs/xml-to-json/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "xml-to-json", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "sax": { 8 | "version": "1.2.4", 9 | "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", 10 | "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" 11 | }, 12 | "xml2js": { 13 | "version": "0.4.23", 14 | "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz", 15 | "integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==", 16 | "requires": { 17 | "sax": ">=0.6.0", 18 | "xmlbuilder": "~11.0.0" 19 | } 20 | }, 21 | "xmlbuilder": { 22 | "version": "11.0.1", 23 | "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", 24 | "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==" 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /nodejs/xml-to-json/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "xml-to-json", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "xml2js": "^0.4.23" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /nodejs/xml-to-json/user.json: -------------------------------------------------------------------------------- 1 | { 2 | "user": { 3 | "id": [ 4 | "1" 5 | ], 6 | "name": [ 7 | "John Doe" 8 | ], 9 | "email": [ 10 | "john.doe@example.com" 11 | ], 12 | "roles": [ 13 | { 14 | "role": [ 15 | "Member", 16 | "Admin" 17 | ] 18 | } 19 | ], 20 | "admin": [ 21 | "true" 22 | ] 23 | } 24 | } -------------------------------------------------------------------------------- /nodejs/xml-to-json/user.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | John Doe 4 | john.doe@example.com 5 | 6 | Member 7 | Admin 8 | 9 | true 10 | -------------------------------------------------------------------------------- /others/anchor-links/.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /build/ 3 | !gradle/wrapper/gradle-wrapper.jar 4 | 5 | ### STS ### 6 | .apt_generated 7 | .classpath 8 | .factorypath 9 | .project 10 | .settings 11 | .springBeans 12 | .sts4-cache 13 | 14 | ### IntelliJ IDEA ### 15 | .idea 16 | *.iws 17 | *.iml 18 | *.ipr 19 | /out/ 20 | 21 | ### NetBeans ### 22 | /nbproject/private/ 23 | /nbbuild/ 24 | /dist/ 25 | /nbdist/ 26 | /.nb-gradle/ 27 | 28 | ### Node ### 29 | node_modules 30 | -------------------------------------------------------------------------------- /others/anchor-links/README.md: -------------------------------------------------------------------------------- 1 | # Add Deep Anchor Links to Your Blog using JavaScript 2 | 3 | For step-by-step instructions, please visit the [blog post](https://attacomsian.com/blog/deep-anchor-links-javascript). 4 | -------------------------------------------------------------------------------- /others/axios-js/README.md: -------------------------------------------------------------------------------- 1 | # How to use Axios in JavaScript 2 | 3 | For step-by-step instructions, please visit the [blog post](https://attacomsian.com/blog/axios-javascript). 4 | -------------------------------------------------------------------------------- /others/axios-js/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Axios in JavaScript 6 | 7 | 8 |
9 |

Users

10 | 11 |
12 |
13 |

Create User

14 |
15 | 16 | 17 | 18 |
19 |
20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /others/axios-js/script.js: -------------------------------------------------------------------------------- 1 | const createLi = (user) => { 2 | const li = document.createElement('li'); 3 | // add user details to `li` 4 | li.textContent = `${user.id}: ${user.first_name} ${user.last_name}`; 5 | 6 | // attach onclick event 7 | li.onclick = e => deleteUser(li, user.id); 8 | 9 | return li; 10 | }; 11 | 12 | const appendToDOM = (users) => { 13 | const ul = document.querySelector('ul'); 14 | //iterate over all users 15 | users.map(user => { 16 | ul.appendChild(createLi(user)); 17 | }); 18 | }; 19 | 20 | const fetchUsers = () => { 21 | axios.get('https://reqres.in/api/users') 22 | .then(response => { 23 | const users = response.data.data; 24 | console.log(`GET list users`, users); 25 | // append to DOM 26 | appendToDOM(users); 27 | }) 28 | .catch(error => console.error(error)); 29 | }; 30 | 31 | fetchUsers(); 32 | 33 | // create a new user 34 | const createUser = (user) => { 35 | axios.post('https://reqres.in/api/users', user) 36 | .then(response => { 37 | const addedUser = response.data; 38 | console.log(`POST: user is added`, addedUser); 39 | // append to DOM 40 | appendToDOM([addedUser]); 41 | }) 42 | .catch(error => console.error(error)); 43 | }; 44 | 45 | // event listener for form submission 46 | const form = document.querySelector('form'); 47 | 48 | const formEvent = form.addEventListener('submit', event => { 49 | event.preventDefault(); 50 | 51 | const first_name = document.querySelector('#first_name').value; 52 | const last_name = document.querySelector('#last_name').value; 53 | 54 | const user = { first_name, last_name }; 55 | createUser(user); 56 | }); 57 | 58 | 59 | // delete a user 60 | const deleteUser = (elem, id) => { 61 | axios.delete(`https://reqres.in/api/users/${id}`) 62 | .then(response => { 63 | console.log(`DELETE: user is removed`, id); 64 | // remove elem from DOM 65 | elem.remove(); 66 | }) 67 | .catch(error => console.error(error)); 68 | }; -------------------------------------------------------------------------------- /spring-boot/console-app/.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /build/ 3 | !gradle/wrapper/gradle-wrapper.jar 4 | 5 | ### STS ### 6 | .apt_generated 7 | .classpath 8 | .factorypath 9 | .project 10 | .settings 11 | .springBeans 12 | .sts4-cache 13 | 14 | ### IntelliJ IDEA ### 15 | .idea 16 | *.iws 17 | *.iml 18 | *.ipr 19 | /out/ 20 | 21 | ### NetBeans ### 22 | /nbproject/private/ 23 | /nbbuild/ 24 | /dist/ 25 | /nbdist/ 26 | /.nb-gradle/ 27 | -------------------------------------------------------------------------------- /spring-boot/console-app/README.md: -------------------------------------------------------------------------------- 1 | # Spring Boot Console Application 2 | 3 | For step-by-step instructions, please visit the [blog post]( 4 | https://attacomsian.com/blog/spring-boot-console-application). 5 | -------------------------------------------------------------------------------- /spring-boot/console-app/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'org.springframework.boot' version '2.1.3.RELEASE' 3 | id 'java' 4 | } 5 | 6 | apply plugin: 'io.spring.dependency-management' 7 | 8 | group = 'com.attacomsian' 9 | version = '0.0.1-SNAPSHOT' 10 | sourceCompatibility = '1.8' 11 | 12 | repositories { 13 | mavenCentral() 14 | } 15 | 16 | dependencies { 17 | implementation 'org.springframework.boot:spring-boot-starter' 18 | } 19 | -------------------------------------------------------------------------------- /spring-boot/console-app/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/attacomsian/code-examples/e48ae7eb3ff05aeb5f47016fe8e44c6341e7d005/spring-boot/console-app/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /spring-boot/console-app/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.2.1-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /spring-boot/console-app/settings.gradle: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | repositories { 3 | gradlePluginPortal() 4 | } 5 | } 6 | rootProject.name = 'console-app' 7 | -------------------------------------------------------------------------------- /spring-boot/console-app/src/main/java/com/attacomsian/console/ConsoleApplication.java: -------------------------------------------------------------------------------- 1 | package com.attacomsian.console; 2 | 3 | import com.attacomsian.console.services.HelloService; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.boot.Banner; 6 | import org.springframework.boot.CommandLineRunner; 7 | import org.springframework.boot.SpringApplication; 8 | import org.springframework.boot.autoconfigure.SpringBootApplication; 9 | 10 | @SpringBootApplication 11 | public class ConsoleApplication implements CommandLineRunner { 12 | 13 | private HelloService helloService; 14 | 15 | public ConsoleApplication(HelloService helloService) { 16 | this.helloService = helloService; 17 | } 18 | 19 | public static void main(String[] args) { 20 | SpringApplication app = new SpringApplication(ConsoleApplication.class); 21 | // disable spring banner 22 | app.setBannerMode(Banner.Mode.OFF); 23 | app.run(args); 24 | } 25 | 26 | @Override 27 | public void run(String... args) throws Exception { 28 | //check if user passes any argument 29 | if (args.length > 0) { 30 | System.out.println(helloService.getMessage(args[0])); 31 | } else { 32 | //print the default message 33 | System.out.println(helloService.getMessage()); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /spring-boot/console-app/src/main/java/com/attacomsian/console/services/HelloService.java: -------------------------------------------------------------------------------- 1 | package com.attacomsian.console.services; 2 | 3 | import org.springframework.beans.factory.annotation.Value; 4 | import org.springframework.stereotype.Service; 5 | 6 | @Service 7 | public class HelloService { 8 | 9 | @Value("${message.default}") 10 | private String message; 11 | 12 | public String getMessage() { 13 | return message; 14 | } 15 | 16 | public String getMessage(String message) { 17 | return "Hey, " + message; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /spring-boot/console-app/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | message.default=attacomsian.com 2 | 3 | # disable embedded web server - alternative way 4 | spring.main.web-application-type=none 5 | spring.main.banner-mode=off -------------------------------------------------------------------------------- /spring-boot/cookies/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | .gradle 3 | /build/ 4 | !gradle/wrapper/gradle-wrapper.jar 5 | 6 | ### STS ### 7 | .apt_generated 8 | .classpath 9 | .factorypath 10 | .project 11 | .settings 12 | .springBeans 13 | .sts4-cache 14 | 15 | ### IntelliJ IDEA ### 16 | .idea 17 | *.iws 18 | *.iml 19 | *.ipr 20 | /out/ 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | 29 | ### VS Code ### 30 | .vscode/ 31 | -------------------------------------------------------------------------------- /spring-boot/cookies/README.md: -------------------------------------------------------------------------------- 1 | # How to Use Cookies in Spring Boot 2 | 3 | For step-by-step instructions, please check out the [blog post](https://attacomsian.com/blog/cookies-spring-boot). 4 | -------------------------------------------------------------------------------- /spring-boot/cookies/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'org.springframework.boot' version '2.1.4.RELEASE' 3 | id 'java' 4 | } 5 | 6 | apply plugin: 'io.spring.dependency-management' 7 | 8 | group = 'com.attacomsian' 9 | version = '0.0.1-SNAPSHOT' 10 | sourceCompatibility = '1.8' 11 | 12 | repositories { 13 | mavenCentral() 14 | } 15 | 16 | dependencies { 17 | implementation 'org.springframework.boot:spring-boot-starter-web' 18 | } 19 | -------------------------------------------------------------------------------- /spring-boot/cookies/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/attacomsian/code-examples/e48ae7eb3ff05aeb5f47016fe8e44c6341e7d005/spring-boot/cookies/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /spring-boot/cookies/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.2.1-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /spring-boot/cookies/settings.gradle: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | repositories { 3 | gradlePluginPortal() 4 | } 5 | } 6 | rootProject.name = 'cookies' 7 | -------------------------------------------------------------------------------- /spring-boot/cookies/src/main/java/com/attacomsian/cookies/Application.java: -------------------------------------------------------------------------------- 1 | package com.attacomsian.cookies; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class Application { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(Application.class, args); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /spring-boot/cookies/src/main/java/com/attacomsian/cookies/controllers/CookieController.java: -------------------------------------------------------------------------------- 1 | package com.attacomsian.cookies.controllers; 2 | 3 | import org.springframework.web.bind.annotation.CookieValue; 4 | import org.springframework.web.bind.annotation.GetMapping; 5 | import org.springframework.web.bind.annotation.RestController; 6 | 7 | import javax.servlet.http.Cookie; 8 | import javax.servlet.http.HttpServletRequest; 9 | import javax.servlet.http.HttpServletResponse; 10 | import java.util.Arrays; 11 | import java.util.stream.Collectors; 12 | 13 | @RestController 14 | public class CookieController { 15 | 16 | @GetMapping("/") 17 | public String readCookie(@CookieValue(value = "username", defaultValue = "Atta") String username) { 18 | return "Hey! My username is " + username; 19 | } 20 | 21 | @GetMapping("/change-username") 22 | public String setCookie(HttpServletResponse response) { 23 | 24 | // create a cookie 25 | Cookie cookie = new Cookie("username", "Jovan"); 26 | cookie.setMaxAge(7 * 24 * 60 * 60); // 7 days 27 | cookie.setSecure(true); 28 | cookie.setHttpOnly(true); 29 | cookie.setPath("/"); // global cookie accessible every where 30 | 31 | //add cookie to response 32 | response.addCookie(cookie); 33 | 34 | return "Username is changed!"; 35 | } 36 | 37 | @GetMapping("/delete-username") 38 | public String deleteCookie(HttpServletResponse response) { 39 | 40 | // create a cookie 41 | Cookie cookie = new Cookie("username", null); 42 | cookie.setMaxAge(0); 43 | cookie.setSecure(true); 44 | cookie.setHttpOnly(true); 45 | cookie.setPath("/"); 46 | 47 | //add cookie to response 48 | response.addCookie(cookie); 49 | 50 | return "Username is deleted!"; 51 | } 52 | 53 | @GetMapping("/all-cookies") 54 | public String readAllCookies(HttpServletRequest request) { 55 | 56 | Cookie[] cookies = request.getCookies(); 57 | if (cookies != null) { 58 | return Arrays.stream(cookies) 59 | .map(c -> c.getName() + "=" + c.getValue()).collect(Collectors.joining(", ")); 60 | } 61 | 62 | return "No cookies"; 63 | } 64 | } -------------------------------------------------------------------------------- /spring-boot/cookies/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /spring-boot/export-data-csv/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | .gradle 3 | /build/ 4 | !gradle/wrapper/gradle-wrapper.jar 5 | 6 | ### STS ### 7 | .apt_generated 8 | .classpath 9 | .factorypath 10 | .project 11 | .settings 12 | .springBeans 13 | .sts4-cache 14 | 15 | ### IntelliJ IDEA ### 16 | .idea 17 | *.iws 18 | *.iml 19 | *.ipr 20 | /out/ 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | 29 | ### VS Code ### 30 | .vscode/ 31 | -------------------------------------------------------------------------------- /spring-boot/export-data-csv/README.md: -------------------------------------------------------------------------------- 1 | # Export & Download Data as CSV File in Spring Boot 2 | 3 | For step-by-step instructions, please visit the [blog post]( 4 | https://attacomsian.com/blog/export-download-data-csv-file-spring-boot). 5 | -------------------------------------------------------------------------------- /spring-boot/export-data-csv/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'org.springframework.boot' version '2.1.3.RELEASE' 3 | id 'java' 4 | } 5 | 6 | apply plugin: 'io.spring.dependency-management' 7 | 8 | group = 'com.attacomsian' 9 | version = '0.0.1-SNAPSHOT' 10 | sourceCompatibility = '1.8' 11 | 12 | repositories { 13 | mavenCentral() 14 | } 15 | 16 | dependencies { 17 | implementation 'org.springframework.boot:spring-boot-starter-web' 18 | implementation 'com.opencsv:opencsv:4.5' 19 | } 20 | -------------------------------------------------------------------------------- /spring-boot/export-data-csv/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/attacomsian/code-examples/e48ae7eb3ff05aeb5f47016fe8e44c6341e7d005/spring-boot/export-data-csv/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /spring-boot/export-data-csv/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.2.1-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /spring-boot/export-data-csv/settings.gradle: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | repositories { 3 | gradlePluginPortal() 4 | } 5 | } 6 | rootProject.name = 'export-data-csv' 7 | -------------------------------------------------------------------------------- /spring-boot/export-data-csv/src/main/java/com/attacomsian/exportcsv/Application.java: -------------------------------------------------------------------------------- 1 | package com.attacomsian.exportcsv; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class Application { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(Application.class, args); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /spring-boot/export-data-csv/src/main/java/com/attacomsian/exportcsv/controllers/UserController.java: -------------------------------------------------------------------------------- 1 | package com.attacomsian.exportcsv.controllers; 2 | 3 | import com.attacomsian.exportcsv.data.User; 4 | import com.attacomsian.exportcsv.data.UserService; 5 | import com.opencsv.CSVWriter; 6 | import com.opencsv.bean.ColumnPositionMappingStrategy; 7 | import com.opencsv.bean.StatefulBeanToCsv; 8 | import com.opencsv.bean.StatefulBeanToCsvBuilder; 9 | import org.springframework.http.HttpHeaders; 10 | import org.springframework.stereotype.Controller; 11 | import org.springframework.web.bind.annotation.GetMapping; 12 | 13 | import javax.servlet.http.HttpServletResponse; 14 | 15 | @Controller 16 | public class UserController { 17 | 18 | private UserService userService; 19 | 20 | public UserController(UserService userService) { 21 | this.userService = userService; 22 | } 23 | 24 | @GetMapping("/export-users") 25 | public void exportCSV(HttpServletResponse response) throws Exception { 26 | 27 | //set file name and content type 28 | String filename = "users.csv"; 29 | 30 | response.setContentType("text/csv"); 31 | response.setHeader(HttpHeaders.CONTENT_DISPOSITION, 32 | "attachment; filename=\"" + filename + "\""); 33 | 34 | //create a csv writer 35 | StatefulBeanToCsv writer = new StatefulBeanToCsvBuilder(response.getWriter()) 36 | .withQuotechar(CSVWriter.NO_QUOTE_CHARACTER) 37 | .withSeparator(CSVWriter.DEFAULT_SEPARATOR) 38 | .withOrderedResults(false) 39 | .build(); 40 | 41 | //write all users to csv file 42 | writer.write(userService.listUsers()); 43 | 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /spring-boot/export-data-csv/src/main/java/com/attacomsian/exportcsv/data/User.java: -------------------------------------------------------------------------------- 1 | package com.attacomsian.exportcsv.data; 2 | 3 | import com.opencsv.bean.CsvBindByPosition; 4 | 5 | public class User { 6 | 7 | // Enable columns positions if you want to 8 | // have your customs order. 9 | 10 | // @CsvBindByPosition(position = 0) 11 | private long id; 12 | // @CsvBindByPosition(position = 1) 13 | private String name; 14 | // @CsvBindByPosition(position = 2) 15 | private String email; 16 | // @CsvBindByPosition(position = 3) 17 | private String country; 18 | // @CsvBindByPosition(position = 4) 19 | private int age; 20 | 21 | public User(long id, String name, String email, String country, int age) { 22 | this.id = id; 23 | this.name = name; 24 | this.email = email; 25 | this.country = country; 26 | this.age = age; 27 | } 28 | 29 | public long getId() { 30 | return id; 31 | } 32 | 33 | public void setId(long id) { 34 | this.id = id; 35 | } 36 | 37 | public String getName() { 38 | return name; 39 | } 40 | 41 | public void setName(String name) { 42 | this.name = name; 43 | } 44 | 45 | public String getEmail() { 46 | return email; 47 | } 48 | 49 | public void setEmail(String email) { 50 | this.email = email; 51 | } 52 | 53 | public String getCountry() { 54 | return country; 55 | } 56 | 57 | public void setCountry(String country) { 58 | this.country = country; 59 | } 60 | 61 | public int getAge() { 62 | return age; 63 | } 64 | 65 | public void setAge(int age) { 66 | this.age = age; 67 | } 68 | 69 | @Override 70 | public String toString() { 71 | return "User{" + 72 | "id=" + id + 73 | ", name='" + name + '\'' + 74 | ", email='" + email + '\'' + 75 | ", country='" + country + '\'' + 76 | ", age=" + age + 77 | '}'; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /spring-boot/export-data-csv/src/main/java/com/attacomsian/exportcsv/data/UserService.java: -------------------------------------------------------------------------------- 1 | package com.attacomsian.exportcsv.data; 2 | 3 | import org.springframework.stereotype.Service; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | @Service 9 | public class UserService { 10 | 11 | public List listUsers() { 12 | List users = new ArrayList<>(); 13 | 14 | //create dummy users 15 | users.add(new User(1, "Jack Lee", "jack@example.com", "Germany", 35)); 16 | users.add(new User(2, "Jovan Srovoki", "jovan@srovoki.me", "Russia", 21)); 17 | users.add(new User(3, "Atta", "atta@gmail.com", "Pakistan", 29)); 18 | 19 | return users; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /spring-boot/export-data-csv/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /spring-boot/jackson/.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /build/ 3 | !gradle/wrapper/gradle-wrapper.jar 4 | 5 | ### STS ### 6 | .apt_generated 7 | .classpath 8 | .factorypath 9 | .project 10 | .settings 11 | .springBeans 12 | .sts4-cache 13 | 14 | ### IntelliJ IDEA ### 15 | .idea 16 | *.iws 17 | *.iml 18 | *.ipr 19 | /out/ 20 | 21 | ### NetBeans ### 22 | /nbproject/private/ 23 | /nbbuild/ 24 | /dist/ 25 | /nbdist/ 26 | /.nb-gradle/ 27 | -------------------------------------------------------------------------------- /spring-boot/jackson/README.md: -------------------------------------------------------------------------------- 1 | # Processing JSON Data in Spring Boot 2 | 3 | A comprehensive guide on how to use Jackson library to processing JSON data in Spring Boot. 4 | 5 | For step-by-step instructions, please visit the [blog post]( 6 | https://attacomsian.com/blog/processing-json-spring-boot). 7 | -------------------------------------------------------------------------------- /spring-boot/jackson/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'org.springframework.boot' version '2.1.3.RELEASE' 3 | id 'java' 4 | } 5 | 6 | apply plugin: 'io.spring.dependency-management' 7 | 8 | group = 'com.attacomsian' 9 | version = '0.0.1-SNAPSHOT' 10 | sourceCompatibility = '1.8' 11 | 12 | repositories { 13 | mavenCentral() 14 | } 15 | 16 | dependencies { 17 | implementation 'org.springframework.boot:spring-boot-starter' 18 | 19 | //include jackson databind dependency 20 | implementation 'com.fasterxml.jackson.core:jackson-databind:2.9.8' 21 | 22 | testImplementation 'org.springframework.boot:spring-boot-starter-test' 23 | } 24 | -------------------------------------------------------------------------------- /spring-boot/jackson/customer.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 123, 3 | "name": "Jovan Lee", 4 | "email": "jovan@example.com", 5 | "phone": "+49 176 14890478", 6 | "age": 32, 7 | "projects": [ 8 | "Remote Job Board", 9 | "Data Migration" 10 | ], 11 | "address": { 12 | "street": "Yorckstr. 75", 13 | "city": "Berlin", 14 | "zipcode": 10965, 15 | "country": "Germany" 16 | }, 17 | "paymentMethods": [ 18 | "PayPal", 19 | "Stripe" 20 | ], 21 | "profileInfo": { 22 | "gender": "Male", 23 | "married": "Yes", 24 | "source": "LinkedIn" 25 | } 26 | } -------------------------------------------------------------------------------- /spring-boot/jackson/customer2.json: -------------------------------------------------------------------------------- 1 | { 2 | "id" : 567, 3 | "name" : "Maria Kovosi", 4 | "email" : "maria@example.com", 5 | "phone" : "+12 785 4895 321", 6 | "age" : 29, 7 | "projects" : [ "Path Finder App", "Push Notifications" ], 8 | "address" : { 9 | "street" : "Karchstr.", 10 | "city" : "Hanover", 11 | "zipcode" : 66525, 12 | "country" : "Germany" 13 | }, 14 | "paymentMethods" : [ "PayPal", "SOFORT" ], 15 | "profileInfo" : { 16 | "income" : "120,000 EURO", 17 | "gender" : "female", 18 | "source" : "Google Search", 19 | "married" : "No" 20 | } 21 | } -------------------------------------------------------------------------------- /spring-boot/jackson/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/attacomsian/code-examples/e48ae7eb3ff05aeb5f47016fe8e44c6341e7d005/spring-boot/jackson/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /spring-boot/jackson/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.2.1-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /spring-boot/jackson/settings.gradle: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | repositories { 3 | gradlePluginPortal() 4 | } 5 | } 6 | rootProject.name = 'jackson' 7 | -------------------------------------------------------------------------------- /spring-boot/jackson/src/main/java/com/attacomsian/jackson/Address.java: -------------------------------------------------------------------------------- 1 | package com.attacomsian.jackson; 2 | 3 | public class Address { 4 | 5 | private String street; 6 | private String city; 7 | private int zipcode; 8 | private String country; 9 | 10 | public String getStreet() { 11 | return street; 12 | } 13 | 14 | public void setStreet(String street) { 15 | this.street = street; 16 | } 17 | 18 | public String getCity() { 19 | return city; 20 | } 21 | 22 | public void setCity(String city) { 23 | this.city = city; 24 | } 25 | 26 | public int getZipcode() { 27 | return zipcode; 28 | } 29 | 30 | public void setZipcode(int zipcode) { 31 | this.zipcode = zipcode; 32 | } 33 | 34 | public String getCountry() { 35 | return country; 36 | } 37 | 38 | public void setCountry(String country) { 39 | this.country = country; 40 | } 41 | 42 | @Override 43 | public String toString() { 44 | return "{" + 45 | "street='" + street + '\'' + 46 | ", city='" + city + '\'' + 47 | ", zipcode=" + zipcode + 48 | ", country='" + country + '\'' + 49 | '}'; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /spring-boot/parse-data-csv/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | .gradle 3 | build/ 4 | !gradle/wrapper/gradle-wrapper.jar 5 | !**/src/main/** 6 | !**/src/test/** 7 | 8 | ### STS ### 9 | .apt_generated 10 | .classpath 11 | .factorypath 12 | .project 13 | .settings 14 | .springBeans 15 | .sts4-cache 16 | 17 | ### IntelliJ IDEA ### 18 | .idea 19 | *.iws 20 | *.iml 21 | *.ipr 22 | out/ 23 | 24 | ### NetBeans ### 25 | /nbproject/private/ 26 | /nbbuild/ 27 | /dist/ 28 | /nbdist/ 29 | /.nb-gradle/ 30 | 31 | ### VS Code ### 32 | .vscode/ 33 | -------------------------------------------------------------------------------- /spring-boot/parse-data-csv/README.md: -------------------------------------------------------------------------------- 1 | # Uploading and Parsing CSV File using Spring Boot 2 | 3 | For step-by-step instructions, please check out [blog post](https://attacomsian.com/blog/spring-boot-upload-parse-csv-file). 4 | -------------------------------------------------------------------------------- /spring-boot/parse-data-csv/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'org.springframework.boot' version '2.2.3.RELEASE' 3 | id 'io.spring.dependency-management' version '1.0.8.RELEASE' 4 | id 'java' 5 | } 6 | 7 | group = 'com.attacomsian' 8 | version = '0.0.1-SNAPSHOT' 9 | sourceCompatibility = '1.8' 10 | 11 | repositories { 12 | mavenCentral() 13 | } 14 | 15 | dependencies { 16 | implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' 17 | implementation 'org.springframework.boot:spring-boot-starter-web' 18 | implementation 'com.opencsv:opencsv:5.0' 19 | 20 | testImplementation('org.springframework.boot:spring-boot-starter-test') { 21 | exclude group: 'org.junit.vintage', module: 'junit-vintage-engine' 22 | } 23 | } 24 | 25 | test { 26 | useJUnitPlatform() 27 | } -------------------------------------------------------------------------------- /spring-boot/parse-data-csv/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/attacomsian/code-examples/e48ae7eb3ff05aeb5f47016fe8e44c6341e7d005/spring-boot/parse-data-csv/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /spring-boot/parse-data-csv/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.0.1-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /spring-boot/parse-data-csv/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'parse-data-csv' 2 | -------------------------------------------------------------------------------- /spring-boot/parse-data-csv/src/main/java/com/attacomsian/parsecsv/Application.java: -------------------------------------------------------------------------------- 1 | package com.attacomsian.parsecsv; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class Application { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(Application.class, args); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /spring-boot/parse-data-csv/src/main/java/com/attacomsian/parsecsv/controllers/UploadController.java: -------------------------------------------------------------------------------- 1 | package com.attacomsian.parsecsv.controllers; 2 | 3 | import com.attacomsian.parsecsv.domains.User; 4 | import com.opencsv.bean.CsvToBean; 5 | import com.opencsv.bean.CsvToBeanBuilder; 6 | import org.springframework.stereotype.Controller; 7 | import org.springframework.ui.Model; 8 | import org.springframework.web.bind.annotation.GetMapping; 9 | import org.springframework.web.bind.annotation.PostMapping; 10 | import org.springframework.web.bind.annotation.RequestParam; 11 | import org.springframework.web.multipart.MultipartFile; 12 | 13 | import java.io.BufferedReader; 14 | import java.io.InputStreamReader; 15 | import java.io.Reader; 16 | import java.util.List; 17 | 18 | @Controller 19 | public class UploadController { 20 | 21 | @GetMapping("/") 22 | public String index() { 23 | return "index"; 24 | } 25 | 26 | @PostMapping("/upload-csv-file") 27 | public String uploadCSVFile(@RequestParam("file") MultipartFile file, Model model) { 28 | 29 | // validate file 30 | if (file.isEmpty()) { 31 | model.addAttribute("message", "Please select a CSV file to upload."); 32 | model.addAttribute("status", false); 33 | } else { 34 | 35 | // parse CSV file to create a list of `User` objects 36 | try (Reader reader = new BufferedReader(new InputStreamReader(file.getInputStream()))) { 37 | 38 | // create csv bean reader 39 | CsvToBean csvToBean = new CsvToBeanBuilder(reader) 40 | .withType(User.class) 41 | .withIgnoreLeadingWhiteSpace(true) 42 | .build(); 43 | 44 | // convert `CsvToBean` object to list of users 45 | List users = csvToBean.parse(); 46 | 47 | // TODO: save users in DB? 48 | 49 | // save users list on model 50 | model.addAttribute("users", users); 51 | model.addAttribute("status", true); 52 | 53 | } catch (Exception ex) { 54 | model.addAttribute("message", "An error occurred while processing the CSV file."); 55 | model.addAttribute("status", false); 56 | } 57 | } 58 | 59 | return "file-upload-status"; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /spring-boot/parse-data-csv/src/main/java/com/attacomsian/parsecsv/domains/User.java: -------------------------------------------------------------------------------- 1 | package com.attacomsian.parsecsv.domains; 2 | 3 | import com.opencsv.bean.CsvBindByName; 4 | 5 | public class User { 6 | 7 | @CsvBindByName 8 | private long id; 9 | @CsvBindByName 10 | private String name; 11 | @CsvBindByName 12 | private String email; 13 | @CsvBindByName(column = "country") 14 | private String countryCode; 15 | @CsvBindByName 16 | private int age; 17 | 18 | public User() { 19 | } 20 | 21 | public User(long id, String name, String email, String countryCode, int age) { 22 | this.id = id; 23 | this.name = name; 24 | this.email = email; 25 | this.countryCode = countryCode; 26 | this.age = age; 27 | } 28 | 29 | public long getId() { 30 | return id; 31 | } 32 | 33 | public void setId(long id) { 34 | this.id = id; 35 | } 36 | 37 | public String getName() { 38 | return name; 39 | } 40 | 41 | public void setName(String name) { 42 | this.name = name; 43 | } 44 | 45 | public String getEmail() { 46 | return email; 47 | } 48 | 49 | public void setEmail(String email) { 50 | this.email = email; 51 | } 52 | 53 | public String getCountryCode() { 54 | return countryCode; 55 | } 56 | 57 | public void setCountryCode(String countryCode) { 58 | this.countryCode = countryCode; 59 | } 60 | 61 | public int getAge() { 62 | return age; 63 | } 64 | 65 | public void setAge(int age) { 66 | this.age = age; 67 | } 68 | 69 | @Override 70 | public String toString() { 71 | return "User{" + 72 | "id=" + id + 73 | ", name='" + name + '\'' + 74 | ", email='" + email + '\'' + 75 | ", countryCode='" + countryCode + '\'' + 76 | ", age=" + age + 77 | '}'; 78 | } 79 | } 80 | 81 | -------------------------------------------------------------------------------- /spring-boot/parse-data-csv/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /spring-boot/parse-data-csv/src/main/resources/templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Upload CSV File Example 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 |
15 |
16 |

Upload CSV File Example

17 |
18 |
19 | 20 | 21 |
22 | 23 |
24 |
25 |
26 |
27 | 28 | 29 | -------------------------------------------------------------------------------- /spring-boot/parse-data-csv/users.csv: -------------------------------------------------------------------------------- 1 | id,name,email,country,age 2 | 100,Atta Shah,atta@example.com,PK,30 3 | 101,Alex Jones,alex@example.com,DE,35 4 | 102,Jovan Lee,jovan@example.com,FR,25 5 | 103,Greg Hover,greg@example.com,US,45 -------------------------------------------------------------------------------- /spring-boot/rest-template/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | .gradle 3 | build/ 4 | !gradle/wrapper/gradle-wrapper.jar 5 | !**/src/main/** 6 | !**/src/test/** 7 | 8 | ### STS ### 9 | .apt_generated 10 | .classpath 11 | .factorypath 12 | .project 13 | .settings 14 | .springBeans 15 | .sts4-cache 16 | 17 | ### IntelliJ IDEA ### 18 | .idea 19 | *.iws 20 | *.iml 21 | *.ipr 22 | out/ 23 | 24 | ### NetBeans ### 25 | /nbproject/private/ 26 | /nbbuild/ 27 | /dist/ 28 | /nbdist/ 29 | /.nb-gradle/ 30 | 31 | ### VS Code ### 32 | .vscode/ 33 | -------------------------------------------------------------------------------- /spring-boot/rest-template/README.md: -------------------------------------------------------------------------------- 1 | # Making HTTP Requests using RestTemplate in Spring Boot 2 | 3 | For step-by-step instructions, please check out [blog post](https://attacomsian.com/blog/http-requests-resttemplate-spring-boot). 4 | -------------------------------------------------------------------------------- /spring-boot/rest-template/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'org.springframework.boot' version '2.1.6.RELEASE' 3 | id 'java' 4 | } 5 | 6 | apply plugin: 'io.spring.dependency-management' 7 | 8 | group = 'com.attacomsian' 9 | version = '0.0.1-SNAPSHOT' 10 | sourceCompatibility = '1.8' 11 | 12 | repositories { 13 | mavenCentral() 14 | } 15 | 16 | dependencies { 17 | implementation 'org.springframework.boot:spring-boot-starter-web' 18 | } 19 | -------------------------------------------------------------------------------- /spring-boot/rest-template/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/attacomsian/code-examples/e48ae7eb3ff05aeb5f47016fe8e44c6341e7d005/spring-boot/rest-template/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /spring-boot/rest-template/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /spring-boot/rest-template/settings.gradle: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | repositories { 3 | gradlePluginPortal() 4 | } 5 | } 6 | rootProject.name = 'rest-template' 7 | -------------------------------------------------------------------------------- /spring-boot/rest-template/src/main/java/com/attacomsian/rest/Application.java: -------------------------------------------------------------------------------- 1 | package com.attacomsian.rest; 2 | 3 | import com.attacomsian.rest.models.Post; 4 | import com.attacomsian.rest.services.RestService; 5 | import org.springframework.boot.CommandLineRunner; 6 | import org.springframework.boot.SpringApplication; 7 | import org.springframework.boot.autoconfigure.SpringBootApplication; 8 | import org.springframework.http.HttpMethod; 9 | import org.springframework.http.MediaType; 10 | 11 | @SpringBootApplication 12 | public class Application implements CommandLineRunner { 13 | 14 | private RestService restService; 15 | 16 | public Application(RestService restService) { 17 | this.restService = restService; 18 | } 19 | 20 | public static void main(String[] args) { 21 | SpringApplication.run(Application.class, args); 22 | } 23 | 24 | @Override 25 | public void run(String... args) throws Exception { 26 | 27 | // fetch posts as plain JSON 28 | // System.out.println(restService.getPostsPlainJSON()); 29 | 30 | // fetch posts as object 31 | // for (Post post: restService.getPostsAsObject()) { 32 | // System.out.println(post); 33 | // } 34 | 35 | // fetch post with url parameter 36 | // System.out.println(restService.getPostWithUrlParameters()); 37 | 38 | // fetch post with response handling 39 | // System.out.println(restService.getPostWithResponseHandling()); 40 | 41 | // fetch post with response handling 42 | // System.out.println(restService.getPostWithCustomHeaders()); 43 | 44 | // create a new post 45 | // System.out.println(restService.createPost()); 46 | 47 | // create a new post with object 48 | // System.out.println(restService.createPostWithObject()); 49 | 50 | // update post 51 | // restService.updatePost(); 52 | 53 | // update post with response handling 54 | // System.out.println(restService.updatePostWithResponse()); 55 | 56 | // delete post 57 | // restService.deletePost(); 58 | 59 | // retrieve headers 60 | // System.out.println(restService.retrieveHeaders().getCacheControl()); 61 | 62 | // list allowed operations 63 | // for (HttpMethod method : restService.allowedOperations()) { 64 | // System.out.println(method.name()); 65 | // } 66 | 67 | // get request with error handling 68 | System.out.println(restService.unknownRequest()); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /spring-boot/rest-template/src/main/java/com/attacomsian/rest/models/Post.java: -------------------------------------------------------------------------------- 1 | package com.attacomsian.rest.models; 2 | 3 | import java.io.Serializable; 4 | 5 | public class Post implements Serializable { 6 | 7 | private int userId; 8 | private int id; 9 | private String title; 10 | private String body; 11 | 12 | public Post() {} 13 | 14 | public Post(int userId, String title, String body) { 15 | this.userId = userId; 16 | this.title = title; 17 | this.body = body; 18 | } 19 | 20 | public int getUserId() { 21 | return userId; 22 | } 23 | 24 | public void setUserId(int userId) { 25 | this.userId = userId; 26 | } 27 | 28 | public int getId() { 29 | return id; 30 | } 31 | 32 | public void setId(int id) { 33 | this.id = id; 34 | } 35 | 36 | public String getTitle() { 37 | return title; 38 | } 39 | 40 | public void setTitle(String title) { 41 | this.title = title; 42 | } 43 | 44 | public String getBody() { 45 | return body; 46 | } 47 | 48 | public void setBody(String body) { 49 | this.body = body; 50 | } 51 | 52 | @Override 53 | public String toString() { 54 | return "Post{" + 55 | "userId=" + userId + 56 | ", id=" + id + 57 | ", title='" + title + '\'' + 58 | ", body='" + body + '\'' + 59 | '}'; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /spring-boot/rest-template/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /spring-boot/scheduling/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | .gradle 3 | build/ 4 | !gradle/wrapper/gradle-wrapper.jar 5 | !**/src/main/** 6 | !**/src/test/** 7 | 8 | ### STS ### 9 | .apt_generated 10 | .classpath 11 | .factorypath 12 | .project 13 | .settings 14 | .springBeans 15 | .sts4-cache 16 | 17 | ### IntelliJ IDEA ### 18 | .idea 19 | *.iws 20 | *.iml 21 | *.ipr 22 | out/ 23 | 24 | ### NetBeans ### 25 | /nbproject/private/ 26 | /nbbuild/ 27 | /dist/ 28 | /nbdist/ 29 | /.nb-gradle/ 30 | 31 | ### VS Code ### 32 | .vscode/ 33 | -------------------------------------------------------------------------------- /spring-boot/scheduling/README.md: -------------------------------------------------------------------------------- 1 | # Task Scheduling in Spring Boot 2 | 3 | For step-by-step instructions, please check out [blog post](https://attacomsian.com/blog/task-scheduling-spring-boot). 4 | -------------------------------------------------------------------------------- /spring-boot/scheduling/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'org.springframework.boot' version '2.1.7.RELEASE' 3 | id 'io.spring.dependency-management' version '1.0.8.RELEASE' 4 | id 'java' 5 | } 6 | 7 | group = 'com.attacomsian' 8 | version = '0.0.1-SNAPSHOT' 9 | sourceCompatibility = '1.8' 10 | 11 | repositories { 12 | mavenCentral() 13 | } 14 | 15 | dependencies { 16 | implementation 'org.springframework.boot:spring-boot-starter' 17 | } 18 | -------------------------------------------------------------------------------- /spring-boot/scheduling/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/attacomsian/code-examples/e48ae7eb3ff05aeb5f47016fe8e44c6341e7d005/spring-boot/scheduling/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /spring-boot/scheduling/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /spring-boot/scheduling/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'scheduling' 2 | -------------------------------------------------------------------------------- /spring-boot/scheduling/src/main/java/com/attacomsian/scheduling/Application.java: -------------------------------------------------------------------------------- 1 | package com.attacomsian.scheduling; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.scheduling.annotation.EnableScheduling; 6 | 7 | @SpringBootApplication 8 | @EnableScheduling 9 | public class Application { 10 | 11 | public static void main(String[] args) { 12 | SpringApplication.run(Application.class, args); 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /spring-boot/scheduling/src/main/java/com/attacomsian/scheduling/SchedulerConfig.java: -------------------------------------------------------------------------------- 1 | package com.attacomsian.scheduling; 2 | 3 | import org.springframework.beans.factory.annotation.Value; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.scheduling.annotation.SchedulingConfigurer; 6 | import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; 7 | import org.springframework.scheduling.config.ScheduledTaskRegistrar; 8 | 9 | @Configuration 10 | public class SchedulerConfig implements SchedulingConfigurer { 11 | 12 | @Value("${thread.pool.size}") 13 | private int POOL_SIZE; 14 | 15 | @Override 16 | public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { 17 | ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler(); 18 | 19 | scheduler.setPoolSize(POOL_SIZE); 20 | scheduler.setThreadNamePrefix("My-Scheduler-"); 21 | scheduler.initialize(); 22 | 23 | taskRegistrar.setTaskScheduler(scheduler); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /spring-boot/scheduling/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | fixed-rate.in.milliseconds=5000 2 | fixed-delay.in.milliseconds=4000 3 | cron.expression=0 15 5 * * FRI 4 | thread.pool.size=10 -------------------------------------------------------------------------------- /spring-boot/ses-spring-boot/.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /build/ 3 | !gradle/wrapper/gradle-wrapper.jar 4 | 5 | ### STS ### 6 | .apt_generated 7 | .classpath 8 | .factorypath 9 | .project 10 | .settings 11 | .springBeans 12 | .sts4-cache 13 | 14 | ### IntelliJ IDEA ### 15 | .idea 16 | *.iws 17 | *.iml 18 | *.ipr 19 | /out/ 20 | 21 | ### NetBeans ### 22 | /nbproject/private/ 23 | /nbbuild/ 24 | /dist/ 25 | /nbdist/ 26 | /.nb-gradle/ -------------------------------------------------------------------------------- /spring-boot/ses-spring-boot/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Atta Ur Rehman Shah 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /spring-boot/ses-spring-boot/README.md: -------------------------------------------------------------------------------- 1 | # ses-spring-boot 2 | Example of Amazon SES integration with Spring Boot. 3 | 4 | For step-by-step instructions, please visit [blog post]( 5 | https://attacomsian.com/blog/amazon-ses-integration-with-spring-boot/). 6 | -------------------------------------------------------------------------------- /spring-boot/ses-spring-boot/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | ext { 3 | springBootVersion = '2.0.4.RELEASE' 4 | } 5 | repositories { 6 | mavenCentral() 7 | } 8 | dependencies { 9 | classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}") 10 | } 11 | } 12 | 13 | apply plugin: 'java' 14 | apply plugin: 'eclipse' 15 | apply plugin: 'org.springframework.boot' 16 | apply plugin: 'io.spring.dependency-management' 17 | 18 | group = 'com.attacomsian' 19 | version = '0.0.1-SNAPSHOT' 20 | sourceCompatibility = 1.8 21 | 22 | repositories { 23 | mavenCentral() 24 | } 25 | 26 | dependencyManagement { 27 | imports { 28 | mavenBom 'com.amazonaws:aws-java-sdk-bom:1.11.394' 29 | } 30 | } 31 | 32 | dependencies { 33 | compile('org.springframework.boot:spring-boot-starter-web') 34 | testCompile('org.springframework.boot:spring-boot-starter-test') 35 | 36 | //aws ses sdk 37 | compile('com.amazonaws:aws-java-sdk-ses') 38 | //javax required for aws core 39 | compile('javax.mail:javax.mail-api:1.6.1') 40 | } 41 | -------------------------------------------------------------------------------- /spring-boot/ses-spring-boot/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/attacomsian/code-examples/e48ae7eb3ff05aeb5f47016fe8e44c6341e7d005/spring-boot/ses-spring-boot/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /spring-boot/ses-spring-boot/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Tue Feb 06 12:27:20 CET 2018 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.8.1-bin.zip 7 | -------------------------------------------------------------------------------- /spring-boot/ses-spring-boot/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'ses-spring-boot' 2 | -------------------------------------------------------------------------------- /spring-boot/ses-spring-boot/src/main/java/app/AppController.java: -------------------------------------------------------------------------------- 1 | package app; 2 | 3 | import app.ses.AmazonEmail; 4 | import app.ses.SESFrom; 5 | import app.ses.SESProcessor; 6 | import org.springframework.web.bind.annotation.RequestMapping; 7 | import org.springframework.web.bind.annotation.RestController; 8 | 9 | @RestController 10 | public class AppController { 11 | 12 | @RequestMapping("/") 13 | public String index() { 14 | 15 | //send Email using default NO_REPLY from email 16 | SESProcessor.getInstance().add(new AmazonEmail( 17 | "hi@attacomsian.com", 18 | "Hey Atta", 19 | "We have an offer for you :)")); 20 | 21 | //send Email using ATTA from email 22 | SESProcessor.getInstance().add(new AmazonEmail( 23 | "hi@attacomsian.com", 24 | SESFrom.ATTA, 25 | "Hey Atta", 26 | "We have an offer for you :)")); 27 | 28 | return "Emails Sent!"; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /spring-boot/ses-spring-boot/src/main/java/app/Application.java: -------------------------------------------------------------------------------- 1 | package app; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class Application { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(Application.class, args); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /spring-boot/ses-spring-boot/src/main/java/app/ses/AmazonAttachment.java: -------------------------------------------------------------------------------- 1 | package app.ses; 2 | 3 | public class AmazonAttachment { 4 | 5 | private String name; 6 | private byte[] content; 7 | private String contentType; 8 | 9 | public AmazonAttachment() { 10 | } 11 | 12 | public AmazonAttachment(String name, byte[] content, String contentType) { 13 | this.name = name; 14 | this.content = content; 15 | this.contentType = contentType; 16 | } 17 | 18 | public String getName() { 19 | return name; 20 | } 21 | 22 | public void setName(String name) { 23 | this.name = name; 24 | } 25 | 26 | public byte[] getContent() { 27 | return content; 28 | } 29 | 30 | public void setContent(byte[] content) { 31 | this.content = content; 32 | } 33 | 34 | public String getContentType() { 35 | return contentType; 36 | } 37 | 38 | public void setContentType(String contentType) { 39 | this.contentType = contentType; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /spring-boot/ses-spring-boot/src/main/java/app/ses/SESFrom.java: -------------------------------------------------------------------------------- 1 | package app.ses; 2 | 3 | public enum SESFrom { 4 | 5 | ATTA("atta@mysestest.com", "Atta from My SES Test"), 6 | NO_REPLY("noreply@mysestest.com", "My SES Test"), 7 | SUPPORT("support@mysestest.com", "My SES Support Support"); 8 | 9 | private final String email; 10 | private final String name; 11 | 12 | private SESFrom(String email, String name) { 13 | this.email =email; 14 | this.name = name; 15 | } 16 | 17 | public String getEmail() { 18 | return email; 19 | } 20 | 21 | public String getName() { 22 | return name; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /spring-boot/ses-spring-boot/src/main/resources/AwsCredentials.properties: -------------------------------------------------------------------------------- 1 | #Amazon AWS credentials 2 | #These are dummy values. Replace them with 3 | #acutal access key and secret key. 4 | accessKey=32AABS3SDSF3DABHF3DF3 5 | secretKey=sd3sdf55sdfd445+ghjh44s+sdfdsd 6 | -------------------------------------------------------------------------------- /spring-boot/ses-spring-boot/src/main/resources/application.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/attacomsian/code-examples/e48ae7eb3ff05aeb5f47016fe8e44c6341e7d005/spring-boot/ses-spring-boot/src/main/resources/application.properties -------------------------------------------------------------------------------- /spring-boot/ses-spring-boot/src/test/java/app/ApplicationTests.java: -------------------------------------------------------------------------------- 1 | package app; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class ApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /spring-boot/stripe-example/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | .gradle 3 | /build/ 4 | !gradle/wrapper/gradle-wrapper.jar 5 | 6 | ### STS ### 7 | .apt_generated 8 | .classpath 9 | .factorypath 10 | .project 11 | .settings 12 | .springBeans 13 | .sts4-cache 14 | 15 | ### IntelliJ IDEA ### 16 | .idea 17 | *.iws 18 | *.iml 19 | *.ipr 20 | /out/ 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | -------------------------------------------------------------------------------- /spring-boot/stripe-example/README.md: -------------------------------------------------------------------------------- 1 | # Spring integration with Spring Boot 2 | 3 | Example of Stripe payments integration with Spring Boot. 4 | 5 | For step-by-step instructions, please visit [blog post](https://attacomsian.com/blog/stripe-integration-with-spring-boot). 6 | -------------------------------------------------------------------------------- /spring-boot/stripe-example/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'org.springframework.boot' version '2.1.3.RELEASE' 3 | id 'java' 4 | } 5 | 6 | apply plugin: 'io.spring.dependency-management' 7 | 8 | group = 'com.attacomsian' 9 | version = '0.0.1-SNAPSHOT' 10 | sourceCompatibility = '1.8' 11 | 12 | repositories { 13 | mavenCentral() 14 | } 15 | 16 | dependencies { 17 | implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' 18 | implementation 'org.springframework.boot:spring-boot-starter-web' 19 | 20 | // include stripe dependency 21 | implementation 'com.stripe:stripe-java:7.26.0' 22 | } 23 | -------------------------------------------------------------------------------- /spring-boot/stripe-example/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/attacomsian/code-examples/e48ae7eb3ff05aeb5f47016fe8e44c6341e7d005/spring-boot/stripe-example/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /spring-boot/stripe-example/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.2.1-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /spring-boot/stripe-example/settings.gradle: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | repositories { 3 | gradlePluginPortal() 4 | } 5 | } 6 | rootProject.name = 'stripe-example' 7 | -------------------------------------------------------------------------------- /spring-boot/stripe-example/src/main/java/com/attacomsian/stripe/StripeApplication.java: -------------------------------------------------------------------------------- 1 | package com.attacomsian.stripe; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class StripeApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(StripeApplication.class, args); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /spring-boot/stripe-example/src/main/java/com/attacomsian/stripe/commons/Response.java: -------------------------------------------------------------------------------- 1 | package com.attacomsian.stripe.commons; 2 | 3 | public class Response { 4 | 5 | private boolean status; 6 | private String details; 7 | 8 | public Response() { 9 | this.status = true; //default to true 10 | } 11 | 12 | public Response(boolean status) { 13 | this.status = status; 14 | } 15 | 16 | public Response(boolean status, String details) { 17 | this.status = status; 18 | this.details = details; 19 | } 20 | 21 | public boolean isStatus() { 22 | return status; 23 | } 24 | 25 | public void setStatus(boolean status) { 26 | this.status = status; 27 | } 28 | 29 | public String getDetails() { 30 | return details; 31 | } 32 | 33 | public void setDetails(String details) { 34 | this.details = details; 35 | } 36 | 37 | @Override 38 | public String toString() { 39 | return "Response{" + 40 | "status=" + status + 41 | ", details='" + details + '\'' + 42 | '}'; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /spring-boot/stripe-example/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | #Stripe keys - REPLACE WITH ACTUAL KEYS 2 | stripe.keys.public=pk_test_XXXXXXXXXXXXXX 3 | stripe.keys.secret=sk_test_XXXXXXXXXXXXXX 4 | 5 | #Don't cache thymeleaf files - FOR TEST PURPOSE ONLY 6 | spring.thymeleaf.cache=false -------------------------------------------------------------------------------- /spring-boot/stripe-example/src/main/resources/templates/homepage.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Homepage 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 |
17 |
18 |
19 |

20 | Stripe Payment Examples 21 |

22 |

23 | What would you like to do? 24 |

25 | Create Recurring Subscription 26 | Create One-Time Charge 27 |

28 | An example project by Atta. 29 |

30 |
31 |
32 |
33 |
34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /spring-boot/upload-files/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | .gradle 3 | /build/ 4 | !gradle/wrapper/gradle-wrapper.jar 5 | 6 | ### STS ### 7 | .apt_generated 8 | .classpath 9 | .factorypath 10 | .project 11 | .settings 12 | .springBeans 13 | .sts4-cache 14 | 15 | ### IntelliJ IDEA ### 16 | .idea 17 | *.iws 18 | *.iml 19 | *.ipr 20 | /out/ 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | 29 | ### VS Code ### 30 | .vscode/ 31 | 32 | # Upload dir 33 | /uploads/ -------------------------------------------------------------------------------- /spring-boot/upload-files/README.md: -------------------------------------------------------------------------------- 1 | # Uploading Files in Spring Boot 2 | 3 | For step-by-step instructions, please visit [blog post](https://attacomsian.com/blog/uploading-files-spring-boot). 4 | -------------------------------------------------------------------------------- /spring-boot/upload-files/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'org.springframework.boot' version '2.1.3.RELEASE' 3 | id 'java' 4 | } 5 | 6 | apply plugin: 'io.spring.dependency-management' 7 | 8 | group = 'com.attacomsian' 9 | version = '0.0.1-SNAPSHOT' 10 | sourceCompatibility = '1.8' 11 | 12 | repositories { 13 | mavenCentral() 14 | } 15 | 16 | dependencies { 17 | implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' 18 | implementation 'org.springframework.boot:spring-boot-starter-web' 19 | } 20 | -------------------------------------------------------------------------------- /spring-boot/upload-files/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/attacomsian/code-examples/e48ae7eb3ff05aeb5f47016fe8e44c6341e7d005/spring-boot/upload-files/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /spring-boot/upload-files/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.2.1-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /spring-boot/upload-files/settings.gradle: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | repositories { 3 | gradlePluginPortal() 4 | } 5 | } 6 | rootProject.name = 'upload-files' 7 | -------------------------------------------------------------------------------- /spring-boot/upload-files/src/main/java/com/attacomsian/uploadfiles/Application.java: -------------------------------------------------------------------------------- 1 | package com.attacomsian.uploadfiles; 2 | 3 | import com.attacomsian.uploadfiles.storage.StorageProperties; 4 | import org.springframework.boot.SpringApplication; 5 | import org.springframework.boot.autoconfigure.SpringBootApplication; 6 | import org.springframework.boot.context.properties.EnableConfigurationProperties; 7 | 8 | @SpringBootApplication 9 | @EnableConfigurationProperties(StorageProperties.class) 10 | public class Application { 11 | 12 | public static void main(String[] args) { 13 | SpringApplication.run(Application.class, args); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /spring-boot/upload-files/src/main/java/com/attacomsian/uploadfiles/commons/FileResponse.java: -------------------------------------------------------------------------------- 1 | package com.attacomsian.uploadfiles.commons; 2 | 3 | public class FileResponse { 4 | private String name; 5 | private String uri; 6 | private String type; 7 | private long size; 8 | 9 | public FileResponse(String name, String uri, String type, long size) { 10 | this.name = name; 11 | this.uri = uri; 12 | this.type = type; 13 | this.size = size; 14 | } 15 | 16 | public String getName() { 17 | return name; 18 | } 19 | 20 | public void setName(String name) { 21 | this.name = name; 22 | } 23 | 24 | public String getUri() { 25 | return uri; 26 | } 27 | 28 | public void setUri(String uri) { 29 | this.uri = uri; 30 | } 31 | 32 | public String getType() { 33 | return type; 34 | } 35 | 36 | public void setType(String type) { 37 | this.type = type; 38 | } 39 | 40 | public long getSize() { 41 | return size; 42 | } 43 | 44 | public void setSize(long size) { 45 | this.size = size; 46 | } 47 | 48 | @Override 49 | public String toString() { 50 | return "FileResponse{" + 51 | "name='" + name + '\'' + 52 | ", uri='" + uri + '\'' + 53 | ", type='" + type + '\'' + 54 | ", size=" + size + 55 | '}'; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /spring-boot/upload-files/src/main/java/com/attacomsian/uploadfiles/storage/FileNotFoundException.java: -------------------------------------------------------------------------------- 1 | package com.attacomsian.uploadfiles.storage; 2 | 3 | import org.springframework.http.HttpStatus; 4 | import org.springframework.web.bind.annotation.ResponseStatus; 5 | 6 | @ResponseStatus(HttpStatus.NOT_FOUND) 7 | public class FileNotFoundException extends StorageException { 8 | 9 | public FileNotFoundException(String message) { 10 | super(message); 11 | } 12 | 13 | public FileNotFoundException(String message, Throwable cause) { 14 | super(message, cause); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /spring-boot/upload-files/src/main/java/com/attacomsian/uploadfiles/storage/StorageException.java: -------------------------------------------------------------------------------- 1 | package com.attacomsian.uploadfiles.storage; 2 | 3 | public class StorageException extends RuntimeException { 4 | 5 | public StorageException(String message) { 6 | super(message); 7 | } 8 | 9 | public StorageException(String message, Throwable cause) { 10 | super(message, cause); 11 | } 12 | } -------------------------------------------------------------------------------- /spring-boot/upload-files/src/main/java/com/attacomsian/uploadfiles/storage/StorageProperties.java: -------------------------------------------------------------------------------- 1 | package com.attacomsian.uploadfiles.storage; 2 | 3 | import org.springframework.boot.context.properties.ConfigurationProperties; 4 | 5 | @ConfigurationProperties(prefix = "storage") 6 | public class StorageProperties { 7 | 8 | private String location; 9 | 10 | public String getLocation() { 11 | return location; 12 | } 13 | 14 | public void setLocation(String location) { 15 | this.location = location; 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /spring-boot/upload-files/src/main/java/com/attacomsian/uploadfiles/storage/StorageService.java: -------------------------------------------------------------------------------- 1 | package com.attacomsian.uploadfiles.storage; 2 | 3 | import org.springframework.core.io.Resource; 4 | import org.springframework.web.multipart.MultipartFile; 5 | 6 | import java.nio.file.Path; 7 | import java.util.stream.Stream; 8 | 9 | public interface StorageService { 10 | 11 | void init(); 12 | 13 | String store(MultipartFile file); 14 | 15 | Stream loadAll(); 16 | 17 | Path load(String filename); 18 | 19 | Resource loadAsResource(String filename); 20 | 21 | void deleteAll(); 22 | 23 | } -------------------------------------------------------------------------------- /spring-boot/upload-files/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | # max file size 2 | spring.servlet.multipart.max-file-size=10MB 3 | # max request size 4 | spring.servlet.multipart.max-request-size=10MB 5 | # files storage location (stores all files uploaded via REST API) 6 | storage.location=./uploads -------------------------------------------------------------------------------- /spring-boot/upload-files/src/main/resources/templates/listFiles.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |

Spring Boot File Upload Example

6 | 7 |
8 | 9 |

Upload Single File:

10 |
11 |

12 | 13 |
14 | 15 |
16 | 17 |

Upload Multiple Files:

18 |
19 |

20 | 21 |
22 | 23 |
24 | 25 |

All Uploaded Files:

26 |
    27 |
  • 28 | 29 |
  • 30 |
31 | 32 | 33 | -------------------------------------------------------------------------------- /spring-boot/xml-response-parser/.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /build/ 3 | !gradle/wrapper/gradle-wrapper.jar 4 | 5 | ### STS ### 6 | .apt_generated 7 | .classpath 8 | .factorypath 9 | .project 10 | .settings 11 | .springBeans 12 | .sts4-cache 13 | 14 | ### IntelliJ IDEA ### 15 | .idea 16 | *.iws 17 | *.iml 18 | *.ipr 19 | /out/ 20 | 21 | ### NetBeans ### 22 | /nbproject/private/ 23 | /nbbuild/ 24 | /dist/ 25 | /nbdist/ 26 | /.nb-gradle/ 27 | 28 | ### VS Code ### 29 | .vscode/ 30 | -------------------------------------------------------------------------------- /spring-boot/xml-response-parser/README.md: -------------------------------------------------------------------------------- 1 | # Parsing XML Response in Spring Boot 2 | 3 | For step-by-step instructions, please visit [blog post](https://attacomsian.com/blog/parsing-xml-response-spring-boot). 4 | -------------------------------------------------------------------------------- /spring-boot/xml-response-parser/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'org.springframework.boot' version '2.1.3.RELEASE' 3 | id 'java' 4 | } 5 | 6 | apply plugin: 'io.spring.dependency-management' 7 | 8 | group = 'com.attacomsian.xml' 9 | version = '0.0.1-SNAPSHOT' 10 | sourceCompatibility = '1.8' 11 | 12 | repositories { 13 | mavenCentral() 14 | } 15 | 16 | dependencies { 17 | implementation 'org.springframework.boot:spring-boot-starter' 18 | } 19 | -------------------------------------------------------------------------------- /spring-boot/xml-response-parser/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/attacomsian/code-examples/e48ae7eb3ff05aeb5f47016fe8e44c6341e7d005/spring-boot/xml-response-parser/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /spring-boot/xml-response-parser/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.2.1-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /spring-boot/xml-response-parser/settings.gradle: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | repositories { 3 | gradlePluginPortal() 4 | } 5 | } 6 | rootProject.name = 'xml-response-parser' 7 | -------------------------------------------------------------------------------- /spring-boot/xml-response-parser/src/main/java/com/attacomsian/xml/XmlParserApplication.java: -------------------------------------------------------------------------------- 1 | package com.attacomsian.xml; 2 | 3 | import com.attacomsian.xml.models.Course; 4 | import com.attacomsian.xml.services.XMLService; 5 | import org.springframework.boot.Banner; 6 | import org.springframework.boot.CommandLineRunner; 7 | import org.springframework.boot.SpringApplication; 8 | import org.springframework.boot.autoconfigure.SpringBootApplication; 9 | 10 | @SpringBootApplication 11 | public class XmlParserApplication implements CommandLineRunner { 12 | 13 | private XMLService xmlService; 14 | 15 | public XmlParserApplication(XMLService xmlService) { 16 | this.xmlService = xmlService; 17 | } 18 | 19 | public static void main(String[] args) { 20 | SpringApplication app = new SpringApplication(XmlParserApplication.class); 21 | // disable spring banner 22 | app.setBannerMode(Banner.Mode.OFF); 23 | app.run(args); 24 | 25 | } 26 | 27 | @Override 28 | public void run(String... args) throws Exception { 29 | 30 | // load course from XMLService 31 | Course course = xmlService.parseCourse(); 32 | 33 | // print course details 34 | System.out.println(course); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /spring-boot/xml-response-parser/src/main/java/com/attacomsian/xml/models/Course.java: -------------------------------------------------------------------------------- 1 | package com.attacomsian.xml.models; 2 | 3 | import java.util.Date; 4 | import java.util.List; 5 | 6 | public class Course { 7 | 8 | private int id; 9 | private String title; 10 | private double price; 11 | private Date created; 12 | private List students; 13 | 14 | public Course(int id, String title, double price, Date created) { 15 | this.id = id; 16 | this.title = title; 17 | this.price = price; 18 | this.created = created; 19 | } 20 | 21 | public int getId() { 22 | return id; 23 | } 24 | 25 | public void setId(int id) { 26 | this.id = id; 27 | } 28 | 29 | public String getTitle() { 30 | return title; 31 | } 32 | 33 | public void setTitle(String title) { 34 | this.title = title; 35 | } 36 | 37 | public double getPrice() { 38 | return price; 39 | } 40 | 41 | public void setPrice(double price) { 42 | this.price = price; 43 | } 44 | 45 | public Date getCreated() { 46 | return created; 47 | } 48 | 49 | public void setCreated(Date created) { 50 | this.created = created; 51 | } 52 | 53 | public List getStudents() { 54 | return students; 55 | } 56 | 57 | public void setStudents(List students) { 58 | this.students = students; 59 | } 60 | 61 | @Override 62 | public String toString() { 63 | return "Course{" + 64 | "id=" + id + 65 | ", title='" + title + '\'' + 66 | ", price=" + price + 67 | ", created=" + created + 68 | ", students=" + students + 69 | '}'; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /spring-boot/xml-response-parser/src/main/java/com/attacomsian/xml/models/Student.java: -------------------------------------------------------------------------------- 1 | package com.attacomsian.xml.models; 2 | 3 | public class Student { 4 | 5 | private int id; 6 | private String firstName; 7 | private String lastName; 8 | private String avatar; 9 | 10 | public Student(int id, String firstName, String lastName, String avatar) { 11 | this.id = id; 12 | this.firstName = firstName; 13 | this.lastName = lastName; 14 | this.avatar = avatar; 15 | } 16 | 17 | public int getId() { 18 | return id; 19 | } 20 | 21 | public void setId(int id) { 22 | this.id = id; 23 | } 24 | 25 | public String getFirstName() { 26 | return firstName; 27 | } 28 | 29 | public void setFirstName(String firstName) { 30 | this.firstName = firstName; 31 | } 32 | 33 | public String getLastName() { 34 | return lastName; 35 | } 36 | 37 | public void setLastName(String lastName) { 38 | this.lastName = lastName; 39 | } 40 | 41 | public String getAvatar() { 42 | return avatar; 43 | } 44 | 45 | public void setAvatar(String avatar) { 46 | this.avatar = avatar; 47 | } 48 | 49 | @Override 50 | public String toString() { 51 | return "Student{" + 52 | "id=" + id + 53 | ", firstName='" + firstName + '\'' + 54 | ", lastName='" + lastName + '\'' + 55 | ", avatar='" + avatar + '\'' + 56 | '}'; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /spring-boot/xml-response-parser/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /spring-data-jpa/jpa-auditing/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | .gradle 3 | build/ 4 | !gradle/wrapper/gradle-wrapper.jar 5 | !**/src/main/** 6 | !**/src/test/** 7 | 8 | ### STS ### 9 | .apt_generated 10 | .classpath 11 | .factorypath 12 | .project 13 | .settings 14 | .springBeans 15 | .sts4-cache 16 | 17 | ### IntelliJ IDEA ### 18 | .idea 19 | *.iws 20 | *.iml 21 | *.ipr 22 | out/ 23 | 24 | ### NetBeans ### 25 | /nbproject/private/ 26 | /nbbuild/ 27 | /dist/ 28 | /nbdist/ 29 | /.nb-gradle/ 30 | 31 | ### VS Code ### 32 | .vscode/ 33 | -------------------------------------------------------------------------------- /spring-data-jpa/jpa-auditing/README.md: -------------------------------------------------------------------------------- 1 | # Spring Data JPA Auditing using Spring Boot and MySQL 2 | 3 | For step-by-step instructions, please check out [blog post](https://attacomsian.com/blog/spring-data-jpa-auditing). 4 | -------------------------------------------------------------------------------- /spring-data-jpa/jpa-auditing/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'org.springframework.boot' version '2.2.0.RELEASE' 3 | id 'io.spring.dependency-management' version '1.0.8.RELEASE' 4 | id 'java' 5 | } 6 | 7 | group = 'com.attacomsian' 8 | version = '0.0.1-SNAPSHOT' 9 | sourceCompatibility = '1.8' 10 | 11 | repositories { 12 | mavenCentral() 13 | } 14 | 15 | dependencies { 16 | implementation 'org.springframework.boot:spring-boot-starter-data-jpa' 17 | runtimeOnly 'mysql:mysql-connector-java' 18 | } 19 | -------------------------------------------------------------------------------- /spring-data-jpa/jpa-auditing/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/attacomsian/code-examples/e48ae7eb3ff05aeb5f47016fe8e44c6341e7d005/spring-data-jpa/jpa-auditing/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /spring-data-jpa/jpa-auditing/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /spring-data-jpa/jpa-auditing/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'jpa-auditing' 2 | -------------------------------------------------------------------------------- /spring-data-jpa/jpa-auditing/src/main/java/com/attacomsian/jpa/Application.java: -------------------------------------------------------------------------------- 1 | package com.attacomsian.jpa; 2 | 3 | import com.attacomsian.jpa.domains.Todo; 4 | import com.attacomsian.jpa.repositories.TodoRepository; 5 | import org.springframework.boot.CommandLineRunner; 6 | import org.springframework.boot.SpringApplication; 7 | import org.springframework.boot.autoconfigure.SpringBootApplication; 8 | import org.springframework.context.annotation.Bean; 9 | 10 | import java.util.Arrays; 11 | 12 | @SpringBootApplication 13 | public class Application { 14 | 15 | public static void main(String[] args) { 16 | SpringApplication.run(Application.class, args); 17 | } 18 | 19 | @Bean 20 | public CommandLineRunner auditingDemo(TodoRepository todoRepository) { 21 | return args -> { 22 | 23 | // create new todos 24 | todoRepository.saveAll(Arrays.asList( 25 | new Todo("Buy milk", false), 26 | new Todo("Email John", false), 27 | new Todo("Visit Emma", false), 28 | new Todo("Call dad", true), 29 | new Todo("Weekend walk", true), 30 | new Todo("Write Auditing Tutorial", true) 31 | )); 32 | 33 | // retrieve all todos 34 | Iterable todos = todoRepository.findAll(); 35 | 36 | // print all todos 37 | todos.forEach(System.out::println); 38 | }; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /spring-data-jpa/jpa-auditing/src/main/java/com/attacomsian/jpa/config/AuditConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.attacomsian.jpa.config; 2 | 3 | import com.attacomsian.jpa.domains.EntityAuditorAware; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.Configuration; 6 | import org.springframework.data.domain.AuditorAware; 7 | import org.springframework.data.jpa.repository.config.EnableJpaAuditing; 8 | 9 | @Configuration 10 | @EnableJpaAuditing 11 | public class AuditConfiguration { 12 | 13 | @Bean 14 | public AuditorAware auditorAware() { 15 | return new EntityAuditorAware(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /spring-data-jpa/jpa-auditing/src/main/java/com/attacomsian/jpa/domains/Auditable.java: -------------------------------------------------------------------------------- 1 | package com.attacomsian.jpa.domains; 2 | 3 | import org.springframework.data.annotation.CreatedBy; 4 | import org.springframework.data.annotation.CreatedDate; 5 | import org.springframework.data.annotation.LastModifiedBy; 6 | import org.springframework.data.annotation.LastModifiedDate; 7 | import org.springframework.data.jpa.domain.support.AuditingEntityListener; 8 | 9 | import javax.persistence.EntityListeners; 10 | import javax.persistence.MappedSuperclass; 11 | import javax.persistence.Temporal; 12 | import javax.persistence.TemporalType; 13 | import java.util.Date; 14 | 15 | @MappedSuperclass 16 | @EntityListeners(AuditingEntityListener.class) 17 | public abstract class Auditable { 18 | 19 | @CreatedBy 20 | protected T createdBy; 21 | 22 | @Temporal(TemporalType.TIMESTAMP) 23 | @CreatedDate 24 | protected Date createdDate; 25 | 26 | @LastModifiedBy 27 | protected T lastModifiedBy; 28 | 29 | @Temporal(TemporalType.TIMESTAMP) 30 | @LastModifiedDate 31 | protected Date lastModifiedDate; 32 | 33 | public T getCreatedBy() { 34 | return createdBy; 35 | } 36 | 37 | public void setCreatedBy(T createdBy) { 38 | this.createdBy = createdBy; 39 | } 40 | 41 | public Date getCreatedDate() { 42 | return createdDate; 43 | } 44 | 45 | public void setCreatedDate(Date createdDate) { 46 | this.createdDate = createdDate; 47 | } 48 | 49 | public T getLastModifiedBy() { 50 | return lastModifiedBy; 51 | } 52 | 53 | public void setLastModifiedBy(T lastModifiedBy) { 54 | this.lastModifiedBy = lastModifiedBy; 55 | } 56 | 57 | public Date getLastModifiedDate() { 58 | return lastModifiedDate; 59 | } 60 | 61 | public void setLastModifiedDate(Date lastModifiedDate) { 62 | this.lastModifiedDate = lastModifiedDate; 63 | } 64 | } -------------------------------------------------------------------------------- /spring-data-jpa/jpa-auditing/src/main/java/com/attacomsian/jpa/domains/EntityAuditorAware.java: -------------------------------------------------------------------------------- 1 | package com.attacomsian.jpa.domains; 2 | 3 | import org.springframework.data.domain.AuditorAware; 4 | 5 | import java.util.Optional; 6 | 7 | public class EntityAuditorAware implements AuditorAware { 8 | 9 | @Override 10 | public Optional getCurrentAuditor() { 11 | return Optional.of("Atta"); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /spring-data-jpa/jpa-auditing/src/main/java/com/attacomsian/jpa/domains/Todo.java: -------------------------------------------------------------------------------- 1 | package com.attacomsian.jpa.domains; 2 | 3 | import javax.persistence.*; 4 | import java.io.Serializable; 5 | import java.util.Objects; 6 | 7 | @Entity 8 | @Table(name = "todos") 9 | public class Todo extends Auditable implements Serializable { 10 | 11 | @Id 12 | @GeneratedValue(strategy = GenerationType.IDENTITY) 13 | private Long id; 14 | 15 | private String title; 16 | private boolean completed; 17 | 18 | public Todo() { 19 | } 20 | 21 | public Todo(String title, boolean completed) { 22 | this.title = title; 23 | this.completed = completed; 24 | } 25 | 26 | public Long getId() { 27 | return id; 28 | } 29 | 30 | public void setId(Long id) { 31 | this.id = id; 32 | } 33 | 34 | public String getTitle() { 35 | return title; 36 | } 37 | 38 | public void setTitle(String title) { 39 | this.title = title; 40 | } 41 | 42 | public boolean isCompleted() { 43 | return completed; 44 | } 45 | 46 | public void setCompleted(boolean completed) { 47 | this.completed = completed; 48 | } 49 | 50 | @Override 51 | public boolean equals(Object o) { 52 | if (this == o) return true; 53 | if (o == null || getClass() != o.getClass()) return false; 54 | Todo todo = (Todo) o; 55 | return id.equals(todo.id); 56 | } 57 | 58 | @Override 59 | public int hashCode() { 60 | return Objects.hash(id); 61 | } 62 | 63 | @Override 64 | public String toString() { 65 | return "Todo{" + 66 | "id=" + id + 67 | ", title='" + title + '\'' + 68 | ", completed=" + completed + 69 | ", createdBy=" + createdBy + 70 | ", createdDate=" + createdDate + 71 | ", lastModifiedBy=" + lastModifiedBy + 72 | ", lastModifiedDate=" + lastModifiedDate + 73 | '}'; 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /spring-data-jpa/jpa-auditing/src/main/java/com/attacomsian/jpa/repositories/TodoRepository.java: -------------------------------------------------------------------------------- 1 | package com.attacomsian.jpa.repositories; 2 | 3 | import com.attacomsian.jpa.domains.Todo; 4 | import org.springframework.data.repository.CrudRepository; 5 | 6 | public interface TodoRepository extends CrudRepository { 7 | 8 | // TODO: add queries 9 | } 10 | -------------------------------------------------------------------------------- /spring-data-jpa/jpa-auditing/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | # MySQL connection properties 2 | spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver 3 | spring.datasource.username=root 4 | spring.datasource.password= 5 | spring.datasource.url=jdbc:mysql://localhost:3306/testdb?createDatabaseIfNotExist=true&useSSL=false 6 | 7 | # Log JPA queries 8 | # Comment this in production 9 | spring.jpa.show-sql=true 10 | 11 | # Drop and create new tables (create, create-drop, validate, update) 12 | # Only for testing purpose - comment this in production 13 | spring.jpa.hibernate.ddl-auto=create 14 | 15 | # Hibernate SQL dialect 16 | spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect -------------------------------------------------------------------------------- /spring-data-jpa/jpa-getting-started/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | .gradle 3 | build/ 4 | !gradle/wrapper/gradle-wrapper.jar 5 | !**/src/main/** 6 | !**/src/test/** 7 | 8 | ### STS ### 9 | .apt_generated 10 | .classpath 11 | .factorypath 12 | .project 13 | .settings 14 | .springBeans 15 | .sts4-cache 16 | 17 | ### IntelliJ IDEA ### 18 | .idea 19 | *.iws 20 | *.iml 21 | *.ipr 22 | out/ 23 | 24 | ### NetBeans ### 25 | /nbproject/private/ 26 | /nbbuild/ 27 | /dist/ 28 | /nbdist/ 29 | /.nb-gradle/ 30 | 31 | ### VS Code ### 32 | .vscode/ 33 | -------------------------------------------------------------------------------- /spring-data-jpa/jpa-getting-started/README.md: -------------------------------------------------------------------------------- 1 | # Getting Started with Spring Data JPA 2 | 3 | For step-by-step instructions, please check out [blog post](https://attacomsian.com/blog/getting-started-spring-data-jpa). 4 | -------------------------------------------------------------------------------- /spring-data-jpa/jpa-getting-started/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'org.springframework.boot' version '2.1.8.RELEASE' 3 | id 'io.spring.dependency-management' version '1.0.8.RELEASE' 4 | id 'java' 5 | } 6 | 7 | group = 'com.attacomsian' 8 | version = '0.0.1-SNAPSHOT' 9 | sourceCompatibility = '1.8' 10 | 11 | repositories { 12 | mavenCentral() 13 | } 14 | 15 | dependencies { 16 | implementation 'org.springframework.boot:spring-boot-starter-data-jpa' 17 | runtimeOnly 'com.h2database:h2' 18 | } 19 | -------------------------------------------------------------------------------- /spring-data-jpa/jpa-getting-started/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/attacomsian/code-examples/e48ae7eb3ff05aeb5f47016fe8e44c6341e7d005/spring-data-jpa/jpa-getting-started/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /spring-data-jpa/jpa-getting-started/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /spring-data-jpa/jpa-getting-started/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'jpa-getting-started' 2 | -------------------------------------------------------------------------------- /spring-data-jpa/jpa-getting-started/src/main/java/com/attacomsian/jpa/domains/User.java: -------------------------------------------------------------------------------- 1 | package com.attacomsian.jpa.domains; 2 | 3 | import javax.persistence.Entity; 4 | import javax.persistence.GeneratedValue; 5 | import javax.persistence.GenerationType; 6 | import javax.persistence.Id; 7 | 8 | @Entity 9 | public class User { 10 | 11 | @Id 12 | @GeneratedValue(strategy = GenerationType.AUTO) 13 | private Long id; 14 | private String name; 15 | private String email; 16 | 17 | public User() { 18 | } 19 | 20 | public User(String name, String email) { 21 | this.name = name; 22 | this.email = email; 23 | } 24 | 25 | public Long getId() { 26 | return id; 27 | } 28 | 29 | public void setId(Long id) { 30 | this.id = id; 31 | } 32 | 33 | public String getName() { 34 | return name; 35 | } 36 | 37 | public void setName(String name) { 38 | this.name = name; 39 | } 40 | 41 | public String getEmail() { 42 | return email; 43 | } 44 | 45 | public void setEmail(String email) { 46 | this.email = email; 47 | } 48 | 49 | @Override 50 | public String toString() { 51 | return "User{" + 52 | "id=" + id + 53 | ", name='" + name + '\'' + 54 | ", email='" + email + '\'' + 55 | '}'; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /spring-data-jpa/jpa-getting-started/src/main/java/com/attacomsian/jpa/repositories/UserRepository.java: -------------------------------------------------------------------------------- 1 | package com.attacomsian.jpa.repositories; 2 | 3 | import com.attacomsian.jpa.domains.User; 4 | import org.springframework.data.repository.CrudRepository; 5 | 6 | import java.util.List; 7 | 8 | public interface UserRepository extends CrudRepository { 9 | 10 | List findByName(String name); 11 | 12 | User findByEmail(String email); 13 | } 14 | -------------------------------------------------------------------------------- /spring-data-jpa/jpa-getting-started/src/main/resources/application.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/attacomsian/code-examples/e48ae7eb3ff05aeb5f47016fe8e44c6341e7d005/spring-data-jpa/jpa-getting-started/src/main/resources/application.properties -------------------------------------------------------------------------------- /spring-data-jpa/jpa-h2/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | .gradle 3 | build/ 4 | !gradle/wrapper/gradle-wrapper.jar 5 | !**/src/main/** 6 | !**/src/test/** 7 | 8 | ### STS ### 9 | .apt_generated 10 | .classpath 11 | .factorypath 12 | .project 13 | .settings 14 | .springBeans 15 | .sts4-cache 16 | 17 | ### IntelliJ IDEA ### 18 | .idea 19 | *.iws 20 | *.iml 21 | *.ipr 22 | out/ 23 | 24 | ### NetBeans ### 25 | /nbproject/private/ 26 | /nbbuild/ 27 | /dist/ 28 | /nbdist/ 29 | /.nb-gradle/ 30 | 31 | ### VS Code ### 32 | .vscode/ 33 | -------------------------------------------------------------------------------- /spring-data-jpa/jpa-h2/README.md: -------------------------------------------------------------------------------- 1 | # Spring Data JPA with H2 DataBase and Spring Boot 2 | 3 | For step-by-step instructions, please check out [blog post](https://attacomsian.com/blog/spring-data-jpa-h2-database). 4 | -------------------------------------------------------------------------------- /spring-data-jpa/jpa-h2/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'org.springframework.boot' version '2.1.8.RELEASE' 3 | id 'io.spring.dependency-management' version '1.0.8.RELEASE' 4 | id 'java' 5 | } 6 | 7 | group = 'com.attacomsian' 8 | version = '0.0.1-SNAPSHOT' 9 | sourceCompatibility = '1.8' 10 | 11 | repositories { 12 | mavenCentral() 13 | } 14 | 15 | dependencies { 16 | implementation 'org.springframework.boot:spring-boot-starter-data-jpa' 17 | runtimeOnly 'com.h2database:h2' 18 | } 19 | -------------------------------------------------------------------------------- /spring-data-jpa/jpa-h2/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/attacomsian/code-examples/e48ae7eb3ff05aeb5f47016fe8e44c6341e7d005/spring-data-jpa/jpa-h2/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /spring-data-jpa/jpa-h2/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /spring-data-jpa/jpa-h2/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'jpa-h2' 2 | -------------------------------------------------------------------------------- /spring-data-jpa/jpa-h2/src/main/java/com/attacomsian/jpa/domains/Book.java: -------------------------------------------------------------------------------- 1 | package com.attacomsian.jpa.domains; 2 | 3 | import javax.persistence.*; 4 | 5 | @Entity 6 | public class Book { 7 | 8 | @Id 9 | @GeneratedValue(strategy = GenerationType.AUTO) 10 | private Long id; 11 | private String title; 12 | @Column(unique = true) 13 | private String isbn; 14 | 15 | public Book() { 16 | } 17 | 18 | public Book(String title, String isbn) { 19 | this.title = title; 20 | this.isbn = isbn; 21 | } 22 | 23 | public Long getId() { 24 | return id; 25 | } 26 | 27 | public void setId(Long id) { 28 | this.id = id; 29 | } 30 | 31 | public String getTitle() { 32 | return title; 33 | } 34 | 35 | public void setTitle(String title) { 36 | this.title = title; 37 | } 38 | 39 | public String getIsbn() { 40 | return isbn; 41 | } 42 | 43 | public void setIsbn(String isbn) { 44 | this.isbn = isbn; 45 | } 46 | 47 | @Override 48 | public String toString() { 49 | return "Book{" + 50 | "id=" + id + 51 | ", title='" + title + '\'' + 52 | ", isbn='" + isbn + '\'' + 53 | '}'; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /spring-data-jpa/jpa-h2/src/main/java/com/attacomsian/jpa/repositories/BookRepository.java: -------------------------------------------------------------------------------- 1 | package com.attacomsian.jpa.repositories; 2 | 3 | import com.attacomsian.jpa.domains.Book; 4 | import org.springframework.data.repository.CrudRepository; 5 | 6 | import java.util.List; 7 | 8 | public interface BookRepository extends CrudRepository { 9 | 10 | Book findByIsbn(String isbn); 11 | 12 | List findByTitleContaining(String title); 13 | } -------------------------------------------------------------------------------- /spring-data-jpa/jpa-h2/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.datasource.url=jdbc:h2:mem:jpadb 2 | spring.datasource.driverClassName=org.h2.Driver 3 | spring.datasource.username=sa 4 | spring.datasource.password=mypass 5 | spring.jpa.database-platform=org.hibernate.dialect.H2Dialect 6 | -------------------------------------------------------------------------------- /spring-data-jpa/jpa-mappings/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | .gradle 3 | build/ 4 | !gradle/wrapper/gradle-wrapper.jar 5 | !**/src/main/** 6 | !**/src/test/** 7 | 8 | ### STS ### 9 | .apt_generated 10 | .classpath 11 | .factorypath 12 | .project 13 | .settings 14 | .springBeans 15 | .sts4-cache 16 | 17 | ### IntelliJ IDEA ### 18 | .idea 19 | *.iws 20 | *.iml 21 | *.ipr 22 | out/ 23 | 24 | ### NetBeans ### 25 | /nbproject/private/ 26 | /nbbuild/ 27 | /dist/ 28 | /nbdist/ 29 | /.nb-gradle/ 30 | 31 | ### VS Code ### 32 | .vscode/ 33 | -------------------------------------------------------------------------------- /spring-data-jpa/jpa-mappings/README.md: -------------------------------------------------------------------------------- 1 | # Spring Data JPA Relationship Mapping Articles 2 | 3 | - [Spring Data JPA One To One Relationship Mapping Example](https://attacomsian.com/blog/spring-data-jpa-one-to-one-mapping) 4 | - [Spring Data JPA One To Many Relationship Mapping Example](https://attacomsian.com/blog/spring-data-jpa-one-to-many-mapping) 5 | - [Spring Data JPA Many To Many Relationship Mapping Example](https://attacomsian.com/blog/spring-data-jpa-many-to-many-mapping) 6 | - [Spring Data JPA Composite Primary Key Mapping Example](https://attacomsian.com/blog/spring-data-jpa-composite-primary-key) -------------------------------------------------------------------------------- /spring-data-jpa/jpa-mappings/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'org.springframework.boot' version '2.1.9.RELEASE' 3 | id 'io.spring.dependency-management' version '1.0.8.RELEASE' 4 | id 'java' 5 | } 6 | 7 | group = 'com.attacomsian' 8 | version = '0.0.1-SNAPSHOT' 9 | sourceCompatibility = '1.8' 10 | 11 | repositories { 12 | mavenCentral() 13 | } 14 | 15 | dependencies { 16 | implementation 'org.springframework.boot:spring-boot-starter-data-jpa' 17 | runtimeOnly 'mysql:mysql-connector-java' 18 | } 19 | -------------------------------------------------------------------------------- /spring-data-jpa/jpa-mappings/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/attacomsian/code-examples/e48ae7eb3ff05aeb5f47016fe8e44c6341e7d005/spring-data-jpa/jpa-mappings/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /spring-data-jpa/jpa-mappings/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /spring-data-jpa/jpa-mappings/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'jpa-mappings' 2 | -------------------------------------------------------------------------------- /spring-data-jpa/jpa-mappings/src/main/java/com/attacomsian/jpa/composite/domains/Account.java: -------------------------------------------------------------------------------- 1 | package com.attacomsian.jpa.composite.domains; 2 | 3 | import javax.persistence.Entity; 4 | import javax.persistence.Id; 5 | import javax.persistence.IdClass; 6 | import javax.persistence.Table; 7 | import java.io.Serializable; 8 | 9 | @Entity 10 | @Table(name = "accounts") 11 | @IdClass(AccountId.class) 12 | public class Account implements Serializable { 13 | 14 | @Id 15 | private String accountNumber; 16 | @Id 17 | private String accountType; 18 | 19 | private double balance; 20 | 21 | public Account() { 22 | } 23 | 24 | public Account(String accountNumber, String accountType, double balance) { 25 | this.accountNumber = accountNumber; 26 | this.accountType = accountType; 27 | this.balance = balance; 28 | } 29 | 30 | public String getAccountNumber() { 31 | return accountNumber; 32 | } 33 | 34 | public void setAccountNumber(String accountNumber) { 35 | this.accountNumber = accountNumber; 36 | } 37 | 38 | public String getAccountType() { 39 | return accountType; 40 | } 41 | 42 | public void setAccountType(String accountType) { 43 | this.accountType = accountType; 44 | } 45 | 46 | public double getBalance() { 47 | return balance; 48 | } 49 | 50 | public void setBalance(double balance) { 51 | this.balance = balance; 52 | } 53 | 54 | @Override 55 | public String toString() { 56 | return "Account{" + 57 | "accountNumber='" + accountNumber + '\'' + 58 | ", accountType='" + accountType + '\'' + 59 | ", balance=" + balance + 60 | '}'; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /spring-data-jpa/jpa-mappings/src/main/java/com/attacomsian/jpa/composite/domains/AccountId.java: -------------------------------------------------------------------------------- 1 | package com.attacomsian.jpa.composite.domains; 2 | 3 | import java.io.Serializable; 4 | import java.util.Objects; 5 | 6 | public class AccountId implements Serializable { 7 | 8 | private String accountNumber; 9 | private String accountType; 10 | 11 | public AccountId() { 12 | } 13 | 14 | public AccountId(String accountNumber, String accountType) { 15 | this.accountNumber = accountNumber; 16 | this.accountType = accountType; 17 | } 18 | 19 | @Override 20 | public boolean equals(Object o) { 21 | if (this == o) return true; 22 | if (o == null || getClass() != o.getClass()) return false; 23 | AccountId accountId = (AccountId) o; 24 | return accountNumber.equals(accountId.accountNumber) && 25 | accountType.equals(accountId.accountType); 26 | } 27 | 28 | @Override 29 | public int hashCode() { 30 | return Objects.hash(accountNumber, accountType); 31 | } 32 | } -------------------------------------------------------------------------------- /spring-data-jpa/jpa-mappings/src/main/java/com/attacomsian/jpa/composite/domains/Employee.java: -------------------------------------------------------------------------------- 1 | package com.attacomsian.jpa.composite.domains; 2 | 3 | import javax.persistence.Column; 4 | import javax.persistence.EmbeddedId; 5 | import javax.persistence.Entity; 6 | import javax.persistence.Table; 7 | import java.io.Serializable; 8 | 9 | @Entity 10 | @Table(name = "employees") 11 | public class Employee implements Serializable { 12 | 13 | @EmbeddedId 14 | private EmployeeId employeeId; 15 | 16 | private String name; 17 | @Column(unique = true) 18 | private String email; 19 | private String phoneNumber; 20 | 21 | public Employee() { 22 | } 23 | 24 | public Employee(EmployeeId employeeId, String name, String email, String phoneNumber) { 25 | this.employeeId = employeeId; 26 | this.name = name; 27 | this.email = email; 28 | this.phoneNumber = phoneNumber; 29 | } 30 | 31 | public EmployeeId getEmployeeId() { 32 | return employeeId; 33 | } 34 | 35 | public void setEmployeeId(EmployeeId employeeId) { 36 | this.employeeId = employeeId; 37 | } 38 | 39 | public String getName() { 40 | return name; 41 | } 42 | 43 | public void setName(String name) { 44 | this.name = name; 45 | } 46 | 47 | public String getEmail() { 48 | return email; 49 | } 50 | 51 | public void setEmail(String email) { 52 | this.email = email; 53 | } 54 | 55 | public String getPhoneNumber() { 56 | return phoneNumber; 57 | } 58 | 59 | public void setPhoneNumber(String phoneNumber) { 60 | this.phoneNumber = phoneNumber; 61 | } 62 | 63 | @Override 64 | public String toString() { 65 | return "Employee{" + 66 | "employeeId=" + employeeId + 67 | ", name='" + name + '\'' + 68 | ", email='" + email + '\'' + 69 | ", phoneNumber='" + phoneNumber + '\'' + 70 | '}'; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /spring-data-jpa/jpa-mappings/src/main/java/com/attacomsian/jpa/composite/domains/EmployeeId.java: -------------------------------------------------------------------------------- 1 | package com.attacomsian.jpa.composite.domains; 2 | 3 | import javax.persistence.Column; 4 | import javax.persistence.Embeddable; 5 | import java.io.Serializable; 6 | import java.util.Objects; 7 | 8 | @Embeddable 9 | public class EmployeeId implements Serializable { 10 | 11 | @Column(name = "employee_id") 12 | private Long employeeId; 13 | 14 | @Column(name = "department_id") 15 | private Long departmentId; 16 | 17 | public EmployeeId() { 18 | } 19 | 20 | public EmployeeId(Long employeeId, Long departmentId) { 21 | this.employeeId = employeeId; 22 | this.departmentId = departmentId; 23 | } 24 | 25 | public Long getEmployeeId() { 26 | return employeeId; 27 | } 28 | 29 | public void setEmployeeId(Long employeeId) { 30 | this.employeeId = employeeId; 31 | } 32 | 33 | public Long getDepartmentId() { 34 | return departmentId; 35 | } 36 | 37 | public void setDepartmentId(Long departmentId) { 38 | this.departmentId = departmentId; 39 | } 40 | 41 | @Override 42 | public boolean equals(Object o) { 43 | if (this == o) return true; 44 | if (o == null || getClass() != o.getClass()) return false; 45 | EmployeeId that = (EmployeeId) o; 46 | return employeeId.equals(that.employeeId) && 47 | departmentId.equals(that.departmentId); 48 | } 49 | 50 | @Override 51 | public int hashCode() { 52 | return Objects.hash(employeeId, departmentId); 53 | } 54 | 55 | @Override 56 | public String toString() { 57 | return "EmployeeId{" + 58 | "employeeId=" + employeeId + 59 | ", departmentId=" + departmentId + 60 | '}'; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /spring-data-jpa/jpa-mappings/src/main/java/com/attacomsian/jpa/composite/repositories/AccountRepository.java: -------------------------------------------------------------------------------- 1 | package com.attacomsian.jpa.composite.repositories; 2 | 3 | import com.attacomsian.jpa.composite.domains.Account; 4 | import com.attacomsian.jpa.composite.domains.AccountId; 5 | import org.springframework.data.repository.CrudRepository; 6 | 7 | import java.util.List; 8 | 9 | public interface AccountRepository extends CrudRepository { 10 | 11 | List findByAccountType(String accountType); 12 | } 13 | -------------------------------------------------------------------------------- /spring-data-jpa/jpa-mappings/src/main/java/com/attacomsian/jpa/composite/repositories/EmployeeRepository.java: -------------------------------------------------------------------------------- 1 | package com.attacomsian.jpa.composite.repositories; 2 | 3 | import com.attacomsian.jpa.composite.domains.Employee; 4 | import com.attacomsian.jpa.composite.domains.EmployeeId; 5 | import org.springframework.data.repository.CrudRepository; 6 | 7 | import java.util.List; 8 | 9 | public interface EmployeeRepository extends CrudRepository { 10 | 11 | List findByEmployeeIdDepartmentId(Long departmentId); 12 | } 13 | -------------------------------------------------------------------------------- /spring-data-jpa/jpa-mappings/src/main/java/com/attacomsian/jpa/many2many/repositories/CourseRepository.java: -------------------------------------------------------------------------------- 1 | package com.attacomsian.jpa.many2many.repositories; 2 | 3 | import com.attacomsian.jpa.many2many.domains.Course; 4 | import org.springframework.data.repository.CrudRepository; 5 | 6 | import java.util.List; 7 | 8 | public interface CourseRepository extends CrudRepository { 9 | 10 | List findByTitleContaining(String title); 11 | 12 | List findByFeeLessThan(double fee); 13 | } 14 | -------------------------------------------------------------------------------- /spring-data-jpa/jpa-mappings/src/main/java/com/attacomsian/jpa/many2many/repositories/StudentRepository.java: -------------------------------------------------------------------------------- 1 | package com.attacomsian.jpa.many2many.repositories; 2 | 3 | import com.attacomsian.jpa.many2many.domains.Student; 4 | import org.springframework.data.repository.CrudRepository; 5 | 6 | import java.util.List; 7 | 8 | public interface StudentRepository extends CrudRepository { 9 | 10 | List findByNameContaining(String name); 11 | } 12 | -------------------------------------------------------------------------------- /spring-data-jpa/jpa-mappings/src/main/java/com/attacomsian/jpa/one2many/domains/Book.java: -------------------------------------------------------------------------------- 1 | package com.attacomsian.jpa.one2many.domains; 2 | 3 | import javax.persistence.*; 4 | import java.io.Serializable; 5 | import java.util.Objects; 6 | import java.util.Set; 7 | 8 | @Entity 9 | @Table(name = "books") 10 | public class Book implements Serializable { 11 | 12 | @Id 13 | @GeneratedValue(strategy = GenerationType.IDENTITY) 14 | private Long id; 15 | 16 | private String title; 17 | private String author; 18 | @Column(unique = true) 19 | private String isbn; 20 | 21 | @OneToMany(mappedBy = "book", fetch = FetchType.LAZY, 22 | cascade = CascadeType.ALL) 23 | private Set pages; 24 | 25 | public Book() { 26 | } 27 | 28 | public Book(String title, String author, String isbn) { 29 | this.title = title; 30 | this.author = author; 31 | this.isbn = isbn; 32 | } 33 | 34 | public Long getId() { 35 | return id; 36 | } 37 | 38 | public void setId(Long id) { 39 | this.id = id; 40 | } 41 | 42 | public String getTitle() { 43 | return title; 44 | } 45 | 46 | public void setTitle(String title) { 47 | this.title = title; 48 | } 49 | 50 | public String getAuthor() { 51 | return author; 52 | } 53 | 54 | public void setAuthor(String author) { 55 | this.author = author; 56 | } 57 | 58 | public String getIsbn() { 59 | return isbn; 60 | } 61 | 62 | public void setIsbn(String isbn) { 63 | this.isbn = isbn; 64 | } 65 | 66 | public Set getPages() { 67 | return pages; 68 | } 69 | 70 | public void setPages(Set pages) { 71 | this.pages = pages; 72 | } 73 | 74 | @Override 75 | public boolean equals(Object o) { 76 | if (this == o) return true; 77 | if (o == null || getClass() != o.getClass()) return false; 78 | Book book = (Book) o; 79 | return id.equals(book.id); 80 | } 81 | 82 | @Override 83 | public int hashCode() { 84 | return Objects.hash(id); 85 | } 86 | 87 | @Override 88 | public String toString() { 89 | return "Book{" + 90 | "id=" + id + 91 | ", title='" + title + '\'' + 92 | ", author='" + author + '\'' + 93 | ", isbn='" + isbn + '\'' + 94 | '}'; 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /spring-data-jpa/jpa-mappings/src/main/java/com/attacomsian/jpa/one2many/domains/Page.java: -------------------------------------------------------------------------------- 1 | package com.attacomsian.jpa.one2many.domains; 2 | 3 | import javax.persistence.*; 4 | import java.io.Serializable; 5 | import java.util.Objects; 6 | 7 | @Entity 8 | @Table(name = "pages") 9 | public class Page implements Serializable { 10 | 11 | @Id 12 | @GeneratedValue(strategy = GenerationType.IDENTITY) 13 | private Long id; 14 | 15 | private int number; 16 | private String content; 17 | private String chapter; 18 | 19 | @ManyToOne(fetch = FetchType.LAZY, optional = false) 20 | @JoinColumn(name = "book_id", nullable = false) 21 | private Book book; 22 | 23 | public Page() { 24 | } 25 | 26 | public Page(int number, String content, String chapter, Book book) { 27 | this.number = number; 28 | this.content = content; 29 | this.chapter = chapter; 30 | this.book = book; 31 | } 32 | 33 | public Long getId() { 34 | return id; 35 | } 36 | 37 | public void setId(Long id) { 38 | this.id = id; 39 | } 40 | 41 | public int getNumber() { 42 | return number; 43 | } 44 | 45 | public void setNumber(int number) { 46 | this.number = number; 47 | } 48 | 49 | public String getContent() { 50 | return content; 51 | } 52 | 53 | public void setContent(String content) { 54 | this.content = content; 55 | } 56 | 57 | public String getChapter() { 58 | return chapter; 59 | } 60 | 61 | public void setChapter(String chapter) { 62 | this.chapter = chapter; 63 | } 64 | 65 | public Book getBook() { 66 | return book; 67 | } 68 | 69 | public void setBook(Book book) { 70 | this.book = book; 71 | } 72 | 73 | @Override 74 | public boolean equals(Object o) { 75 | if (this == o) return true; 76 | if (o == null || getClass() != o.getClass()) return false; 77 | Page page = (Page) o; 78 | return id.equals(page.id); 79 | } 80 | 81 | @Override 82 | public int hashCode() { 83 | return Objects.hash(id); 84 | } 85 | 86 | @Override 87 | public String toString() { 88 | return "Page{" + 89 | "id=" + id + 90 | ", number=" + number + 91 | ", content='" + content + '\'' + 92 | ", chapter='" + chapter + '\'' + 93 | ", book=" + book + 94 | '}'; 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /spring-data-jpa/jpa-mappings/src/main/java/com/attacomsian/jpa/one2many/repositories/BookRepository.java: -------------------------------------------------------------------------------- 1 | package com.attacomsian.jpa.one2many.repositories; 2 | 3 | import com.attacomsian.jpa.one2many.domains.Book; 4 | import org.springframework.data.repository.CrudRepository; 5 | 6 | public interface BookRepository extends CrudRepository { 7 | 8 | Book findByIsbn(String isbn); 9 | } 10 | -------------------------------------------------------------------------------- /spring-data-jpa/jpa-mappings/src/main/java/com/attacomsian/jpa/one2many/repositories/PageRepository.java: -------------------------------------------------------------------------------- 1 | package com.attacomsian.jpa.one2many.repositories; 2 | 3 | import com.attacomsian.jpa.one2many.domains.Book; 4 | import com.attacomsian.jpa.one2many.domains.Page; 5 | import org.springframework.data.domain.Sort; 6 | import org.springframework.data.repository.CrudRepository; 7 | 8 | import java.util.List; 9 | 10 | public interface PageRepository extends CrudRepository { 11 | 12 | List findByBook(Book book, Sort sort); 13 | } 14 | -------------------------------------------------------------------------------- /spring-data-jpa/jpa-mappings/src/main/java/com/attacomsian/jpa/one2one/domains/User.java: -------------------------------------------------------------------------------- 1 | package com.attacomsian.jpa.one2one.domains; 2 | 3 | import javax.persistence.*; 4 | import java.io.Serializable; 5 | import java.util.Objects; 6 | 7 | @Entity 8 | @Table(name = "users") 9 | public class User implements Serializable { 10 | 11 | @Id 12 | @GeneratedValue(strategy = GenerationType.IDENTITY) 13 | private Long id; 14 | 15 | private String name; 16 | private String email; 17 | private String password; 18 | 19 | @OneToOne(mappedBy = "user", fetch = FetchType.LAZY, 20 | cascade = CascadeType.ALL) 21 | private Address address; 22 | 23 | public User() { 24 | } 25 | 26 | public User(String name, String email, String password) { 27 | this.name = name; 28 | this.email = email; 29 | this.password = password; 30 | } 31 | 32 | public Long getId() { 33 | return id; 34 | } 35 | 36 | public void setId(Long id) { 37 | this.id = id; 38 | } 39 | 40 | public String getName() { 41 | return name; 42 | } 43 | 44 | public void setName(String name) { 45 | this.name = name; 46 | } 47 | 48 | public String getEmail() { 49 | return email; 50 | } 51 | 52 | public void setEmail(String email) { 53 | this.email = email; 54 | } 55 | 56 | public String getPassword() { 57 | return password; 58 | } 59 | 60 | public void setPassword(String password) { 61 | this.password = password; 62 | } 63 | 64 | public Address getAddress() { 65 | return address; 66 | } 67 | 68 | public void setAddress(Address address) { 69 | this.address = address; 70 | } 71 | 72 | @Override 73 | public boolean equals(Object o) { 74 | if (this == o) return true; 75 | if (o == null || getClass() != o.getClass()) return false; 76 | User user = (User) o; 77 | return id.equals(user.id); 78 | } 79 | 80 | @Override 81 | public int hashCode() { 82 | return Objects.hash(id); 83 | } 84 | 85 | @Override 86 | public String toString() { 87 | return "User{" + 88 | "id=" + id + 89 | ", name='" + name + '\'' + 90 | ", email='" + email + '\'' + 91 | ", password='" + password + '\'' + 92 | ", address=" + address + 93 | '}'; 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /spring-data-jpa/jpa-mappings/src/main/java/com/attacomsian/jpa/one2one/repositories/AddressRepository.java: -------------------------------------------------------------------------------- 1 | package com.attacomsian.jpa.one2one.repositories; 2 | 3 | import com.attacomsian.jpa.one2one.domains.Address; 4 | import org.springframework.data.repository.CrudRepository; 5 | 6 | public interface AddressRepository extends CrudRepository { 7 | 8 | } 9 | -------------------------------------------------------------------------------- /spring-data-jpa/jpa-mappings/src/main/java/com/attacomsian/jpa/one2one/repositories/UserRepository.java: -------------------------------------------------------------------------------- 1 | package com.attacomsian.jpa.one2one.repositories; 2 | 3 | import com.attacomsian.jpa.one2one.domains.User; 4 | import org.springframework.data.repository.CrudRepository; 5 | 6 | public interface UserRepository extends CrudRepository { 7 | 8 | } 9 | -------------------------------------------------------------------------------- /spring-data-jpa/jpa-mappings/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | # MySQL connection properties 2 | spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver 3 | spring.datasource.username=root 4 | spring.datasource.password= 5 | spring.datasource.url=jdbc:mysql://localhost:3306/testdb?createDatabaseIfNotExist=true&useSSL=false 6 | 7 | # Log JPA queries 8 | # Comment this in production 9 | spring.jpa.show-sql=true 10 | 11 | # Drop and create new tables (create, create-drop, validate, update) 12 | # Only for testing purpose - comment this in production 13 | spring.jpa.hibernate.ddl-auto=create 14 | 15 | # Hibernate SQL dialect 16 | spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect 17 | -------------------------------------------------------------------------------- /spring-data-jpa/jpa-mysql/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | .gradle 3 | build/ 4 | !gradle/wrapper/gradle-wrapper.jar 5 | !**/src/main/** 6 | !**/src/test/** 7 | 8 | ### STS ### 9 | .apt_generated 10 | .classpath 11 | .factorypath 12 | .project 13 | .settings 14 | .springBeans 15 | .sts4-cache 16 | 17 | ### IntelliJ IDEA ### 18 | .idea 19 | *.iws 20 | *.iml 21 | *.ipr 22 | out/ 23 | 24 | ### NetBeans ### 25 | /nbproject/private/ 26 | /nbbuild/ 27 | /dist/ 28 | /nbdist/ 29 | /.nb-gradle/ 30 | 31 | ### VS Code ### 32 | .vscode/ 33 | -------------------------------------------------------------------------------- /spring-data-jpa/jpa-mysql/README.md: -------------------------------------------------------------------------------- 1 | # Accessing Data with Spring Data JPA and MySQL 2 | 3 | For step-by-step instructions, please check out [blog post](https://attacomsian.com/blog/accessing-data-spring-data-jpa-mysql). 4 | -------------------------------------------------------------------------------- /spring-data-jpa/jpa-mysql/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'org.springframework.boot' version '2.1.9.RELEASE' 3 | id 'io.spring.dependency-management' version '1.0.8.RELEASE' 4 | id 'java' 5 | } 6 | 7 | group = 'com.attacomsian' 8 | version = '0.0.1-SNAPSHOT' 9 | sourceCompatibility = '1.8' 10 | 11 | repositories { 12 | mavenCentral() 13 | } 14 | 15 | dependencies { 16 | implementation 'org.springframework.boot:spring-boot-starter-data-jpa' 17 | runtimeOnly 'mysql:mysql-connector-java' 18 | } 19 | -------------------------------------------------------------------------------- /spring-data-jpa/jpa-mysql/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/attacomsian/code-examples/e48ae7eb3ff05aeb5f47016fe8e44c6341e7d005/spring-data-jpa/jpa-mysql/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /spring-data-jpa/jpa-mysql/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /spring-data-jpa/jpa-mysql/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'jpa-mysql' 2 | -------------------------------------------------------------------------------- /spring-data-jpa/jpa-mysql/src/main/java/com/attacomsian/jpa/domains/Note.java: -------------------------------------------------------------------------------- 1 | package com.attacomsian.jpa.domains; 2 | 3 | import javax.persistence.*; 4 | import java.util.Date; 5 | import java.util.Objects; 6 | 7 | @Entity 8 | @Table(name = "notes") 9 | public class Note { 10 | 11 | @Id 12 | @GeneratedValue(strategy = GenerationType.IDENTITY) 13 | private Long id; 14 | private String title; 15 | private String content; 16 | private Date created; 17 | 18 | public Note() { 19 | } 20 | 21 | public Note(String title, String content, Date created) { 22 | this.title = title; 23 | this.content = content; 24 | this.created = created; 25 | } 26 | 27 | public Long getId() { 28 | return id; 29 | } 30 | 31 | public void setId(Long id) { 32 | this.id = id; 33 | } 34 | 35 | public String getTitle() { 36 | return title; 37 | } 38 | 39 | public void setTitle(String title) { 40 | this.title = title; 41 | } 42 | 43 | public String getContent() { 44 | return content; 45 | } 46 | 47 | public void setContent(String content) { 48 | this.content = content; 49 | } 50 | 51 | public Date getCreated() { 52 | return created; 53 | } 54 | 55 | public void setCreated(Date created) { 56 | this.created = created; 57 | } 58 | 59 | @Override 60 | public boolean equals(Object o) { 61 | if (this == o) return true; 62 | if (o == null || getClass() != o.getClass()) return false; 63 | Note note = (Note) o; 64 | return id.equals(note.id); 65 | } 66 | 67 | @Override 68 | public int hashCode() { 69 | return Objects.hash(id); 70 | } 71 | 72 | @Override 73 | public String toString() { 74 | return "Note{" + 75 | "id=" + id + 76 | ", title='" + title + '\'' + 77 | ", content='" + content + '\'' + 78 | ", created=" + created + 79 | '}'; 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /spring-data-jpa/jpa-mysql/src/main/java/com/attacomsian/jpa/repositories/NoteRepository.java: -------------------------------------------------------------------------------- 1 | package com.attacomsian.jpa.repositories; 2 | 3 | import com.attacomsian.jpa.domains.Note; 4 | import org.springframework.data.repository.CrudRepository; 5 | 6 | import java.util.List; 7 | 8 | public interface NoteRepository extends CrudRepository { 9 | 10 | List findByTitleContaining(String title); 11 | 12 | } 13 | -------------------------------------------------------------------------------- /spring-data-jpa/jpa-mysql/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | # MySQL connection properties 2 | spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver 3 | spring.datasource.username=root 4 | spring.datasource.password= 5 | spring.datasource.url=jdbc:mysql://localhost:3306/testdb?createDatabaseIfNotExist=true&useSSL=false 6 | 7 | # Log JPA queries 8 | # Comment this in production 9 | spring.jpa.show-sql=true 10 | 11 | # Drop and create new tables 12 | # Only for testing purpose - comment this in production 13 | spring.jpa.hibernate.ddl-auto=create 14 | 15 | # Hibernate SQL dialect 16 | spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect -------------------------------------------------------------------------------- /spring-data-jpa/jpa-pagination/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | .gradle 3 | build/ 4 | !gradle/wrapper/gradle-wrapper.jar 5 | !**/src/main/** 6 | !**/src/test/** 7 | 8 | ### STS ### 9 | .apt_generated 10 | .classpath 11 | .factorypath 12 | .project 13 | .settings 14 | .springBeans 15 | .sts4-cache 16 | 17 | ### IntelliJ IDEA ### 18 | .idea 19 | *.iws 20 | *.iml 21 | *.ipr 22 | out/ 23 | 24 | ### NetBeans ### 25 | /nbproject/private/ 26 | /nbbuild/ 27 | /dist/ 28 | /nbdist/ 29 | /.nb-gradle/ 30 | 31 | ### VS Code ### 32 | .vscode/ 33 | -------------------------------------------------------------------------------- /spring-data-jpa/jpa-pagination/README.md: -------------------------------------------------------------------------------- 1 | # Pagination with Spring Data JPA 2 | 3 | For step-by-step instructions, please check out [blog post](https://attacomsian.com/blog/spring-data-jpa-pagination). 4 | -------------------------------------------------------------------------------- /spring-data-jpa/jpa-pagination/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'org.springframework.boot' version '2.1.9.RELEASE' 3 | id 'io.spring.dependency-management' version '1.0.8.RELEASE' 4 | id 'java' 5 | } 6 | 7 | group = 'com.attacomsian' 8 | version = '0.0.1-SNAPSHOT' 9 | sourceCompatibility = '1.8' 10 | 11 | repositories { 12 | mavenCentral() 13 | } 14 | 15 | dependencies { 16 | implementation 'org.springframework.boot:spring-boot-starter-data-jpa' 17 | runtimeOnly 'com.h2database:h2' 18 | } 19 | -------------------------------------------------------------------------------- /spring-data-jpa/jpa-pagination/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/attacomsian/code-examples/e48ae7eb3ff05aeb5f47016fe8e44c6341e7d005/spring-data-jpa/jpa-pagination/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /spring-data-jpa/jpa-pagination/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /spring-data-jpa/jpa-pagination/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'jpa-pagination' 2 | -------------------------------------------------------------------------------- /spring-data-jpa/jpa-pagination/src/main/java/com/attacomsian/jpa/Application.java: -------------------------------------------------------------------------------- 1 | package com.attacomsian.jpa; 2 | 3 | import com.attacomsian.jpa.domains.Person; 4 | import com.attacomsian.jpa.repositories.PersonRepository; 5 | import org.springframework.boot.CommandLineRunner; 6 | import org.springframework.boot.SpringApplication; 7 | import org.springframework.boot.autoconfigure.SpringBootApplication; 8 | import org.springframework.context.annotation.Bean; 9 | import org.springframework.data.domain.*; 10 | 11 | import java.util.Arrays; 12 | import java.util.List; 13 | 14 | @SpringBootApplication 15 | public class Application { 16 | 17 | public static void main(String[] args) { 18 | SpringApplication.run(Application.class, args); 19 | } 20 | 21 | @Bean 22 | public CommandLineRunner demo(PersonRepository personRepository) { 23 | return args -> { 24 | 25 | // create persons 26 | List personList = Arrays.asList( 27 | new Person("John", "Doe", 55), 28 | new Person("Emma", "Watson", 29), 29 | new Person("Jovan", "Hover", 35), 30 | new Person("Atta", "Shah", 30), 31 | new Person("Mike", "Lee", 61) 32 | ); 33 | personRepository.saveAll(personList); 34 | 35 | // get all persons by last name 36 | Pageable pageable = PageRequest.of(0, 3); 37 | Page personPage = personRepository.findByLastName("Doe", pageable); 38 | 39 | // get all persons sorted by their age in the descending order 40 | Pageable pageable2 = PageRequest.of(0, 5, Sort.by("age").descending()); 41 | Page personPage2 = personRepository.findAll(pageable2); 42 | 43 | // skip pagination 44 | Slice personSlice = personRepository.findByAgeBetween(20, 60, Pageable.unpaged()); 45 | }; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /spring-data-jpa/jpa-pagination/src/main/java/com/attacomsian/jpa/domains/Person.java: -------------------------------------------------------------------------------- 1 | package com.attacomsian.jpa.domains; 2 | 3 | import javax.persistence.*; 4 | import java.util.Objects; 5 | 6 | @Entity 7 | @NamedQuery(name = "Person.findByFirstNameNamed", 8 | query = "SELECT p FROM Person p WHERE p.firstName = ?1") 9 | @NamedNativeQuery(name = "Person.findByLastNameNativeNamed", 10 | query = "SELECT * FROM Person p WHERE p.lastName = :lastName") 11 | public class Person { 12 | 13 | @Id 14 | @GeneratedValue(strategy = GenerationType.AUTO) 15 | private Long id; 16 | 17 | private String firstName; 18 | private String lastName; 19 | private int age; 20 | 21 | public Person() { 22 | } 23 | 24 | public Person(String firstName, String lastName, int age) { 25 | this.firstName = firstName; 26 | this.lastName = lastName; 27 | this.age = age; 28 | } 29 | 30 | public Long getId() { 31 | return id; 32 | } 33 | 34 | public void setId(Long id) { 35 | this.id = id; 36 | } 37 | 38 | public String getFirstName() { 39 | return firstName; 40 | } 41 | 42 | public void setFirstName(String firstName) { 43 | this.firstName = firstName; 44 | } 45 | 46 | public String getLastName() { 47 | return lastName; 48 | } 49 | 50 | public void setLastName(String lastName) { 51 | this.lastName = lastName; 52 | } 53 | 54 | public int getAge() { 55 | return age; 56 | } 57 | 58 | public void setAge(int age) { 59 | this.age = age; 60 | } 61 | 62 | @Override 63 | public boolean equals(Object o) { 64 | if (this == o) return true; 65 | if (o == null || getClass() != o.getClass()) return false; 66 | Person person = (Person) o; 67 | return id.equals(person.id); 68 | } 69 | 70 | @Override 71 | public int hashCode() { 72 | return Objects.hash(id); 73 | } 74 | 75 | @Override 76 | public String toString() { 77 | return "Person{" + 78 | "id=" + id + 79 | ", firstName='" + firstName + '\'' + 80 | ", lastName='" + lastName + '\'' + 81 | ", age=" + age + 82 | '}'; 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /spring-data-jpa/jpa-pagination/src/main/java/com/attacomsian/jpa/repositories/PersonRepository.java: -------------------------------------------------------------------------------- 1 | package com.attacomsian.jpa.repositories; 2 | 3 | import com.attacomsian.jpa.domains.Person; 4 | import org.springframework.data.domain.Page; 5 | import org.springframework.data.domain.Pageable; 6 | import org.springframework.data.domain.Slice; 7 | import org.springframework.data.jpa.repository.Query; 8 | import org.springframework.data.repository.PagingAndSortingRepository; 9 | import org.springframework.data.repository.query.Param; 10 | 11 | import java.util.List; 12 | 13 | public interface PersonRepository extends PagingAndSortingRepository { 14 | 15 | Page findByLastName(String lastName, Pageable pageable); 16 | 17 | Slice findByAgeGreaterThan(int age, Pageable pageable); 18 | 19 | // derived queries 20 | 21 | Page findByFirstName(String firstName, Pageable pageable); 22 | 23 | Slice findByAgeBetween(int start, int end, Pageable pageable); 24 | 25 | List findByLastNameIsNotNull(Pageable pageable); 26 | 27 | // custom queries 28 | 29 | @Query("SELECT p FROM Person p WHERE p.lastName = ?1") 30 | Page findByLastNameJPQL(String lastName, Pageable pageable); 31 | 32 | @Query("SELECT p FROM Person p WHERE p.age < :age") 33 | Page findByAgeLessThanJPQL(@Param("age") int page, Pageable pageable); 34 | 35 | @Query(value = "SELECT * FROM Person p WHERE p.firstName = :firstName", 36 | countQuery = "SELECT count(*) Person p WHERE p.firstName = :firstName", 37 | nativeQuery = true) 38 | Page findByFirstNameNativeSQL(@Param("firstName") String firstName, Pageable pageable); 39 | 40 | // named queries 41 | 42 | Page findByFirstNameNamed(String firstName, Pageable pageable); 43 | 44 | @Query(countQuery = "SELECT count(*) Person p WHERE p.lastName = :lastName", 45 | nativeQuery = true) 46 | Page findByLastNameNativeNamed(@Param("lastName") String lastName, Pageable pageable); 47 | } 48 | -------------------------------------------------------------------------------- /spring-data-jpa/jpa-pagination/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /spring-data-jpa/jpa-queries/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | .gradle 3 | build/ 4 | !gradle/wrapper/gradle-wrapper.jar 5 | !**/src/main/** 6 | !**/src/test/** 7 | 8 | ### STS ### 9 | .apt_generated 10 | .classpath 11 | .factorypath 12 | .project 13 | .settings 14 | .springBeans 15 | .sts4-cache 16 | 17 | ### IntelliJ IDEA ### 18 | .idea 19 | *.iws 20 | *.iml 21 | *.ipr 22 | out/ 23 | 24 | ### NetBeans ### 25 | /nbproject/private/ 26 | /nbbuild/ 27 | /dist/ 28 | /nbdist/ 29 | /.nb-gradle/ 30 | 31 | ### VS Code ### 32 | .vscode/ 33 | -------------------------------------------------------------------------------- /spring-data-jpa/jpa-queries/README.md: -------------------------------------------------------------------------------- 1 | # Spring Data JPA Query Creation Articles 2 | 3 | - [Derived Query Methods in Spring Data JPA](https://attacomsian.com/blog/derived-query-methods-spring-data-jpa) 4 | - [Spring Data JPA Custom Queries with the @Query Annotation](https://attacomsian.com/blog/spring-data-jpa-query-annotation) 5 | - [How to Use Spring Data JPA Named Queries](https://attacomsian.com/blog/spring-data-jpa-named-queries) 6 | -------------------------------------------------------------------------------- /spring-data-jpa/jpa-queries/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'org.springframework.boot' version '2.1.9.RELEASE' 3 | id 'io.spring.dependency-management' version '1.0.8.RELEASE' 4 | id 'java' 5 | } 6 | 7 | group = 'com.attacomsian' 8 | version = '0.0.1-SNAPSHOT' 9 | sourceCompatibility = '1.8' 10 | 11 | repositories { 12 | mavenCentral() 13 | } 14 | 15 | dependencies { 16 | implementation 'org.springframework.boot:spring-boot-starter-data-jpa' 17 | runtimeOnly 'com.h2database:h2' 18 | } 19 | -------------------------------------------------------------------------------- /spring-data-jpa/jpa-queries/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/attacomsian/code-examples/e48ae7eb3ff05aeb5f47016fe8e44c6341e7d005/spring-data-jpa/jpa-queries/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /spring-data-jpa/jpa-queries/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /spring-data-jpa/jpa-queries/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'jpa-queries' 2 | -------------------------------------------------------------------------------- /spring-data-jpa/jpa-queries/src/main/java/com/attacomsian/jpa/custom/domains/Note.java: -------------------------------------------------------------------------------- 1 | package com.attacomsian.jpa.custom.domains; 2 | 3 | import javax.persistence.*; 4 | import java.util.Date; 5 | import java.util.Objects; 6 | 7 | @Entity 8 | public class Note { 9 | 10 | @Id 11 | @GeneratedValue(strategy = GenerationType.AUTO) 12 | private Long id; 13 | private String title; 14 | private int priority; 15 | private boolean featured; 16 | private Date created; 17 | 18 | public Note() { 19 | } 20 | 21 | public Note(String title, int priority, boolean featured, Date created) { 22 | this.title = title; 23 | this.priority = priority; 24 | this.featured = featured; 25 | this.created = created; 26 | } 27 | 28 | public Long getId() { 29 | return id; 30 | } 31 | 32 | public void setId(Long id) { 33 | this.id = id; 34 | } 35 | 36 | public String getTitle() { 37 | return title; 38 | } 39 | 40 | public void setTitle(String title) { 41 | this.title = title; 42 | } 43 | 44 | public int getPriority() { 45 | return priority; 46 | } 47 | 48 | public void setPriority(int priority) { 49 | this.priority = priority; 50 | } 51 | 52 | public boolean isFeatured() { 53 | return featured; 54 | } 55 | 56 | public void setFeatured(boolean featured) { 57 | this.featured = featured; 58 | } 59 | 60 | public Date getCreated() { 61 | return created; 62 | } 63 | 64 | public void setCreated(Date created) { 65 | this.created = created; 66 | } 67 | 68 | @Override 69 | public boolean equals(Object o) { 70 | if (this == o) return true; 71 | if (o == null || getClass() != o.getClass()) return false; 72 | Note note = (Note) o; 73 | return id.equals(note.id); 74 | } 75 | 76 | @Override 77 | public int hashCode() { 78 | return Objects.hash(id); 79 | } 80 | 81 | @Override 82 | public String toString() { 83 | return "Note{" + 84 | "id=" + id + 85 | ", title='" + title + '\'' + 86 | ", priority=" + priority + 87 | ", featured=" + featured + 88 | ", created=" + created + 89 | '}'; 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /spring-data-jpa/jpa-queries/src/main/java/com/attacomsian/jpa/named/repositories/BookRepository.java: -------------------------------------------------------------------------------- 1 | package com.attacomsian.jpa.named.repositories; 2 | 3 | import com.attacomsian.jpa.named.domains.Book; 4 | import org.springframework.data.jpa.repository.Query; 5 | import org.springframework.data.repository.CrudRepository; 6 | import org.springframework.data.repository.query.Param; 7 | 8 | import java.util.List; 9 | 10 | public interface BookRepository extends CrudRepository { 11 | 12 | // named queries declared in `jpa-named-queries.properties` file 13 | 14 | List findAllNamedFile(); 15 | 16 | List findByTitleNamedFile(String title); 17 | 18 | Book findByIsbnNamedFile(String isbn); 19 | 20 | @Query(nativeQuery = true) 21 | List findByTitleNativeNamedFile(@Param("title") String title); 22 | 23 | // named queries declared in `orm.xml` file 24 | 25 | List findAllXML(); 26 | 27 | List findByTitleContainingXML(String title); 28 | 29 | @Query(nativeQuery = true) 30 | List findByIsbnNativeXML(@Param("isbn") String isbn); 31 | 32 | // named queries declared with `@NamedQuery` 33 | 34 | List findAllJPQL(); 35 | 36 | List findByTitleJPQL(String title); 37 | 38 | List findByTitleAndPagesGreaterThanJPQL(@Param("title") String title, @Param("pages") int pages); 39 | 40 | // named queries declared with `@NamedNativeQuery` 41 | 42 | @Query(nativeQuery = true) 43 | List findAllNative(); 44 | 45 | @Query(nativeQuery = true) 46 | List findByIsbnNative(@Param("isbn") String isbn); 47 | } 48 | -------------------------------------------------------------------------------- /spring-data-jpa/jpa-queries/src/main/resources/META-INF/jpa-named-queries.properties: -------------------------------------------------------------------------------- 1 | # find all books order by title descending 2 | Book.findAllNamedFile=SELECT b FROM Book b ORDER BY b.title DESC 3 | 4 | # find books by title 5 | Book.findByTitleNamedFile=SELECT b FROM Book b WHERE b.title = ?1 6 | 7 | # find a book by isbn 8 | Book.findByIsbnNamedFile=SELECT b FROM Book b WHERE b.isbn = ?1 9 | 10 | # native SQL query to find books by title 11 | Book.findByTitleNativeNamedFile=SELECT * FROM book b WHERE b.title = :title -------------------------------------------------------------------------------- /spring-data-jpa/jpa-queries/src/main/resources/META-INF/orm.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | SELECT b FROM Book b ORDER BY b.pages DESC 10 | 11 | 12 | 13 | 14 | SELECT b FROM Book b WHERE b.title LIKE ?1 15 | 16 | 17 | 18 | 20 | SELECT * FROM book b WHERE b.isbn = :isbn 21 | 22 | 23 | -------------------------------------------------------------------------------- /spring-data-jpa/jpa-queries/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | # Log JPA queries 2 | # Comment this in production 3 | spring.jpa.show-sql=true 4 | -------------------------------------------------------------------------------- /spring-data-jpa/jpa-sorting/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | .gradle 3 | build/ 4 | !gradle/wrapper/gradle-wrapper.jar 5 | !**/src/main/** 6 | !**/src/test/** 7 | 8 | ### STS ### 9 | .apt_generated 10 | .classpath 11 | .factorypath 12 | .project 13 | .settings 14 | .springBeans 15 | .sts4-cache 16 | 17 | ### IntelliJ IDEA ### 18 | .idea 19 | *.iws 20 | *.iml 21 | *.ipr 22 | out/ 23 | 24 | ### NetBeans ### 25 | /nbproject/private/ 26 | /nbbuild/ 27 | /dist/ 28 | /nbdist/ 29 | /.nb-gradle/ 30 | 31 | ### VS Code ### 32 | .vscode/ 33 | -------------------------------------------------------------------------------- /spring-data-jpa/jpa-sorting/README.md: -------------------------------------------------------------------------------- 1 | # Sorting Query Results with Spring Data JPA 2 | 3 | For step-by-step instructions, please check out [blog post](https://attacomsian.com/blog/spring-data-jpa-sorting). 4 | -------------------------------------------------------------------------------- /spring-data-jpa/jpa-sorting/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'org.springframework.boot' version '2.1.9.RELEASE' 3 | id 'io.spring.dependency-management' version '1.0.8.RELEASE' 4 | id 'java' 5 | } 6 | 7 | group = 'com.attacomsian' 8 | version = '0.0.1-SNAPSHOT' 9 | sourceCompatibility = '1.8' 10 | 11 | repositories { 12 | mavenCentral() 13 | } 14 | 15 | dependencies { 16 | implementation 'org.springframework.boot:spring-boot-starter-data-jpa' 17 | runtimeOnly 'com.h2database:h2' 18 | } 19 | -------------------------------------------------------------------------------- /spring-data-jpa/jpa-sorting/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/attacomsian/code-examples/e48ae7eb3ff05aeb5f47016fe8e44c6341e7d005/spring-data-jpa/jpa-sorting/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /spring-data-jpa/jpa-sorting/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /spring-data-jpa/jpa-sorting/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'jpa-sorting' 2 | -------------------------------------------------------------------------------- /spring-data-jpa/jpa-sorting/src/main/java/com/attacomsian/jpa/Application.java: -------------------------------------------------------------------------------- 1 | package com.attacomsian.jpa; 2 | 3 | import com.attacomsian.jpa.domains.Employee; 4 | import com.attacomsian.jpa.repositories.EmployeeRepository; 5 | import org.springframework.boot.CommandLineRunner; 6 | import org.springframework.boot.SpringApplication; 7 | import org.springframework.boot.autoconfigure.SpringBootApplication; 8 | import org.springframework.context.annotation.Bean; 9 | import org.springframework.data.domain.Sort; 10 | 11 | import java.util.Arrays; 12 | import java.util.List; 13 | 14 | @SpringBootApplication 15 | public class Application { 16 | 17 | public static void main(String[] args) { 18 | SpringApplication.run(Application.class, args); 19 | } 20 | 21 | @Bean 22 | public CommandLineRunner sortingDemo(EmployeeRepository employeeRepository) { 23 | return args -> { 24 | // create new employees 25 | List list = Arrays.asList( 26 | new Employee("John", "Doe", 45, 8000), 27 | new Employee("Mike", "Hassan", 55, 6500), 28 | new Employee("Emma", "Doe", 35, 4580), 29 | new Employee("Ali", "Obray", 21, 3200), 30 | new Employee("Beanca", "Lee", 21, 3200) 31 | ); 32 | employeeRepository.saveAll(list); 33 | 34 | // find all users 35 | // Iterable emps = employeeRepository.findAll(Sort.by("age", "salary").descending()); 36 | 37 | // find users by last name 38 | // Sort sort = Sort.by("salary").descending().and(Sort.by("firstName")); 39 | // List employees = employeeRepository.findByLastName("Doe", sort); 40 | 41 | Sort sort = Sort.by("salary").descending().and(Sort.by("firstName")) 42 | .and(Sort.by("age").descending()).and(Sort.by("lastName").ascending()); 43 | List employees = employeeRepository.findBySalaryRange(100, 10000, sort); 44 | 45 | // omit sorting 46 | Iterable emps = employeeRepository.findAll(Sort.unsorted()); 47 | 48 | // print employees 49 | employees.forEach(emp -> { 50 | System.out.println(emp.toString()); 51 | }); 52 | }; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /spring-data-jpa/jpa-sorting/src/main/java/com/attacomsian/jpa/repositories/EmployeeRepository.java: -------------------------------------------------------------------------------- 1 | package com.attacomsian.jpa.repositories; 2 | 3 | import com.attacomsian.jpa.domains.Employee; 4 | import org.springframework.data.domain.Sort; 5 | import org.springframework.data.jpa.repository.Query; 6 | import org.springframework.data.repository.PagingAndSortingRepository; 7 | import org.springframework.data.repository.query.Param; 8 | 9 | import java.util.List; 10 | 11 | public interface EmployeeRepository extends PagingAndSortingRepository { 12 | 13 | // static sorting 14 | List findByOrderBySalaryAsc(); 15 | 16 | List findByOrderBySalaryDesc(); 17 | 18 | List findByLastNameOrderByAgeDesc(String lastName); 19 | 20 | List findByOrderByLastNameAscSalaryDesc(); 21 | 22 | @Query("SELECT e FROM Employee e WHERE e.salary > ?1 ORDER BY e.age DESC") 23 | List findBySalaryGreaterThanJPQL(double salary); 24 | 25 | @Query(value = "SELECT * FROM Employee e WHERE e.fistName = :firstName ORDER BY e.salary ASC", 26 | nativeQuery = true) 27 | List findByFirstNameNativeSQL(@Param("firstName") String firstName); 28 | 29 | List findByAgeGreaterThanNamedJPQL(@Param("age") int age); 30 | 31 | @Query(nativeQuery = true) 32 | List findAllNamedNativeSQL(); 33 | 34 | // dynamic sorting 35 | List findByLastName(String lastName, Sort sort); 36 | 37 | List findByFirstNameAndSalaryLessThan(String lastName, double salary, Sort sort); 38 | 39 | @Query("SELECT e FROM Employee e WHERE e.salary > ?1 AND e.salary < ?2") 40 | List findBySalaryRange(double start, double end, Sort sort); 41 | } 42 | -------------------------------------------------------------------------------- /spring-data-jpa/jpa-sorting/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /spring-data-jpa/jpa-specifications/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | .gradle 3 | build/ 4 | !gradle/wrapper/gradle-wrapper.jar 5 | !**/src/main/** 6 | !**/src/test/** 7 | 8 | ### STS ### 9 | .apt_generated 10 | .classpath 11 | .factorypath 12 | .project 13 | .settings 14 | .springBeans 15 | .sts4-cache 16 | 17 | ### IntelliJ IDEA ### 18 | .idea 19 | *.iws 20 | *.iml 21 | *.ipr 22 | out/ 23 | 24 | ### NetBeans ### 25 | /nbproject/private/ 26 | /nbbuild/ 27 | /dist/ 28 | /nbdist/ 29 | /.nb-gradle/ 30 | 31 | ### VS Code ### 32 | .vscode/ 33 | -------------------------------------------------------------------------------- /spring-data-jpa/jpa-specifications/README.md: -------------------------------------------------------------------------------- 1 | # Dynamic Queries with Spring Data JPA Specifications 2 | 3 | For step-by-step instructions, please check out [blog post](https://attacomsian.com/blog/spring-data-jpa-specifications). 4 | -------------------------------------------------------------------------------- /spring-data-jpa/jpa-specifications/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'org.springframework.boot' version '2.2.0.RELEASE' 3 | id 'io.spring.dependency-management' version '1.0.8.RELEASE' 4 | id 'java' 5 | } 6 | 7 | group = 'com.attacomsian' 8 | version = '0.0.1-SNAPSHOT' 9 | sourceCompatibility = '1.8' 10 | 11 | repositories { 12 | mavenCentral() 13 | } 14 | 15 | dependencies { 16 | implementation 'org.springframework.boot:spring-boot-starter-data-jpa' 17 | runtimeOnly 'com.h2database:h2' 18 | } 19 | -------------------------------------------------------------------------------- /spring-data-jpa/jpa-specifications/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/attacomsian/code-examples/e48ae7eb3ff05aeb5f47016fe8e44c6341e7d005/spring-data-jpa/jpa-specifications/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /spring-data-jpa/jpa-specifications/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /spring-data-jpa/jpa-specifications/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'jpa-specifications' 2 | -------------------------------------------------------------------------------- /spring-data-jpa/jpa-specifications/src/main/java/com/attacomsian/jpa/repositories/MovieRepository.java: -------------------------------------------------------------------------------- 1 | package com.attacomsian.jpa.repositories; 2 | 3 | import com.attacomsian.jpa.domains.Movie; 4 | import org.springframework.data.jpa.repository.JpaSpecificationExecutor; 5 | import org.springframework.data.repository.CrudRepository; 6 | 7 | public interface MovieRepository extends CrudRepository, 8 | JpaSpecificationExecutor { 9 | 10 | // TODO: add queries 11 | } 12 | -------------------------------------------------------------------------------- /spring-data-jpa/jpa-specifications/src/main/java/com/attacomsian/jpa/repositories/specs/SearchCriteria.java: -------------------------------------------------------------------------------- 1 | package com.attacomsian.jpa.repositories.specs; 2 | 3 | public class SearchCriteria { 4 | private String key; 5 | private Object value; 6 | private SearchOperation operation; 7 | 8 | public SearchCriteria() { 9 | } 10 | 11 | public SearchCriteria(String key, Object value, SearchOperation operation) { 12 | this.key = key; 13 | this.value = value; 14 | this.operation = operation; 15 | } 16 | 17 | // getters and setters, equals(), toString(), ... (omitted for brevity) 18 | 19 | public String getKey() { 20 | return key; 21 | } 22 | 23 | public void setKey(String key) { 24 | this.key = key; 25 | } 26 | 27 | public Object getValue() { 28 | return value; 29 | } 30 | 31 | public void setValue(Object value) { 32 | this.value = value; 33 | } 34 | 35 | public SearchOperation getOperation() { 36 | return operation; 37 | } 38 | 39 | public void setOperation(SearchOperation operation) { 40 | this.operation = operation; 41 | } 42 | 43 | @Override 44 | public String toString() { 45 | return "SearchCriteria{" + 46 | "key='" + key + '\'' + 47 | ", value=" + value + 48 | ", operation=" + operation + 49 | '}'; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /spring-data-jpa/jpa-specifications/src/main/java/com/attacomsian/jpa/repositories/specs/SearchOperation.java: -------------------------------------------------------------------------------- 1 | package com.attacomsian.jpa.repositories.specs; 2 | 3 | public enum SearchOperation { 4 | GREATER_THAN, 5 | LESS_THAN, 6 | GREATER_THAN_EQUAL, 7 | LESS_THAN_EQUAL, 8 | NOT_EQUAL, 9 | EQUAL, 10 | MATCH, 11 | MATCH_START, 12 | MATCH_END, 13 | IN, 14 | NOT_IN 15 | } 16 | -------------------------------------------------------------------------------- /spring-data-jpa/jpa-specifications/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /thymeleaf/get-started/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | .gradle 3 | build/ 4 | !gradle/wrapper/gradle-wrapper.jar 5 | !**/src/main/** 6 | !**/src/test/** 7 | 8 | ### STS ### 9 | .apt_generated 10 | .classpath 11 | .factorypath 12 | .project 13 | .settings 14 | .springBeans 15 | .sts4-cache 16 | 17 | ### IntelliJ IDEA ### 18 | .idea 19 | *.iws 20 | *.iml 21 | *.ipr 22 | out/ 23 | 24 | ### NetBeans ### 25 | /nbproject/private/ 26 | /nbbuild/ 27 | /dist/ 28 | /nbdist/ 29 | /.nb-gradle/ 30 | 31 | ### VS Code ### 32 | .vscode/ 33 | -------------------------------------------------------------------------------- /thymeleaf/get-started/README.md: -------------------------------------------------------------------------------- 1 | # How to use Thymeleaf with Spring Boot 2 | 3 | For step-by-step instructions, please check out [blog post](https://attacomsian.com/blog/spring-boot-thymeleaf-example). 4 | -------------------------------------------------------------------------------- /thymeleaf/get-started/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'org.springframework.boot' version '2.2.3.RELEASE' 3 | id 'io.spring.dependency-management' version '1.0.8.RELEASE' 4 | id 'java' 5 | } 6 | 7 | group = 'com.attacomsian' 8 | version = '0.0.1-SNAPSHOT' 9 | sourceCompatibility = '1.8' 10 | 11 | repositories { 12 | mavenCentral() 13 | } 14 | 15 | dependencies { 16 | implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' 17 | implementation 'org.springframework.boot:spring-boot-starter-web' 18 | testImplementation('org.springframework.boot:spring-boot-starter-test') { 19 | exclude group: 'org.junit.vintage', module: 'junit-vintage-engine' 20 | } 21 | } 22 | 23 | test { 24 | useJUnitPlatform() 25 | } 26 | -------------------------------------------------------------------------------- /thymeleaf/get-started/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/attacomsian/code-examples/e48ae7eb3ff05aeb5f47016fe8e44c6341e7d005/thymeleaf/get-started/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /thymeleaf/get-started/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.0.1-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /thymeleaf/get-started/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'get-started' 2 | -------------------------------------------------------------------------------- /thymeleaf/get-started/src/main/java/com/attacomsian/getstarted/Application.java: -------------------------------------------------------------------------------- 1 | package com.attacomsian.getstarted; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class Application { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(Application.class, args); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /thymeleaf/get-started/src/main/java/com/attacomsian/getstarted/controllers/IndexController.java: -------------------------------------------------------------------------------- 1 | package com.attacomsian.getstarted.controllers; 2 | 3 | import org.springframework.stereotype.Controller; 4 | import org.springframework.ui.Model; 5 | import org.springframework.web.bind.annotation.GetMapping; 6 | 7 | @Controller 8 | public class IndexController { 9 | 10 | @GetMapping("/") 11 | public String index(Model model) { 12 | 13 | // add `message` attribute 14 | model.addAttribute("message", "Thank you for visiting."); 15 | 16 | // return view name 17 | return "index"; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /thymeleaf/get-started/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | # disable templates caching 2 | # not recommended for production 3 | spring.thymeleaf.cache=false 4 | 5 | # change default templates folder 6 | # spring.thymeleaf.prefix=classpath:/views/ -------------------------------------------------------------------------------- /thymeleaf/get-started/src/main/resources/templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Spring Boot Thymeleaf Web Application 6 | 7 | 8 |

Welcome to Spring Boot Thymeleaf

9 |

10 | Hey there! message 11 |

12 | 13 | -------------------------------------------------------------------------------- /thymeleaf/thymeleaf-forms/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | .gradle 3 | build/ 4 | !gradle/wrapper/gradle-wrapper.jar 5 | !**/src/main/** 6 | !**/src/test/** 7 | 8 | ### STS ### 9 | .apt_generated 10 | .classpath 11 | .factorypath 12 | .project 13 | .settings 14 | .springBeans 15 | .sts4-cache 16 | 17 | ### IntelliJ IDEA ### 18 | .idea 19 | *.iws 20 | *.iml 21 | *.ipr 22 | out/ 23 | 24 | ### NetBeans ### 25 | /nbproject/private/ 26 | /nbbuild/ 27 | /dist/ 28 | /nbdist/ 29 | /.nb-gradle/ 30 | 31 | ### VS Code ### 32 | .vscode/ 33 | -------------------------------------------------------------------------------- /thymeleaf/thymeleaf-forms/README.md: -------------------------------------------------------------------------------- 1 | # HTML Form Handling in Thymeleaf and Spring Boot 2 | 3 | For step-by-step instructions, please check out [blog post](https://attacomsian.com/blog/spring-boot-thymeleaf-form-handling). 4 | -------------------------------------------------------------------------------- /thymeleaf/thymeleaf-forms/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'org.springframework.boot' version '2.2.4.RELEASE' 3 | id 'io.spring.dependency-management' version '1.0.9.RELEASE' 4 | id 'java' 5 | } 6 | 7 | group = 'com.attacmosian' 8 | version = '0.0.1-SNAPSHOT' 9 | sourceCompatibility = '1.8' 10 | 11 | repositories { 12 | mavenCentral() 13 | } 14 | 15 | dependencies { 16 | implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' 17 | implementation 'org.springframework.boot:spring-boot-starter-web' 18 | testImplementation('org.springframework.boot:spring-boot-starter-test') { 19 | exclude group: 'org.junit.vintage', module: 'junit-vintage-engine' 20 | } 21 | } 22 | 23 | test { 24 | useJUnitPlatform() 25 | } 26 | -------------------------------------------------------------------------------- /thymeleaf/thymeleaf-forms/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/attacomsian/code-examples/e48ae7eb3ff05aeb5f47016fe8e44c6341e7d005/thymeleaf/thymeleaf-forms/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /thymeleaf/thymeleaf-forms/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.0.1-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /thymeleaf/thymeleaf-forms/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'thymeleaf-forms' 2 | -------------------------------------------------------------------------------- /thymeleaf/thymeleaf-forms/src/main/java/com/attacmosian/thymeleaf/forms/Application.java: -------------------------------------------------------------------------------- 1 | package com.attacmosian.thymeleaf.forms; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class Application { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(Application.class, args); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /thymeleaf/thymeleaf-forms/src/main/java/com/attacmosian/thymeleaf/forms/controllers/ProjectController.java: -------------------------------------------------------------------------------- 1 | package com.attacmosian.thymeleaf.forms.controllers; 2 | 3 | import com.attacmosian.thymeleaf.forms.domains.Project; 4 | import org.springframework.stereotype.Controller; 5 | import org.springframework.ui.Model; 6 | import org.springframework.web.bind.annotation.GetMapping; 7 | import org.springframework.web.bind.annotation.ModelAttribute; 8 | import org.springframework.web.bind.annotation.PostMapping; 9 | 10 | @Controller 11 | public class ProjectController { 12 | 13 | @GetMapping("/create-project") 14 | public String createProjectForm(Model model) { 15 | 16 | model.addAttribute("project", new Project()); 17 | return "create-project"; 18 | } 19 | 20 | @PostMapping("/save-project") 21 | public String saveProjectSubmission(@ModelAttribute Project project) { 22 | 23 | // TODO: save project in DB here 24 | 25 | return "result"; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /thymeleaf/thymeleaf-forms/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /thymeleaf/thymeleaf-forms/src/main/resources/templates/result.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Result 6 | 7 | 8 | 9 | 10 | 11 |
12 |
13 |
14 |

Result

15 |
16 |

ID:

17 |

Title:

18 |

Type:

19 |

Color:

20 |

Description:

21 |

Days:

22 |

Price:

23 |

Featured:

24 |

Launch Date:

25 |
26 | Add new project 27 |
28 |
29 |
30 | 31 | 32 | -------------------------------------------------------------------------------- /thymeleaf/thymeleaf-layouts/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | .gradle 3 | build/ 4 | !gradle/wrapper/gradle-wrapper.jar 5 | !**/src/main/** 6 | !**/src/test/** 7 | 8 | ### STS ### 9 | .apt_generated 10 | .classpath 11 | .factorypath 12 | .project 13 | .settings 14 | .springBeans 15 | .sts4-cache 16 | 17 | ### IntelliJ IDEA ### 18 | .idea 19 | *.iws 20 | *.iml 21 | *.ipr 22 | out/ 23 | 24 | ### NetBeans ### 25 | /nbproject/private/ 26 | /nbbuild/ 27 | /dist/ 28 | /nbdist/ 29 | /.nb-gradle/ 30 | 31 | ### VS Code ### 32 | .vscode/ 33 | -------------------------------------------------------------------------------- /thymeleaf/thymeleaf-layouts/README.md: -------------------------------------------------------------------------------- 1 | # Working with Thymeleaf Layout Dialect in Spring Boot 2 | 3 | For step-by-step instructions, please check out [blog post](https://attacomsian.com/blog/spring-boot-thymeleaf-layouts). 4 | -------------------------------------------------------------------------------- /thymeleaf/thymeleaf-layouts/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'org.springframework.boot' version '2.2.4.RELEASE' 3 | id 'io.spring.dependency-management' version '1.0.9.RELEASE' 4 | id 'java' 5 | } 6 | 7 | group = 'com.attacomsian' 8 | version = '0.0.1-SNAPSHOT' 9 | sourceCompatibility = '1.8' 10 | 11 | repositories { 12 | mavenCentral() 13 | } 14 | 15 | dependencies { 16 | implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' 17 | implementation 'org.springframework.boot:spring-boot-starter-web' 18 | implementation 'nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect' 19 | 20 | testImplementation('org.springframework.boot:spring-boot-starter-test') { 21 | exclude group: 'org.junit.vintage', module: 'junit-vintage-engine' 22 | } 23 | } 24 | 25 | test { 26 | useJUnitPlatform() 27 | } 28 | -------------------------------------------------------------------------------- /thymeleaf/thymeleaf-layouts/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/attacomsian/code-examples/e48ae7eb3ff05aeb5f47016fe8e44c6341e7d005/thymeleaf/thymeleaf-layouts/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /thymeleaf/thymeleaf-layouts/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.0.1-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /thymeleaf/thymeleaf-layouts/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'thymeleaf-layouts' 2 | -------------------------------------------------------------------------------- /thymeleaf/thymeleaf-layouts/src/main/java/com/attacomsian/thymeleaf/layouts/Application.java: -------------------------------------------------------------------------------- 1 | package com.attacomsian.thymeleaf.layouts; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class Application { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(Application.class, args); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /thymeleaf/thymeleaf-layouts/src/main/java/com/attacomsian/thymeleaf/layouts/controllers/IndexController.java: -------------------------------------------------------------------------------- 1 | package com.attacomsian.thymeleaf.layouts.controllers; 2 | 3 | import org.springframework.stereotype.Controller; 4 | import org.springframework.web.bind.annotation.GetMapping; 5 | 6 | @Controller 7 | public class IndexController { 8 | 9 | @GetMapping("/") 10 | public String homePage() { 11 | return "index"; 12 | } 13 | 14 | @GetMapping("/contact") 15 | public String contactPage() { 16 | return "contact"; 17 | } 18 | 19 | @GetMapping("/about") 20 | public String aboutPage() { 21 | return "about"; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /thymeleaf/thymeleaf-layouts/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /thymeleaf/thymeleaf-layouts/src/main/resources/templates/about.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | About Us 7 | 8 | 9 | 10 |
11 |
12 |
13 |
14 |
15 |

About Us

16 |

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut 17 | labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco 18 | laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in 19 | voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat 20 | non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

21 |
22 |
23 |
24 |
25 |
26 | 27 | 28 | -------------------------------------------------------------------------------- /thymeleaf/thymeleaf-layouts/src/main/resources/templates/contact.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | Contact Us 7 | 8 | 9 | 10 |
11 |
12 |
13 |
14 |
15 |

Contact Us

16 |

Please send us an email at help@example.com.

17 |
18 |
19 |
20 |
21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /thymeleaf/thymeleaf-layouts/src/main/resources/templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | Welcome to Our Site 7 | 8 | 9 | 10 |
11 |
12 |
13 |
14 |
15 |

Welcome to Our Site

16 |

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut 17 | labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco 18 | laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in 19 | voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat 20 | non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

21 |
22 |
23 |
24 |
25 |
26 | 27 | 28 | -------------------------------------------------------------------------------- /thymeleaf/thymeleaf-layouts/src/main/resources/templates/layout.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 36 | 37 | 38 |
39 |

This is filled by the content template.

40 |
41 | 42 | 43 |
44 |
45 |
46 |

© 2020 Business Name. All rights reserved.

47 |
48 |
49 |
50 | 51 | 52 | 53 | 54 | 55 | --------------------------------------------------------------------------------