├── .gitattributes ├── .gitignore ├── .idea └── .gitignore ├── LICENSE ├── README.md ├── async-controller-example ├── pom.xml └── src │ ├── main │ └── java │ │ └── com │ │ └── howtodoinjava │ │ └── springasyncexample │ │ ├── demo1 │ │ └── AsyncDemoApplication.java │ │ └── demo2 │ │ ├── SpringAsyncExampleApplication.java │ │ ├── config │ │ └── AsyncConfig.java │ │ └── web │ │ ├── controller │ │ ├── DataSetController.java │ │ ├── HelloWorldCallableController.java │ │ └── HelloWorldCompletableFutureController.java │ │ ├── model │ │ └── DataSet.java │ │ └── service │ │ └── DataSetService.java │ └── test │ └── java │ └── com │ └── howtodoinjava │ └── springasyncexample │ └── demo2 │ └── web │ └── controller │ ├── DataSetControllerTest.java │ ├── HelloWorldCallableControllerTest.java │ └── HelloWorldCompletableFutureControllerTest.java ├── db.json ├── declarative-http-client-example ├── .gitignore ├── README.md ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── howtodoinjava │ │ │ └── app │ │ │ ├── App.java │ │ │ ├── config │ │ │ ├── DynamicHeaderFilter.java │ │ │ └── WebConfig.java │ │ │ ├── model │ │ │ └── User.java │ │ │ └── web │ │ │ └── UserClient.java │ └── resources │ │ ├── application.properties │ │ └── logback.xml │ └── test │ └── java │ └── com │ └── howtodoinjava │ └── AppTest.java ├── declarative-validation ├── pom.xml └── src │ └── main │ ├── java │ └── com │ │ └── howtodoinjava │ │ └── app │ │ ├── Application.java │ │ ├── exceptions │ │ ├── CustomExceptionHandler.java │ │ ├── ErrorResponse.java │ │ └── RecordNotFoundException.java │ │ ├── model │ │ └── Employee.java │ │ └── web │ │ └── EmployeeController.java │ └── resources │ ├── messages.properties │ └── templates │ └── employee-registration-form.html ├── ehcache-example ├── README.md ├── pom.xml ├── src │ ├── main │ │ ├── java │ │ │ └── com │ │ │ │ └── howtodoinjava │ │ │ │ ├── App.java │ │ │ │ ├── caching │ │ │ │ ├── CacheConfig.java │ │ │ │ └── CustomCacheEventLogger.java │ │ │ │ ├── model │ │ │ │ └── Employee.java │ │ │ │ └── service │ │ │ │ └── EmployeeService.java │ │ └── resources │ │ │ ├── application.properties │ │ │ └── ehcache.xml │ └── test │ │ └── java │ │ └── com │ │ └── howtodoinjava │ │ └── AppTest.java └── target │ └── classes │ ├── application.properties │ └── ehcache.xml ├── inventory-management-app ├── docker-compose.yaml ├── inventory-mgmt-service │ ├── .gitignore │ ├── mvnw │ ├── mvnw.cmd │ ├── pom.xml │ └── src │ │ ├── main │ │ ├── java │ │ │ └── com │ │ │ │ └── howtodoinjava │ │ │ │ └── app │ │ │ │ ├── InventoryMgmtServiceApplication.java │ │ │ │ ├── config │ │ │ │ └── DataSourceConfig.java │ │ │ │ ├── dao │ │ │ │ ├── ItemRepository.java │ │ │ │ └── entity │ │ │ │ │ ├── Item.java │ │ │ │ │ ├── ItemCategory.java │ │ │ │ │ ├── ItemDetail.java │ │ │ │ │ └── Seller.java │ │ │ │ ├── utils │ │ │ │ └── TestDataSetup.java │ │ │ │ └── web │ │ │ │ └── ItemController.java │ │ └── resources │ │ │ ├── application-dev.properties │ │ │ ├── application-prod.properties │ │ │ ├── application.properties │ │ │ └── logback.xml │ │ └── test │ │ ├── java │ │ └── com │ │ │ └── howtodoinjava │ │ │ └── app │ │ │ ├── InventoryMgmtServiceApplicationTests.java │ │ │ ├── dao │ │ │ └── ItemRepositoryTests.java │ │ │ └── web │ │ │ └── ItemControllerTests.java │ │ └── resources │ │ └── application.properties └── inventory-mgmt-ui │ ├── .editorconfig │ ├── .gitignore │ ├── .vscode │ ├── extensions.json │ ├── launch.json │ └── tasks.json │ ├── README.md │ ├── angular.json │ ├── package-lock.json │ ├── package.json │ ├── src │ ├── app │ │ ├── app-routing.module.ts │ │ ├── app.component.css │ │ ├── app.component.html │ │ ├── app.component.spec.ts │ │ ├── app.component.ts │ │ └── app.module.ts │ ├── assets │ │ └── .gitkeep │ ├── favicon.ico │ ├── index.html │ ├── main.ts │ └── styles.css │ ├── tsconfig.app.json │ ├── tsconfig.json │ └── tsconfig.spec.json ├── item-report.jasper ├── jasper-reports-example ├── README.md ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── howtodoinjava │ │ │ └── app │ │ │ ├── App.java │ │ │ ├── dao │ │ │ └── ItemRepository.java │ │ │ ├── jasper │ │ │ └── JasperReportService.java │ │ │ ├── model │ │ │ └── Item.java │ │ │ └── web │ │ │ └── ReportController.java │ └── resources │ │ ├── application.properties │ │ └── item-report.jrxml │ └── test │ └── java │ └── com │ └── howtodoinjava │ └── app │ └── AppTest.java ├── jsp-demo ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── howtodoinjava │ │ │ └── app │ │ │ ├── App.java │ │ │ ├── config │ │ │ └── WebMvcConfig.java │ │ │ ├── model │ │ │ └── Item.java │ │ │ ├── service │ │ │ └── ItemService.java │ │ │ └── web │ │ │ └── ItemController.java │ ├── resources │ │ ├── application.properties │ │ └── static │ │ │ └── css │ │ │ └── style.css │ └── webapp │ │ └── WEB-INF │ │ └── jsp │ │ └── view-items.jsp │ └── test │ └── java │ └── com │ └── howtodoinjava │ └── app │ └── AppTest.java ├── mybatis-example ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── howtodoinjava │ │ │ └── app │ │ │ ├── App.java │ │ │ ├── config │ │ │ └── PersistenceConfig.java │ │ │ ├── mapper │ │ │ └── ToDoMapper.java │ │ │ └── model │ │ │ └── TODO.java │ └── resources │ │ ├── application.properties │ │ ├── data.sql │ │ ├── logback.xml │ │ └── schema.sql │ └── test │ └── java │ └── com │ └── howtodoinjava │ └── AppTest.java ├── pom.xml ├── problem-detail-error-responses-example ├── .gitignore ├── README.md ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── howtodoinjava │ │ │ ├── App.java │ │ │ ├── app │ │ │ └── model │ │ │ │ └── Employee.java │ │ │ ├── errors │ │ │ └── RecordNotFoundException.java │ │ │ └── web │ │ │ ├── EmployeeController.java │ │ │ └── GlobalExceptionHandler.java │ └── resources │ │ └── application.properties │ └── test │ ├── java │ └── com │ │ └── howtodoinjava │ │ ├── AppTest.java │ │ └── web │ │ └── EmployeeControllerTest.java │ └── resources │ └── application-test.properties ├── programmatic-validator ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── howtodoinjava │ │ │ └── app │ │ │ └── customValidator │ │ │ ├── Application.java │ │ │ ├── model │ │ │ ├── Department.java │ │ │ ├── Employee.java │ │ │ └── validation │ │ │ │ ├── DepartmentValidator.java │ │ │ │ ├── EmployeeValidator.java │ │ │ │ └── ValidationErrorCodes.java │ │ │ └── web │ │ │ └── EmployeeController.java │ └── resources │ │ ├── messages.properties │ │ └── templates │ │ └── employee-registration-form.html │ └── test │ └── java │ └── com │ └── howtodoinjava │ └── app │ └── customValidator │ └── model │ └── validation │ └── TestEmployeeValidator.java ├── rest-api-crud-example ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── howtodoinjava │ │ │ ├── App.java │ │ │ ├── dao │ │ │ └── model │ │ │ │ ├── Item.java │ │ │ │ └── ItemRepository.java │ │ │ └── web │ │ │ ├── ItemController.java │ │ │ └── errors │ │ │ ├── ApplicationExceptionHandler.java │ │ │ ├── ErrorResponse.java │ │ │ └── ItemNotFoundException.java │ └── resources │ │ └── application.properties │ └── test │ └── java │ └── com │ └── howtodoinjava │ ├── AppTest.java │ └── web │ └── ItemControllerTest.java ├── rsocket ├── .gitignore ├── README.md ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── howtodoinjava │ │ │ └── app │ │ │ ├── bidirectional │ │ │ ├── App.java │ │ │ ├── controller │ │ │ │ └── LoanCheckController.java │ │ │ └── model │ │ │ │ └── LoanDetails.java │ │ │ ├── fireAndForget │ │ │ ├── App.java │ │ │ ├── controller │ │ │ │ └── EventController.java │ │ │ └── model │ │ │ │ └── Event.java │ │ │ ├── requestResponse │ │ │ ├── App.java │ │ │ └── controller │ │ │ │ └── MessageController.java │ │ │ ├── requestStream │ │ │ ├── App.java │ │ │ ├── controller │ │ │ │ └── StockPriceController.java │ │ │ └── model │ │ │ │ └── StockPrice.java │ │ │ └── rsocketexchange │ │ │ ├── App.java │ │ │ ├── controller │ │ │ └── MessageController.java │ │ │ └── declarativeClient │ │ │ └── MessageService.java │ └── resources │ │ └── application.properties │ └── test │ └── java │ └── com │ └── howtodoinjava │ └── AppTest.java ├── security ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── howtodoinjava │ │ │ └── App.java │ └── resources │ │ └── application.properties │ └── test │ └── java │ └── com │ └── howtodoinjava │ └── AppTest.java ├── soap-client-example ├── pom.xml └── src │ └── main │ ├── java │ ├── META-INF │ │ └── sun-jaxb.episode │ └── com │ │ ├── example │ │ └── howtodoinjava │ │ │ └── schemas │ │ │ └── school │ │ │ ├── ObjectFactory.java │ │ │ ├── Student.java │ │ │ ├── StudentDetailsRequest.java │ │ │ ├── StudentDetailsResponse.java │ │ │ └── package-info.java │ │ └── howtodoinjava │ │ ├── App.java │ │ └── soap │ │ └── client │ │ ├── Config.java │ │ └── SOAPConnector.java │ └── resources │ ├── application.properties │ └── wsdl │ └── studentDetailsWsdl.wsdl ├── soap-ws-example ├── pom.xml └── src │ └── main │ ├── java │ ├── META-INF │ │ └── JAXB │ │ │ └── episode_xjc.xjb │ └── com │ │ └── howtodoinjava │ │ ├── App.java │ │ ├── config │ │ └── SoapConfig.java │ │ ├── endpoints │ │ └── StudentEndpoint.java │ │ ├── repository │ │ └── StudentRepository.java │ │ └── xml │ │ └── school │ │ ├── ObjectFactory.java │ │ ├── Student.java │ │ ├── StudentDetailsRequest.java │ │ ├── StudentDetailsResponse.java │ │ └── package-info.java │ └── resources │ └── student.xsd ├── spring-boot-hateoas ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── howtodoinjava │ │ │ ├── App.java │ │ │ └── rest │ │ │ ├── assembers │ │ │ ├── ActorModelAssembler.java │ │ │ └── AlbumModelAssembler.java │ │ │ ├── entity │ │ │ ├── ActorEntity.java │ │ │ └── AlbumEntity.java │ │ │ ├── model │ │ │ ├── ActorModel.java │ │ │ └── AlbumModel.java │ │ │ ├── repository │ │ │ ├── ActorRepository.java │ │ │ └── AlbumRepository.java │ │ │ └── web │ │ │ └── WebController.java │ └── resources │ │ ├── application.properties │ │ ├── data.sql │ │ └── schema.sql │ └── test │ └── java │ └── com │ └── howtodoinjava │ └── AppTest.java ├── spring-restclient ├── README.md ├── db.json ├── pom.xml └── src │ ├── main │ └── java │ │ └── com │ │ └── howtodoinjava │ │ ├── app │ │ ├── App.java │ │ ├── config │ │ │ └── WebConfig.java │ │ ├── exception │ │ │ └── ApplicationException.java │ │ ├── model │ │ │ └── Employee.java │ │ └── web │ │ │ └── EmployeeController.java │ │ └── webclient │ │ └── demo │ │ └── get │ │ └── Application.java │ └── test │ └── java │ └── com │ └── howtodoinjava │ └── app │ ├── AppTest.java │ └── HttpClientConfig.java ├── structured-logging ├── .gitattributes ├── .gitignore ├── .mvn │ └── wrapper │ │ └── maven-wrapper.properties ├── mvnw ├── mvnw.cmd ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── howtodoinjava │ │ │ └── demo │ │ │ ├── CustomLogFormatter.java │ │ │ └── StructuredLoggingApplication.java │ └── resources │ │ └── application.properties │ └── test │ └── java │ └── com │ └── howtodoinjava │ └── demo │ └── StructuredLoggingApplicationTests.java ├── task-scheduler ├── README.md ├── pom.xml ├── src │ ├── main │ │ ├── java │ │ │ └── com │ │ │ │ └── howtodoinjava │ │ │ │ ├── App.java │ │ │ │ ├── config │ │ │ │ └── SchedulerConfig.java │ │ │ │ └── tasks │ │ │ │ └── Task.java │ │ └── resources │ │ │ └── application.properties │ └── test │ │ └── java │ │ └── com │ │ └── howtodoinjava │ │ └── AppTest.java └── target │ └── classes │ └── application.properties ├── virtual-threads-demo ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── howtodoinjava │ │ │ ├── App.java │ │ │ ├── AppEventListener.java │ │ │ └── config │ │ │ └── AsyncConfig.java │ └── resources │ │ └── application.properties │ └── test │ └── java │ └── com │ └── howtodoinjava │ └── AppTest.java └── webflux-part-event-api-example ├── .gitignore ├── pom.xml └── src ├── main ├── java │ └── com │ │ └── howtodoinjava │ │ ├── App.java │ │ └── app │ │ ├── config │ │ └── WebFuxConfig.java │ │ ├── model │ │ └── FileUploadCommand.java │ │ └── web │ │ └── FileUploadController.java └── resources │ ├── application.properties │ └── spring.png └── test └── java └── com └── howtodoinjava ├── AppTest.java └── web └── FileUploadControllerTest.java /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled class file 2 | *.class 3 | 4 | # Log file 5 | *.log 6 | 7 | # BlueJ files 8 | *.ctxt 9 | 10 | # Mobile Tools for Java (J2ME) 11 | .mtj.tmp/ 12 | 13 | # Package Files # 14 | *.jar 15 | *.war 16 | *.nar 17 | *.ear 18 | *.zip 19 | *.tar.gz 20 | *.rar 21 | *.iml 22 | 23 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 24 | hs_err_pid* 25 | replay_pid* 26 | .idea 27 | /.idea/aws.xml 28 | /.idea/compiler.xml 29 | /.idea/dbnavigator.xml 30 | /.idea/encodings.xml 31 | /.idea/jarRepositories.xml 32 | /.idea/jpa-buddy.xml 33 | /.idea/misc.xml 34 | /.idea/modules.xml 35 | /.idea/Spring-Boot3-Demos.iml 36 | /.idea/uiDesigner.xml 37 | /.idea/vcs.xml 38 | 39 | **/target 40 | 41 | /soap-client-example/src/main/resources/maxresdefault.jpg 42 | -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Spring Boot3 Demos 2 | Spring Boot 3 Demo Projects and Examples 3 | -------------------------------------------------------------------------------- /async-controller-example/pom.xml: -------------------------------------------------------------------------------- 1 | 4 | 4.0.0 5 | 6 | com.howtodoinjava 7 | Spring-Boot3-Demos 8 | 1.0-SNAPSHOT 9 | 10 | 11 | async-controller-example 12 | jar 13 | 14 | async-controller-example 15 | 16 | 17 | UTF-8 18 | 19 | 20 | 21 | 22 | org.springframework.boot 23 | spring-boot-starter-web 24 | 25 | 26 | org.springframework.boot 27 | spring-boot-starter-webflux 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /async-controller-example/src/main/java/com/howtodoinjava/springasyncexample/demo2/SpringAsyncExampleApplication.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.springasyncexample.demo2; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class SpringAsyncExampleApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(SpringAsyncExampleApplication.class, args); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /async-controller-example/src/main/java/com/howtodoinjava/springasyncexample/demo2/config/AsyncConfig.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.springasyncexample.demo2.config; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.scheduling.annotation.EnableAsync; 6 | import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; 7 | import org.springframework.web.servlet.config.annotation.AsyncSupportConfigurer; 8 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; 9 | 10 | @Configuration 11 | @EnableAsync 12 | public class AsyncConfig implements WebMvcConfigurer { 13 | 14 | @Override 15 | public void configureAsyncSupport(AsyncSupportConfigurer configurer) { 16 | 17 | configurer.setTaskExecutor(mvcTaskExecutor()); 18 | configurer.setDefaultTimeout(30_000); 19 | } 20 | 21 | @Bean 22 | public ThreadPoolTaskExecutor mvcTaskExecutor() { 23 | 24 | ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor(); 25 | threadPoolTaskExecutor.setCorePoolSize(10); 26 | threadPoolTaskExecutor.setThreadNamePrefix("mvc-task-"); 27 | return threadPoolTaskExecutor; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /async-controller-example/src/main/java/com/howtodoinjava/springasyncexample/demo2/web/controller/HelloWorldCallableController.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.springasyncexample.demo2.web.controller; 2 | 3 | import org.springframework.web.bind.annotation.GetMapping; 4 | import org.springframework.web.bind.annotation.RestController; 5 | import java.util.concurrent.Callable; 6 | 7 | @RestController 8 | public class HelloWorldCallableController 9 | { 10 | @GetMapping(value = "/testCallable") 11 | public Callable echoHelloWorld() 12 | { 13 | return () -> { 14 | Thread.sleep(5000); 15 | return "Hello World !!"; 16 | }; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /async-controller-example/src/main/java/com/howtodoinjava/springasyncexample/demo2/web/controller/HelloWorldCompletableFutureController.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.springasyncexample.demo2.web.controller; 2 | 3 | import java.util.concurrent.CompletableFuture; 4 | import java.util.concurrent.ThreadLocalRandom; 5 | 6 | import org.springframework.core.task.TaskExecutor; 7 | import org.springframework.web.bind.annotation.GetMapping; 8 | import org.springframework.web.bind.annotation.RestController; 9 | 10 | @RestController 11 | public class HelloWorldCompletableFutureController 12 | { 13 | private final TaskExecutor taskExecutor; 14 | 15 | public HelloWorldCompletableFutureController(TaskExecutor taskExecutor) { 16 | this.taskExecutor = taskExecutor; 17 | } 18 | 19 | @GetMapping(value = "/testCompletableFuture") 20 | public CompletableFuture echoHelloWorld2() { 21 | return CompletableFuture.supplyAsync(() -> { 22 | randomDelay(); 23 | return "Hello World !!"; 24 | }, taskExecutor); 25 | } 26 | 27 | private void randomDelay() { 28 | try { 29 | Thread.sleep(ThreadLocalRandom.current().nextInt(5000)); 30 | } catch (InterruptedException e) { 31 | Thread.currentThread().interrupt(); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /async-controller-example/src/main/java/com/howtodoinjava/springasyncexample/demo2/web/model/DataSet.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.springasyncexample.demo2.web.model; 2 | 3 | import java.math.BigInteger; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | @Data 9 | @AllArgsConstructor 10 | @NoArgsConstructor 11 | public class DataSet { 12 | 13 | private BigInteger id; 14 | private String name; 15 | } 16 | -------------------------------------------------------------------------------- /async-controller-example/src/main/java/com/howtodoinjava/springasyncexample/demo2/web/service/DataSetService.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.springasyncexample.demo2.web.service; 2 | 3 | import com.howtodoinjava.springasyncexample.demo2.web.model.DataSet; 4 | import jakarta.annotation.PostConstruct; 5 | import java.math.BigInteger; 6 | import java.util.ArrayList; 7 | import java.util.Collections; 8 | import java.util.List; 9 | import org.springframework.stereotype.Service; 10 | 11 | @Service 12 | public class DataSetService { 13 | 14 | private final List datasetList = new ArrayList<>(); 15 | 16 | @PostConstruct 17 | public void setup() { 18 | createDataSets(); 19 | } 20 | 21 | public List findAll() { 22 | return Collections.unmodifiableList(datasetList); 23 | } 24 | 25 | private Iterable createDataSets() { 26 | String name = "dummy text_"; 27 | 28 | for (int i = 0; i < 5; i++) { 29 | this.datasetList.add(new DataSet(BigInteger.valueOf(i), name + i)); 30 | } 31 | return datasetList; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /async-controller-example/src/test/java/com/howtodoinjava/springasyncexample/demo2/web/controller/DataSetControllerTest.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.springasyncexample.demo2.web.controller; 2 | 3 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.asyncDispatch; 4 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; 5 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; 6 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.request; 7 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; 8 | 9 | import com.howtodoinjava.springasyncexample.demo2.web.model.DataSet; 10 | import com.howtodoinjava.springasyncexample.demo2.web.service.DataSetService; 11 | import java.math.BigInteger; 12 | import java.util.Arrays; 13 | import org.junit.jupiter.api.Test; 14 | import org.mockito.Mockito; 15 | import org.springframework.beans.factory.annotation.Autowired; 16 | import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; 17 | import org.springframework.boot.test.mock.mockito.MockBean; 18 | import org.springframework.test.web.servlet.MockMvc; 19 | import org.springframework.test.web.servlet.MvcResult; 20 | import org.springframework.test.web.servlet.result.MockMvcResultHandlers; 21 | 22 | @WebMvcTest(DataSetController.class) 23 | public class DataSetControllerTest { 24 | 25 | @Autowired 26 | private MockMvc mockMvc; 27 | 28 | @MockBean 29 | private DataSetService dataSetService; 30 | 31 | @Test 32 | public void testFetchData() throws Exception { 33 | Mockito.when(dataSetService.findAll()).thenReturn(Arrays.asList(new DataSet(BigInteger.valueOf(1), "data"))); 34 | MvcResult mvcResult = mockMvc.perform(get("/fetch-data-sets")).andExpect(request().asyncStarted()) 35 | .andDo(MockMvcResultHandlers.log()).andReturn(); 36 | mockMvc.perform(asyncDispatch(mvcResult)).andDo(MockMvcResultHandlers.log()).andExpect(status().isOk()) 37 | .andExpect(content().json("{\"id\":1,\"name\":\"data\"}")); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /async-controller-example/src/test/java/com/howtodoinjava/springasyncexample/demo2/web/controller/HelloWorldCallableControllerTest.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.springasyncexample.demo2.web.controller; 2 | 3 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.asyncDispatch; 4 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; 5 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; 6 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.request; 7 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; 8 | 9 | import org.junit.jupiter.api.Test; 10 | import org.springframework.beans.factory.annotation.Autowired; 11 | import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; 12 | import org.springframework.test.web.servlet.MockMvc; 13 | import org.springframework.test.web.servlet.MvcResult; 14 | import org.springframework.test.web.servlet.result.MockMvcResultHandlers; 15 | 16 | @WebMvcTest(HelloWorldCallableController.class) 17 | public class HelloWorldCallableControllerTest { 18 | 19 | @Autowired 20 | private MockMvc mockMvc; 21 | 22 | @Test 23 | public void testHelloWorldController() throws Exception { 24 | 25 | MvcResult mvcResult = mockMvc.perform(get("/testCallable")) 26 | .andExpect(request().asyncStarted()) 27 | .andDo(MockMvcResultHandlers.log()) 28 | .andReturn(); 29 | 30 | mockMvc.perform(asyncDispatch(mvcResult)) 31 | .andExpect(status().isOk()) 32 | .andExpect(content().contentTypeCompatibleWith("text/plain")) 33 | .andExpect(content().string("Hello World !!")); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /async-controller-example/src/test/java/com/howtodoinjava/springasyncexample/demo2/web/controller/HelloWorldCompletableFutureControllerTest.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.springasyncexample.demo2.web.controller; 2 | 3 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.asyncDispatch; 4 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; 5 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; 6 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.request; 7 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; 8 | 9 | import org.junit.jupiter.api.Test; 10 | import org.springframework.beans.factory.annotation.Autowired; 11 | import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; 12 | import org.springframework.test.web.servlet.MockMvc; 13 | import org.springframework.test.web.servlet.MvcResult; 14 | import org.springframework.test.web.servlet.result.MockMvcResultHandlers; 15 | 16 | @WebMvcTest(HelloWorldCompletableFutureController.class) 17 | public class HelloWorldCompletableFutureControllerTest { 18 | 19 | @Autowired 20 | private MockMvc mockMvc; 21 | 22 | @Test 23 | public void testHelloWorldController() throws Exception { 24 | MvcResult mvcResult = mockMvc.perform(get("/testCompletableFuture")).andExpect(request().asyncStarted()) 25 | .andDo(MockMvcResultHandlers.log()).andReturn(); 26 | mockMvc.perform(asyncDispatch(mvcResult)).andExpect(status().isOk()) 27 | .andExpect(content().contentTypeCompatibleWith("text/plain")) 28 | .andExpect(content().string("Hello World !!")); 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /db.json: -------------------------------------------------------------------------------- 1 | { 2 | "employees": [ 3 | { 4 | "id": 1, 5 | "name": "Lokesh", 6 | "status": "Active" 7 | }, 8 | { 9 | "id": 2, 10 | "name": "Andy", 11 | "status": "Inactive" 12 | }, 13 | { 14 | "id": 3, 15 | "name": "Brian", 16 | "status": "Active" 17 | }, 18 | { 19 | "id": 4, 20 | "name": "Charles", 21 | "status": "Inactive" 22 | }, 23 | { 24 | "id": 5, 25 | "name": "Lokesh", 26 | "status": "Active" 27 | }, 28 | { 29 | "id": 8, 30 | "name": "Lokesh", 31 | "status": "Active" 32 | }, 33 | { 34 | "id": 9, 35 | "name": "Lokesh", 36 | "status": "Active" 37 | }, 38 | { 39 | "id": 19, 40 | "name": "Lokesh", 41 | "status": "Active" 42 | }, 43 | { 44 | "id": 18, 45 | "name": "Lokesh", 46 | "status": "Active" 47 | }, 48 | { 49 | "id": 190, 50 | "name": "Lokesh", 51 | "status": "Active" 52 | }, 53 | { 54 | "id": 180, 55 | "name": "Lokesh", 56 | "status": "Active" 57 | }, 58 | { 59 | "id": "1900", 60 | "name": "test name", 61 | "status": "active" 62 | }, 63 | { 64 | "id": "tic5EuJ" 65 | }, 66 | { 67 | "id": "lHpVj5O" 68 | }, 69 | { 70 | "id": "wULJO_L" 71 | }, 72 | { 73 | "id": "Sft9IYX" 74 | }, 75 | { 76 | "id": "pltNBl6" 77 | }, 78 | { 79 | "id": "HJiEnlm" 80 | }, 81 | { 82 | "id": "qtg0QSh" 83 | }, 84 | { 85 | "id": "MNa78BD" 86 | } 87 | ] 88 | } -------------------------------------------------------------------------------- /declarative-http-client-example/.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled class file 2 | *.class 3 | 4 | # Log file 5 | *.log 6 | 7 | # BlueJ files 8 | *.ctxt 9 | 10 | # Mobile Tools for Java (J2ME) 11 | .mtj.tmp/ 12 | 13 | # Package Files # 14 | *.jar 15 | *.war 16 | *.nar 17 | *.ear 18 | *.zip 19 | *.tar.gz 20 | *.rar 21 | 22 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 23 | hs_err_pid* 24 | replay_pid* 25 | -------------------------------------------------------------------------------- /declarative-http-client-example/README.md: -------------------------------------------------------------------------------- 1 | # Related Tutorials 2 | 3 | * [Spring Declarative HTTP Client using @HttpExchange](https://howtodoinjava.com/spring-webflux/http-declarative-http-client-httpexchange/) 4 | 5 | -------------------------------------------------------------------------------- /declarative-http-client-example/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 4.0.0 6 | 7 | com.howtodoinjava 8 | declarative-http-client-example 9 | 1.0-SNAPSHOT 10 | problem-detail-error-responses-example 11 | https://howtodoinjava.com 12 | 13 | 14 | com.howtodoinjava 15 | Spring-Boot3-Demos 16 | 1.0-SNAPSHOT 17 | 18 | 19 | 20 | 21 | org.springframework.boot 22 | spring-boot-starter-web 23 | 24 | 25 | org.springframework.boot 26 | spring-boot-starter-webflux 27 | 28 | 29 | org.springframework.boot 30 | spring-boot-devtools 31 | runtime 32 | true 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /declarative-http-client-example/src/main/java/com/howtodoinjava/app/App.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.app; 2 | 3 | import com.howtodoinjava.app.model.User; 4 | import com.howtodoinjava.app.web.UserClient; 5 | import java.util.UUID; 6 | import lombok.extern.slf4j.Slf4j; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.boot.CommandLineRunner; 9 | import org.springframework.boot.SpringApplication; 10 | import org.springframework.boot.autoconfigure.SpringBootApplication; 11 | import reactor.core.publisher.Mono; 12 | 13 | @Slf4j 14 | @SpringBootApplication 15 | public class App implements CommandLineRunner { 16 | 17 | public static void main(String[] args) { 18 | SpringApplication.run(App.class, args); 19 | } 20 | 21 | @Autowired 22 | UserClient userClient; 23 | 24 | @Override 25 | public void run(String... args) throws Exception { 26 | 27 | //Get All Users 28 | String headerValue = UUID.randomUUID().toString(); 29 | userClient.getAll(headerValue).subscribe( 30 | data -> log.info("User: {}", data) 31 | ); 32 | 33 | //Get User By Id 34 | userClient.getById(1L).subscribe( 35 | data -> log.info("User: {}", data) 36 | ); 37 | 38 | //Create a New User 39 | userClient.save(new User(null, "Lokesh", "lokesh", "admin@email.com")) 40 | .log() 41 | .flatMap(user -> { 42 | var uri = user.getHeaders().getLocation().toString(); 43 | var strings = uri.split("/"); 44 | return userClient.getById(Long.valueOf(strings[strings.length - 1])) 45 | .log() 46 | .map(u -> { 47 | log.debug("User: {}", u); 48 | return u; 49 | }); 50 | } 51 | ).subscribe( 52 | data -> log.info("User: {}", data) 53 | ); 54 | 55 | //Delete User By Id 56 | userClient.delete(1L).subscribe( 57 | data -> log.info("User: {}", data) 58 | ); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /declarative-http-client-example/src/main/java/com/howtodoinjava/app/config/DynamicHeaderFilter.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.app.config; 2 | 3 | 4 | import java.time.LocalDateTime; 5 | import org.springframework.stereotype.Component; 6 | import org.springframework.web.reactive.function.client.ClientRequest; 7 | import org.springframework.web.reactive.function.client.ClientResponse; 8 | import org.springframework.web.reactive.function.client.ExchangeFilterFunction; 9 | import org.springframework.web.reactive.function.client.ExchangeFunction; 10 | import reactor.core.publisher.Mono; 11 | 12 | @Component 13 | public class DynamicHeaderFilter implements ExchangeFilterFunction { 14 | 15 | @Override 16 | public Mono filter(ClientRequest clientRequest, ExchangeFunction nextFilter) { 17 | 18 | // Create a new ClientRequest with the additional headers 19 | ClientRequest modifiedRequest = ClientRequest 20 | .from(clientRequest) 21 | .header("X-REQUEST-TIMESTAMP", LocalDateTime.now().toString()) 22 | .build(); 23 | 24 | return nextFilter.exchange(modifiedRequest); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /declarative-http-client-example/src/main/java/com/howtodoinjava/app/config/WebConfig.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.app.config; 2 | 3 | import com.fasterxml.jackson.databind.ObjectMapper; 4 | import com.howtodoinjava.app.web.UserClient; 5 | import lombok.SneakyThrows; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.context.annotation.Bean; 8 | import org.springframework.context.annotation.Configuration; 9 | import org.springframework.web.reactive.function.client.ExchangeStrategies; 10 | import org.springframework.web.reactive.function.client.WebClient; 11 | import org.springframework.web.reactive.function.client.support.WebClientAdapter; 12 | import org.springframework.web.service.invoker.HttpServiceProxyFactory; 13 | 14 | @Configuration 15 | public class WebConfig { 16 | 17 | @Autowired 18 | DynamicHeaderFilter dynamicHeaderFilter; 19 | 20 | @Bean 21 | WebClient webClient(/*ObjectMapper objectMapper*/) { 22 | return WebClient.builder() 23 | .exchangeStrategies(ExchangeStrategies.builder().codecs(c -> 24 | c.defaultCodecs().enableLoggingRequestDetails(true)).build() 25 | ) 26 | .defaultHeaders(header -> header.setBasicAuth("username", "password")) 27 | .filter(dynamicHeaderFilter) 28 | .baseUrl("https://jsonplaceholder.typicode.com/") 29 | .build(); 30 | } 31 | 32 | @SneakyThrows 33 | @Bean 34 | UserClient postClient(WebClient webClient) { 35 | HttpServiceProxyFactory httpServiceProxyFactory = 36 | HttpServiceProxyFactory.builderFor(WebClientAdapter.create(webClient)) 37 | .build(); 38 | return httpServiceProxyFactory.createClient(UserClient.class); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /declarative-http-client-example/src/main/java/com/howtodoinjava/app/model/User.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.app.model; 2 | 3 | public record User(Long id, 4 | String name, 5 | String username, 6 | String email 7 | ) { 8 | 9 | } 10 | -------------------------------------------------------------------------------- /declarative-http-client-example/src/main/java/com/howtodoinjava/app/web/UserClient.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.app.web; 2 | 3 | import com.howtodoinjava.app.model.User; 4 | import org.springframework.http.ResponseEntity; 5 | import org.springframework.web.bind.annotation.PathVariable; 6 | import org.springframework.web.bind.annotation.RequestBody; 7 | import org.springframework.web.bind.annotation.RequestHeader; 8 | import org.springframework.web.service.annotation.DeleteExchange; 9 | import org.springframework.web.service.annotation.GetExchange; 10 | import org.springframework.web.service.annotation.HttpExchange; 11 | import org.springframework.web.service.annotation.PostExchange; 12 | import org.springframework.web.service.annotation.PutExchange; 13 | import reactor.core.publisher.Flux; 14 | import reactor.core.publisher.Mono; 15 | 16 | @HttpExchange(url = "/users", accept = "application/json", contentType = "application/json") 17 | public interface UserClient { 18 | 19 | @GetExchange("/") 20 | Flux getAll(@RequestHeader("X-LOCAL-HEADER") String headerName); 21 | 22 | @GetExchange("/{id}") 23 | Mono getById(@PathVariable("id") Long id); 24 | 25 | @PostExchange("/") 26 | Mono> save(@RequestBody User user); 27 | 28 | @PutExchange("/{id}") 29 | Mono> update(@PathVariable Long id, @RequestBody User user); 30 | 31 | @DeleteExchange("/{id}") 32 | Mono> delete(@PathVariable Long id); 33 | } 34 | -------------------------------------------------------------------------------- /declarative-http-client-example/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | logging.level.org.springframework.web=trace -------------------------------------------------------------------------------- /declarative-http-client-example/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | %green(%d{ISO8601}) %highlight(%-5level) [%blue(%t)] %yellow(%C{1}): %msg%n%throwable 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /declarative-http-client-example/src/test/java/com/howtodoinjava/AppTest.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava; 2 | 3 | import org.junit.jupiter.api.Test; 4 | 5 | public class AppTest 6 | { 7 | @Test 8 | public void contextLoads() 9 | { 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /declarative-validation/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | 8 | org.springframework.boot 9 | spring-boot-starter-parent 10 | 3.2.0-M3 11 | 12 | 13 | 14 | com.howtodoinjava.app 15 | declarative-validation 16 | 17 | 18 | 21 19 | 21 20 | UTF-8 21 | 22 | 23 | 24 | 25 | org.projectlombok 26 | lombok 27 | true 28 | 1.18.30 29 | 30 | 31 | org.springframework.boot 32 | spring-boot-starter-web 33 | 34 | 35 | org.springframework.boot 36 | spring-boot-starter-webflux 37 | 38 | 39 | org.springframework.boot 40 | spring-boot-starter-validation 41 | 42 | 43 | org.springframework.boot 44 | spring-boot-starter-test 45 | 46 | 47 | 48 | 49 | 50 | spring-milestone 51 | Spring Milestones 52 | https://repo.spring.io/milestone 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /declarative-validation/src/main/java/com/howtodoinjava/app/Application.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.app; 2 | 3 | import org.springframework.boot.CommandLineRunner; 4 | import org.springframework.boot.SpringApplication; 5 | import org.springframework.boot.autoconfigure.SpringBootApplication; 6 | import org.springframework.context.MessageSource; 7 | 8 | @SpringBootApplication 9 | public class Application implements CommandLineRunner { 10 | 11 | MessageSource messageSource; 12 | 13 | public Application(MessageSource messageSource) { 14 | this.messageSource = messageSource; 15 | } 16 | 17 | public static void main(String[] args) { 18 | SpringApplication.run(Application.class, args); 19 | } 20 | 21 | @Override 22 | public void run(String... args) { 23 | } 24 | } -------------------------------------------------------------------------------- /declarative-validation/src/main/java/com/howtodoinjava/app/exceptions/CustomExceptionHandler.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.app.exceptions; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import org.springframework.http.HttpHeaders; 7 | import org.springframework.http.HttpStatus; 8 | import org.springframework.http.HttpStatusCode; 9 | import org.springframework.http.ResponseEntity; 10 | import org.springframework.validation.ObjectError; 11 | import org.springframework.web.bind.MethodArgumentNotValidException; 12 | import org.springframework.web.bind.annotation.ControllerAdvice; 13 | import org.springframework.web.bind.annotation.ExceptionHandler; 14 | import org.springframework.web.context.request.WebRequest; 15 | import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; 16 | 17 | @ControllerAdvice 18 | public class CustomExceptionHandler extends ResponseEntityExceptionHandler { 19 | 20 | @ExceptionHandler(Exception.class) 21 | public final ResponseEntity handleAllExceptions(Exception ex, WebRequest request) { 22 | List details = new ArrayList<>(); 23 | details.add(ex.getLocalizedMessage()); 24 | ErrorResponse error = new ErrorResponse("Server Error", details); 25 | return new ResponseEntity(error, HttpStatus.INTERNAL_SERVER_ERROR); 26 | } 27 | 28 | @ExceptionHandler(RecordNotFoundException.class) 29 | public final ResponseEntity handleUserNotFoundException(RecordNotFoundException ex, WebRequest request) { 30 | List details = new ArrayList<>(); 31 | details.add(ex.getLocalizedMessage()); 32 | ErrorResponse error = new ErrorResponse("Record Not Found", details); 33 | return new ResponseEntity(error, HttpStatus.NOT_FOUND); 34 | } 35 | 36 | @Override 37 | protected ResponseEntity handleMethodArgumentNotValid(MethodArgumentNotValidException ex, HttpHeaders headers, HttpStatusCode status, WebRequest request) { 38 | List details = new ArrayList<>(); 39 | for (ObjectError error : ex.getBindingResult().getAllErrors()) { 40 | details.add(error.getDefaultMessage()); 41 | } 42 | ErrorResponse error = new ErrorResponse("Validation Failed", details); 43 | return new ResponseEntity(error, HttpStatus.BAD_REQUEST); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /declarative-validation/src/main/java/com/howtodoinjava/app/exceptions/ErrorResponse.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.app.exceptions; 2 | 3 | import lombok.Data; 4 | import lombok.NoArgsConstructor; 5 | 6 | import java.util.List; 7 | 8 | @Data 9 | @NoArgsConstructor 10 | public class ErrorResponse { 11 | 12 | public ErrorResponse(String message, List details) { 13 | super(); 14 | this.message = message; 15 | this.details = details; 16 | } 17 | 18 | //General error message about nature of error 19 | private String message; 20 | 21 | //Specific errors in API request processing 22 | private List details; 23 | } 24 | -------------------------------------------------------------------------------- /declarative-validation/src/main/java/com/howtodoinjava/app/exceptions/RecordNotFoundException.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.app.exceptions; 2 | 3 | import org.springframework.http.HttpStatus; 4 | import org.springframework.web.bind.annotation.ResponseStatus; 5 | 6 | @ResponseStatus(HttpStatus.NOT_FOUND) 7 | public class RecordNotFoundException extends RuntimeException { 8 | public RecordNotFoundException(String exception) { 9 | super(exception); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /declarative-validation/src/main/java/com/howtodoinjava/app/model/Employee.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.app.model; 2 | 3 | import jakarta.validation.constraints.Email; 4 | import jakarta.validation.constraints.NotBlank; 5 | import jakarta.validation.constraints.Pattern; 6 | import jakarta.validation.constraints.Size; 7 | import lombok.AllArgsConstructor; 8 | import lombok.Builder; 9 | import lombok.Data; 10 | import lombok.NoArgsConstructor; 11 | 12 | @Data 13 | @Builder 14 | @NoArgsConstructor 15 | @AllArgsConstructor 16 | public class Employee { 17 | 18 | Long id; 19 | 20 | @NotBlank(message = "First name is required") 21 | @Size(min = 3, max = 20, message = "First name should be between 3 and 20 characters") 22 | String firstName; 23 | 24 | @NotBlank(message = "Last name is required") 25 | @Size(min = 3, max = 20, message = "Last name should be between 3 and 20 characters") 26 | String lastName; 27 | 28 | @NotBlank(message = "Email is required") 29 | @Email(message = "Email is invalid") 30 | String email; 31 | } 32 | -------------------------------------------------------------------------------- /declarative-validation/src/main/resources/messages.properties: -------------------------------------------------------------------------------- 1 | error.field.empty=${property} cannot be empty 2 | error.field.size=${property} must be between {min} and {max} 3 | error.field.invalid.pattern=${property} is an invalid value -------------------------------------------------------------------------------- /declarative-validation/src/main/resources/templates/employee-registration-form.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Employee Registration 7 | 8 | 9 | 10 |

Employee Registration Form

11 | 12 | 13 |
14 | 15 | 16 |
17 |
18 |

19 |
20 |
21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 |
30 | 31 | 32 | 33 | 34 | 35 |
36 | 37 | 38 | 39 | 40 | 41 |
42 | 43 | 44 | 45 | 46 |
47 | 48 | 49 | 50 | 51 |
52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /ehcache-example/README.md: -------------------------------------------------------------------------------- 1 | # Related Tutorials 2 | 3 | - [Spring Boot and Ehcache 3 Example](https://howtodoinjava.com/spring-boot/spring-boot-ehcache-example/) -------------------------------------------------------------------------------- /ehcache-example/pom.xml: -------------------------------------------------------------------------------- 1 | 4 | 4.0.0 5 | 6 | 7 | com.howtodoinjava 8 | Spring-Boot3-Demos 9 | 1.0-SNAPSHOT 10 | 11 | 12 | ehcache-example 13 | jar 14 | ehcache-example 15 | https://howtodoinjava.com 16 | 17 | 18 | UTF-8 19 | 20 | 21 | 22 | 23 | org.springframework.boot 24 | spring-boot-starter-cache 25 | 26 | 27 | org.ehcache 28 | ehcache 29 | jakarta 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /ehcache-example/src/main/java/com/howtodoinjava/App.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava; 2 | 3 | import com.howtodoinjava.model.Employee; 4 | import com.howtodoinjava.service.EmployeeService; 5 | import javax.cache.Cache; 6 | import javax.cache.CacheManager; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.boot.CommandLineRunner; 9 | import org.springframework.boot.SpringApplication; 10 | import org.springframework.boot.autoconfigure.SpringBootApplication; 11 | 12 | @SpringBootApplication 13 | public class App implements CommandLineRunner { 14 | 15 | public static void main(String[] args) { 16 | SpringApplication.run(App.class, args); 17 | } 18 | 19 | @Autowired 20 | private CacheManager cacheManager; 21 | 22 | @Autowired 23 | private EmployeeService employeeService; 24 | 25 | @Override 26 | public void run(String... args) throws Exception { 27 | 28 | //This will hit the database 29 | employeeService.getEmployeeById(1L); 30 | 31 | //This will hit the cache - verify the message in console output 32 | employeeService.getEmployeeById(1L); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /ehcache-example/src/main/java/com/howtodoinjava/caching/CacheConfig.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.caching; 2 | 3 | import org.springframework.cache.annotation.EnableCaching; 4 | import org.springframework.context.annotation.Configuration; 5 | 6 | @Configuration 7 | @EnableCaching 8 | public class CacheConfig { 9 | 10 | } 11 | -------------------------------------------------------------------------------- /ehcache-example/src/main/java/com/howtodoinjava/caching/CustomCacheEventLogger.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.caching; 2 | 3 | import org.ehcache.event.CacheEvent; 4 | import org.ehcache.event.CacheEventListener; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | import org.springframework.stereotype.Component; 8 | 9 | @Component 10 | public class CustomCacheEventLogger implements CacheEventListener { 11 | 12 | private static final Logger LOG = LoggerFactory.getLogger(CustomCacheEventLogger.class); 13 | 14 | @Override 15 | public void onEvent(CacheEvent cacheEvent) { 16 | LOG.info("Cache event = {}, Key = {}, Old value = {}, New value = {}", cacheEvent.getType(), 17 | cacheEvent.getKey(), cacheEvent.getOldValue(), cacheEvent.getNewValue()); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /ehcache-example/src/main/java/com/howtodoinjava/model/Employee.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.model; 2 | 3 | import java.io.Serializable; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | @Data 9 | @AllArgsConstructor 10 | @NoArgsConstructor 11 | public class Employee implements Serializable { 12 | 13 | private Long id; 14 | private String firstName; 15 | private String lastName; 16 | } 17 | -------------------------------------------------------------------------------- /ehcache-example/src/main/java/com/howtodoinjava/service/EmployeeService.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.service; 2 | 3 | import com.howtodoinjava.model.Employee; 4 | import java.util.HashMap; 5 | import java.util.Map; 6 | import lombok.extern.java.Log; 7 | import org.springframework.cache.annotation.Cacheable; 8 | import org.springframework.stereotype.Service; 9 | 10 | @Service 11 | @Log 12 | public class EmployeeService 13 | { 14 | static Map db = new HashMap<>(); 15 | 16 | static { 17 | db.put(1L, new Employee(1L, "Alex", "Gussin")); 18 | db.put(2L, new Employee(2L, "Brian", "Schultz")); 19 | } 20 | 21 | @Cacheable(cacheNames="employeeCache", key="#id") 22 | public Employee getEmployeeById(Long id) { 23 | log.info("Getting employee from DB"); 24 | return db.get(id); 25 | } 26 | } -------------------------------------------------------------------------------- /ehcache-example/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.cache.jcache.config=classpath:ehcache.xml 2 | logging.level.org.springframework.cache=TRACE -------------------------------------------------------------------------------- /ehcache-example/src/main/resources/ehcache.xml: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | java.lang.Long 12 | com.howtodoinjava.model.Employee 13 | 14 | 10000 15 | 16 | 17 | 18 | com.howtodoinjava.caching.CustomCacheEventLogger 19 | ASYNCHRONOUS 20 | UNORDERED 21 | CREATED 22 | UPDATED 23 | EXPIRED 24 | REMOVED 25 | EVICTED 26 | 27 | 28 | 29 | 2000 30 | 100 31 | 32 | 33 | -------------------------------------------------------------------------------- /ehcache-example/src/test/java/com/howtodoinjava/AppTest.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava; 2 | 3 | public class AppTest { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /ehcache-example/target/classes/application.properties: -------------------------------------------------------------------------------- 1 | spring.cache.jcache.config=classpath:ehcache.xml 2 | logging.level.org.springframework.cache=TRACE -------------------------------------------------------------------------------- /ehcache-example/target/classes/ehcache.xml: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | java.lang.Long 12 | com.howtodoinjava.model.Employee 13 | 14 | 10000 15 | 16 | 17 | 18 | com.howtodoinjava.caching.CustomCacheEventLogger 19 | ASYNCHRONOUS 20 | UNORDERED 21 | CREATED 22 | UPDATED 23 | EXPIRED 24 | REMOVED 25 | EVICTED 26 | 27 | 28 | 29 | 2000 30 | 100 31 | 32 | 33 | -------------------------------------------------------------------------------- /inventory-management-app/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | version: '3.7' 2 | services: 3 | mysql_db_container: 4 | image: mysql:latest 5 | command: --default-authentication-plugin=mysql_native_password 6 | environment: 7 | MYSQL_ROOT_PASSWORD: rootpassword 8 | ports: 9 | - "3306:3306" 10 | volumes: 11 | - mysql_db_data_container:/var/lib/mysql 12 | adminer_container: 13 | image: adminer:latest 14 | environment: 15 | ADMINER_DEFAULT_SERVER: mysql_db_container 16 | ports: 17 | - "8080:8080" 18 | 19 | volumes: 20 | mysql_db_data_container: -------------------------------------------------------------------------------- /inventory-management-app/inventory-mgmt-service/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | !**/src/main/**/build/ 30 | !**/src/test/**/build/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | /.mvn/ 35 | -------------------------------------------------------------------------------- /inventory-management-app/inventory-mgmt-service/src/main/java/com/howtodoinjava/app/InventoryMgmtServiceApplication.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.app; 2 | 3 | import com.howtodoinjava.app.dao.ItemRepository; 4 | import com.howtodoinjava.app.dao.entity.Item; 5 | import com.howtodoinjava.app.dao.entity.ItemCategory; 6 | import com.howtodoinjava.app.dao.entity.ItemDetail; 7 | import com.howtodoinjava.app.dao.entity.Seller; 8 | import java.util.Iterator; 9 | import lombok.extern.slf4j.Slf4j; 10 | import org.springframework.beans.factory.annotation.Autowired; 11 | import org.springframework.boot.CommandLineRunner; 12 | import org.springframework.boot.SpringApplication; 13 | import org.springframework.boot.autoconfigure.SpringBootApplication; 14 | 15 | @SpringBootApplication 16 | @Slf4j 17 | public class InventoryMgmtServiceApplication implements CommandLineRunner { 18 | 19 | @Autowired 20 | private ItemRepository itemRepository; 21 | 22 | public static void main(String[] args) { 23 | SpringApplication.run(InventoryMgmtServiceApplication.class, args); 24 | } 25 | 26 | @Override 27 | public void run(String... args) throws Exception { 28 | 29 | Iterator iterator = itemRepository.findAll().iterator(); 30 | //If there is already some test data, leave it. 31 | if(!iterator.hasNext()) { 32 | Seller seller = new Seller(null, "Book Publishing Co.", true); 33 | ItemDetail itemDetail = new ItemDetail(null, seller, ItemCategory.BOOKS); 34 | Item item = new Item(null, "Harry Potter", "Fiction and Magic for Kids", 100, itemDetail, true); 35 | 36 | itemRepository.save(item); 37 | } 38 | 39 | Item item = itemRepository.findById(1L).get(); 40 | log.info("Item read :: " + item); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /inventory-management-app/inventory-mgmt-service/src/main/java/com/howtodoinjava/app/config/DataSourceConfig.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.app.config; 2 | 3 | import javax.sql.DataSource; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.context.annotation.Configuration; 7 | import org.springframework.core.env.Environment; 8 | import org.springframework.jdbc.datasource.DriverManagerDataSource; 9 | 10 | @Configuration 11 | public class DataSourceConfig { 12 | 13 | @Autowired 14 | private Environment env; 15 | 16 | /*@Bean 17 | public DataSource dataSource() { 18 | DriverManagerDataSource dataSource = new DriverManagerDataSource(); 19 | dataSource.setDriverClassName(env.getProperty("app.datasource.driverClassName")); 20 | dataSource.setUrl(env.getProperty("app.datasource.url")); 21 | dataSource.setUsername(env.getProperty("app.datasource.username")); 22 | dataSource.setPassword(env.getProperty("app.datasource.password")); 23 | return dataSource; 24 | }*/ 25 | } 26 | -------------------------------------------------------------------------------- /inventory-management-app/inventory-mgmt-service/src/main/java/com/howtodoinjava/app/dao/ItemRepository.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.app.dao; 2 | 3 | import com.howtodoinjava.app.dao.entity.Item; 4 | import java.util.List; 5 | import org.springframework.data.domain.Pageable; 6 | import org.springframework.data.repository.CrudRepository; 7 | import org.springframework.stereotype.Repository; 8 | 9 | @Repository 10 | public interface ItemRepository extends CrudRepository { 11 | 12 | List findByNameContaining(String searchTerm, Pageable pageable); 13 | } 14 | -------------------------------------------------------------------------------- /inventory-management-app/inventory-mgmt-service/src/main/java/com/howtodoinjava/app/dao/entity/Item.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.app.dao.entity; 2 | 3 | import jakarta.persistence.CascadeType; 4 | import jakarta.persistence.Column; 5 | import jakarta.persistence.Entity; 6 | import jakarta.persistence.GeneratedValue; 7 | import jakarta.persistence.GenerationType; 8 | import jakarta.persistence.Id; 9 | import jakarta.persistence.JoinColumn; 10 | import jakarta.persistence.OneToOne; 11 | import jakarta.persistence.Table; 12 | import lombok.AllArgsConstructor; 13 | import lombok.Data; 14 | import lombok.NoArgsConstructor; 15 | 16 | @Data 17 | @NoArgsConstructor 18 | @AllArgsConstructor 19 | @Entity 20 | @Table(name = "TBL_ITEM") 21 | public class Item { 22 | 23 | @Id 24 | @GeneratedValue(strategy = GenerationType.AUTO) 25 | @Column(name = "id", nullable = false) 26 | private Long id; 27 | 28 | @Column(name = "name", nullable = false) 29 | private String name; 30 | 31 | @Column(name = "description", nullable = false) 32 | private String description; 33 | 34 | @Column(name = "quantity", nullable = false) 35 | private int quantity; 36 | 37 | @OneToOne(cascade = {CascadeType.MERGE, CascadeType.PERSIST}) 38 | @JoinColumn(name = "item_detail_id") 39 | private ItemDetail itemDetail; 40 | 41 | @Column(name = "active", nullable = false) 42 | private boolean active; 43 | } 44 | -------------------------------------------------------------------------------- /inventory-management-app/inventory-mgmt-service/src/main/java/com/howtodoinjava/app/dao/entity/ItemCategory.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.app.dao.entity; 2 | 3 | public enum ItemCategory { 4 | 5 | FASHION(1), FOOD(2), ELECTRONICS(3), MOBILE(4), BOOKS(5); 6 | 7 | int id; 8 | 9 | ItemCategory(int id) { 10 | this.id = id; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /inventory-management-app/inventory-mgmt-service/src/main/java/com/howtodoinjava/app/dao/entity/ItemDetail.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.app.dao.entity; 2 | 3 | import jakarta.persistence.CascadeType; 4 | import jakarta.persistence.Column; 5 | import jakarta.persistence.Entity; 6 | import jakarta.persistence.GeneratedValue; 7 | import jakarta.persistence.GenerationType; 8 | import jakarta.persistence.Id; 9 | import jakarta.persistence.JoinColumn; 10 | import jakarta.persistence.OneToOne; 11 | import jakarta.persistence.Table; 12 | import lombok.AllArgsConstructor; 13 | import lombok.Data; 14 | import lombok.NoArgsConstructor; 15 | 16 | @Data 17 | @NoArgsConstructor 18 | @AllArgsConstructor 19 | @Entity 20 | @Table(name = "TBL_ITEM_DTL") 21 | public class ItemDetail { 22 | 23 | @Id 24 | @GeneratedValue(strategy = GenerationType.AUTO) 25 | @Column(name = "id", nullable = false) 26 | private Long id; 27 | 28 | @OneToOne(cascade = {CascadeType.MERGE, CascadeType.PERSIST}) 29 | @JoinColumn(name = "seller_id") 30 | private Seller seller; 31 | 32 | @Column(name = "category", nullable = false) 33 | ItemCategory category; 34 | } 35 | -------------------------------------------------------------------------------- /inventory-management-app/inventory-mgmt-service/src/main/java/com/howtodoinjava/app/dao/entity/Seller.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.app.dao.entity; 2 | 3 | import jakarta.persistence.Column; 4 | import jakarta.persistence.Entity; 5 | import jakarta.persistence.GeneratedValue; 6 | import jakarta.persistence.GenerationType; 7 | import jakarta.persistence.Id; 8 | import jakarta.persistence.Table; 9 | import lombok.AllArgsConstructor; 10 | import lombok.Data; 11 | import lombok.NoArgsConstructor; 12 | 13 | @Data 14 | @NoArgsConstructor 15 | @AllArgsConstructor 16 | @Entity 17 | @Table(name = "TBL_SELLER") 18 | public class Seller { 19 | @Id 20 | @GeneratedValue(strategy = GenerationType.AUTO) 21 | @Column(name = "id", nullable = false) 22 | private Long id; 23 | 24 | @Column(name = "name", nullable = false) 25 | private String name; 26 | 27 | @Column(name = "active", nullable = false) 28 | private boolean active; 29 | } 30 | -------------------------------------------------------------------------------- /inventory-management-app/inventory-mgmt-service/src/main/java/com/howtodoinjava/app/utils/TestDataSetup.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.app.utils; 2 | 3 | import com.howtodoinjava.app.dao.ItemRepository; 4 | import com.howtodoinjava.app.dao.entity.Item; 5 | import com.howtodoinjava.app.dao.entity.ItemCategory; 6 | import com.howtodoinjava.app.dao.entity.ItemDetail; 7 | import com.howtodoinjava.app.dao.entity.Seller; 8 | import java.util.Iterator; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.boot.CommandLineRunner; 11 | import org.springframework.context.annotation.Profile; 12 | import org.springframework.stereotype.Component; 13 | 14 | @Profile("!test") 15 | @Component 16 | public class TestDataSetup implements CommandLineRunner { 17 | 18 | @Autowired 19 | private ItemRepository itemRepository; 20 | 21 | @Override 22 | public void run(String... args) throws Exception { 23 | 24 | Iterator iterator = itemRepository.findAll().iterator(); 25 | //If there is already some test data, leave setup. 26 | if(iterator.hasNext()) { 27 | return; 28 | } 29 | 30 | Seller seller = new Seller(null, "Book Publishing Co.", true); 31 | ItemDetail itemDetail = new ItemDetail(null, seller, ItemCategory.BOOKS); 32 | Item item = new Item(null, "Harry Potter", "Fiction and Magic for Kids", 100, itemDetail, true); 33 | 34 | itemRepository.save(item); 35 | 36 | seller = new Seller(null, "Old Publishing Co.", true); 37 | itemDetail = new ItemDetail(null, seller, ItemCategory.BOOKS); 38 | item = new Item(null, "Wednesday", "Fiction and Magic for Kids", 100, itemDetail, true); 39 | 40 | itemRepository.save(item); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /inventory-management-app/inventory-mgmt-service/src/main/java/com/howtodoinjava/app/web/ItemController.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.app.web; 2 | 3 | import com.howtodoinjava.app.dao.ItemRepository; 4 | import com.howtodoinjava.app.dao.entity.Item; 5 | import java.util.List; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.data.domain.PageRequest; 8 | import org.springframework.data.domain.Pageable; 9 | import org.springframework.data.domain.Sort; 10 | import org.springframework.web.bind.annotation.GetMapping; 11 | import org.springframework.web.bind.annotation.RequestMapping; 12 | import org.springframework.web.bind.annotation.RequestParam; 13 | import org.springframework.web.bind.annotation.RestController; 14 | 15 | @RestController 16 | @RequestMapping("/items") 17 | public class ItemController { 18 | 19 | @Autowired 20 | private ItemRepository itemRepository; 21 | 22 | @GetMapping 23 | public List getAll( 24 | @RequestParam(required = false, defaultValue = "0") int page, 25 | @RequestParam(required = false, defaultValue = "10") int size, 26 | @RequestParam(required = false, defaultValue = "id") String sortBy, 27 | @RequestParam(required = false, defaultValue = "asc") String order, 28 | @RequestParam(required = false) String searchTerm){ 29 | 30 | Pageable pageable = PageRequest.of(page, size, Sort.by(Sort.Direction.fromString(order), sortBy)); 31 | return itemRepository.findByNameContaining(searchTerm, pageable); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /inventory-management-app/inventory-mgmt-service/src/main/resources/application-dev.properties: -------------------------------------------------------------------------------- 1 | #app.datasource.url=jdbc:mysql://${DB_HOST:localhost}:${DB_PORT:3306}/inventory 2 | #app.datasource.username=${DB_USER:root} 3 | #app.datasource.password=${DB_PASSWORD:rootpassword} 4 | #app.datasource.driverClassName=com.mysql.cj.jdbc.Driver 5 | 6 | spring.datasource.url=jdbc:mysql://${DB_HOST:localhost}:${DB_PORT:3306}/inventory 7 | spring.datasource.username=${DB_USER:root} 8 | spring.datasource.password=${DB_PASSWORD:rootpassword} 9 | spring.datasource.driverClassName=com.mysql.cj.jdbc.Driver 10 | 11 | spring.jpa.show-sql=true 12 | spring.jpa.format-sql=true 13 | spring.jpa.hibernate.ddl-auto=update 14 | spring.jpa.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect 15 | spring.jpa.hibernate.naming_strategy=org.hibernate.cfg.ImprovedNamingStrategy 16 | 17 | logging.level.org.springframework=DEBUG 18 | logging.level.com.howtodoinjava=DEBUG -------------------------------------------------------------------------------- /inventory-management-app/inventory-mgmt-service/src/main/resources/application-prod.properties: -------------------------------------------------------------------------------- 1 | #app.datasource.url=jdbc:mysql://${DB_HOST:localhost}:${DB_PORT:3306}/inventory 2 | #app.datasource.username=${DB_USER:root} 3 | #app.datasource.password=${DB_PASSWORD:rootpassword} 4 | #app.datasource.driverClassName=com.mysql.cj.jdbc.Driver 5 | 6 | spring.datasource.url=jdbc:mysql://${DB_HOST:localhost}:${DB_PORT:3306}/inventory 7 | spring.datasource.username=${DB_USER:root} 8 | spring.datasource.password=${DB_PASSWORD:rootpassword} 9 | spring.datasource.driverClassName=com.mysql.cj.jdbc.Driver 10 | 11 | spring.jpa.show-sql=true 12 | spring.jpa.format-sql=true 13 | spring.jpa.hibernate.ddl-auto=update 14 | spring.jpa.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect 15 | spring.jpa.hibernate.naming_strategy=org.hibernate.cfg.ImprovedNamingStrategy 16 | 17 | logging.level.org.springframework=INFO 18 | logging.level.com.howtodoinjava=INFO -------------------------------------------------------------------------------- /inventory-management-app/inventory-mgmt-service/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.profiles.active=dev 2 | server.port=8081 3 | -------------------------------------------------------------------------------- /inventory-management-app/inventory-mgmt-service/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | %d{yyyy-MM-dd_HH:mm:ss.SSS} %-5level %logger{36} - %msg%n 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /inventory-management-app/inventory-mgmt-service/src/test/java/com/howtodoinjava/app/dao/ItemRepositoryTests.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.app.dao; 2 | 3 | import com.howtodoinjava.app.dao.entity.Item; 4 | import com.howtodoinjava.app.dao.entity.ItemCategory; 5 | import com.howtodoinjava.app.dao.entity.ItemDetail; 6 | import com.howtodoinjava.app.dao.entity.Seller; 7 | import java.util.List; 8 | import org.junit.jupiter.api.Assertions; 9 | import org.junit.jupiter.api.Test; 10 | import org.springframework.beans.factory.annotation.Autowired; 11 | import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; 12 | import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; 13 | import org.springframework.data.domain.PageRequest; 14 | import org.springframework.data.domain.Pageable; 15 | import org.springframework.data.domain.Sort; 16 | import org.springframework.test.context.ActiveProfiles; 17 | 18 | @DataJpaTest 19 | @AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) 20 | @ActiveProfiles("test") 21 | public class ItemRepositoryTests { 22 | 23 | @Autowired 24 | private ItemRepository itemRepository; 25 | 26 | @Test 27 | public void testGetAll(){ 28 | Seller seller = new Seller(null, "Book Publishing Co.", true); 29 | ItemDetail itemDetail = new ItemDetail(null, seller, ItemCategory.BOOKS); 30 | Item item = new Item(null, "Jungle Book", "Fiction and Magic for Kids", 100, itemDetail, true); 31 | 32 | itemRepository.save(item); 33 | 34 | long itemId = item.getId(); 35 | 36 | Pageable pageable = PageRequest.of(0, 10, Sort.by(Sort.Direction.fromString("asc"), "id")); 37 | List itemList = itemRepository.findByNameContaining("Jungle Book", pageable); 38 | 39 | Assertions.assertEquals(1, itemList.size()); 40 | 41 | itemList = itemRepository.findByNameContaining("JungleBook", pageable); 42 | 43 | Assertions.assertEquals(0, itemList.size()); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /inventory-management-app/inventory-mgmt-service/src/test/java/com/howtodoinjava/app/web/ItemControllerTests.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.app.web; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; 5 | 6 | @WebMvcTest 7 | public class ItemControllerTests { 8 | 9 | 10 | 11 | } 12 | -------------------------------------------------------------------------------- /inventory-management-app/inventory-mgmt-service/src/test/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.datasource.url=jdbc:h2:mem:inventory;DB_CLOSE_DELAY=-1 2 | spring.datasource.username=sa 3 | spring.datasource.password=sa 4 | spring.datasource.driverClassName=org.h2.Driver 5 | 6 | spring.jpa.show-sql=true 7 | spring.jpa.format-sql=true 8 | spring.jpa.hibernate.ddl-auto=update 9 | spring.jpa.hibernate.dialect=org.hibernate.dialect.H2Dialect 10 | spring.jpa.hibernate.naming_strategy=org.hibernate.cfg.ImprovedNamingStrategy 11 | 12 | logging.level.org.springframework=DEBUG 13 | logging.level.com.howtodoinjava=DEBUG 14 | -------------------------------------------------------------------------------- /inventory-management-app/inventory-mgmt-ui/.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | indent_style = space 6 | indent_size = 2 7 | insert_final_newline = true 8 | trim_trailing_whitespace = true 9 | 10 | [*.ts] 11 | quote_type = single 12 | 13 | [*.md] 14 | max_line_length = off 15 | trim_trailing_whitespace = false 16 | -------------------------------------------------------------------------------- /inventory-management-app/inventory-mgmt-ui/.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # Compiled output 4 | /dist 5 | /tmp 6 | /out-tsc 7 | /bazel-out 8 | 9 | # Node 10 | /node_modules 11 | npm-debug.log 12 | yarn-error.log 13 | 14 | # IDEs and editors 15 | .idea/ 16 | .project 17 | .classpath 18 | .c9/ 19 | *.launch 20 | .settings/ 21 | *.sublime-workspace 22 | 23 | # Visual Studio Code 24 | .vscode/* 25 | !.vscode/settings.json 26 | !.vscode/tasks.json 27 | !.vscode/launch.json 28 | !.vscode/extensions.json 29 | .history/* 30 | 31 | # Miscellaneous 32 | /.angular/cache 33 | .sass-cache/ 34 | /connect.lock 35 | /coverage 36 | /libpeerconnection.log 37 | testem.log 38 | /typings 39 | 40 | # System files 41 | .DS_Store 42 | Thumbs.db 43 | -------------------------------------------------------------------------------- /inventory-management-app/inventory-mgmt-ui/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": ["angular.ng-template"] 3 | } 4 | -------------------------------------------------------------------------------- /inventory-management-app/inventory-mgmt-ui/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "name": "ng serve", 6 | "type": "pwa-chrome", 7 | "request": "launch", 8 | "preLaunchTask": "npm: start", 9 | "url": "http://localhost:4200/" 10 | }, 11 | { 12 | "name": "ng test", 13 | "type": "chrome", 14 | "request": "launch", 15 | "preLaunchTask": "npm: test", 16 | "url": "http://localhost:9876/debug.html" 17 | } 18 | ] 19 | } 20 | -------------------------------------------------------------------------------- /inventory-management-app/inventory-mgmt-ui/.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.0", 3 | "tasks": [ 4 | { 5 | "type": "npm", 6 | "script": "start", 7 | "isBackground": true, 8 | "problemMatcher": { 9 | "owner": "typescript", 10 | "pattern": "$tsc", 11 | "background": { 12 | "activeOnStart": true, 13 | "beginsPattern": { 14 | "regexp": "(.*?)" 15 | }, 16 | "endsPattern": { 17 | "regexp": "bundle generation complete" 18 | } 19 | } 20 | } 21 | }, 22 | { 23 | "type": "npm", 24 | "script": "test", 25 | "isBackground": true, 26 | "problemMatcher": { 27 | "owner": "typescript", 28 | "pattern": "$tsc", 29 | "background": { 30 | "activeOnStart": true, 31 | "beginsPattern": { 32 | "regexp": "(.*?)" 33 | }, 34 | "endsPattern": { 35 | "regexp": "bundle generation complete" 36 | } 37 | } 38 | } 39 | } 40 | ] 41 | } 42 | -------------------------------------------------------------------------------- /inventory-management-app/inventory-mgmt-ui/README.md: -------------------------------------------------------------------------------- 1 | # InventoryMgmtUi 2 | 3 | This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 15.1.3. 4 | 5 | ## Development server 6 | 7 | Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The application will automatically reload if you change any of the source files. 8 | 9 | ## Code scaffolding 10 | 11 | Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`. 12 | 13 | ## Build 14 | 15 | Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. 16 | 17 | ## Running unit tests 18 | 19 | Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io). 20 | 21 | ## Running end-to-end tests 22 | 23 | Run `ng e2e` to execute the end-to-end tests via a platform of your choice. To use this command, you need to first add a package that implements end-to-end testing capabilities. 24 | 25 | ## Further help 26 | 27 | To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI Overview and Command Reference](https://angular.io/cli) page. 28 | -------------------------------------------------------------------------------- /inventory-management-app/inventory-mgmt-ui/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "inventory-mgmt-ui", 3 | "version": "0.0.0", 4 | "scripts": { 5 | "ng": "ng", 6 | "start": "ng serve", 7 | "build": "ng build", 8 | "watch": "ng build --watch --configuration development", 9 | "test": "ng test" 10 | }, 11 | "private": true, 12 | "dependencies": { 13 | "@angular/animations": "^15.1.0", 14 | "@angular/cdk": "^15.1.2", 15 | "@angular/common": "^15.1.0", 16 | "@angular/compiler": "^15.1.0", 17 | "@angular/core": "^15.1.0", 18 | "@angular/forms": "^15.1.0", 19 | "@angular/material": "^15.1.2", 20 | "@angular/platform-browser": "^15.1.0", 21 | "@angular/platform-browser-dynamic": "^15.1.0", 22 | "@angular/router": "^15.1.0", 23 | "rxjs": "~7.8.0", 24 | "tslib": "^2.3.0", 25 | "zone.js": "~0.12.0" 26 | }, 27 | "devDependencies": { 28 | "@angular-devkit/build-angular": "^15.1.3", 29 | "@angular/cli": "~15.1.3", 30 | "@angular/compiler-cli": "^15.1.0", 31 | "@types/jasmine": "~4.3.0", 32 | "jasmine-core": "~4.5.0", 33 | "karma": "~6.4.0", 34 | "karma-chrome-launcher": "~3.1.0", 35 | "karma-coverage": "~2.2.0", 36 | "karma-jasmine": "~5.1.0", 37 | "karma-jasmine-html-reporter": "~2.0.0", 38 | "typescript": "~4.9.4" 39 | } 40 | } -------------------------------------------------------------------------------- /inventory-management-app/inventory-mgmt-ui/src/app/app-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { RouterModule, Routes } from '@angular/router'; 3 | 4 | const routes: Routes = []; 5 | 6 | @NgModule({ 7 | imports: [RouterModule.forRoot(routes)], 8 | exports: [RouterModule] 9 | }) 10 | export class AppRoutingModule { } 11 | -------------------------------------------------------------------------------- /inventory-management-app/inventory-mgmt-ui/src/app/app.component.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lokeshgupta1981/Spring-Boot3-Demos/6974e42d87a604213d2cdb2c0b2a1e26418e172c/inventory-management-app/inventory-mgmt-ui/src/app/app.component.css -------------------------------------------------------------------------------- /inventory-management-app/inventory-mgmt-ui/src/app/app.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed } from '@angular/core/testing'; 2 | import { RouterTestingModule } from '@angular/router/testing'; 3 | import { AppComponent } from './app.component'; 4 | 5 | describe('AppComponent', () => { 6 | beforeEach(async () => { 7 | await TestBed.configureTestingModule({ 8 | imports: [ 9 | RouterTestingModule 10 | ], 11 | declarations: [ 12 | AppComponent 13 | ], 14 | }).compileComponents(); 15 | }); 16 | 17 | it('should create the app', () => { 18 | const fixture = TestBed.createComponent(AppComponent); 19 | const app = fixture.componentInstance; 20 | expect(app).toBeTruthy(); 21 | }); 22 | 23 | it(`should have as title 'inventory-mgmt-ui'`, () => { 24 | const fixture = TestBed.createComponent(AppComponent); 25 | const app = fixture.componentInstance; 26 | expect(app.title).toEqual('inventory-mgmt-ui'); 27 | }); 28 | 29 | it('should render title', () => { 30 | const fixture = TestBed.createComponent(AppComponent); 31 | fixture.detectChanges(); 32 | const compiled = fixture.nativeElement as HTMLElement; 33 | expect(compiled.querySelector('.content span')?.textContent).toContain('inventory-mgmt-ui app is running!'); 34 | }); 35 | }); 36 | -------------------------------------------------------------------------------- /inventory-management-app/inventory-mgmt-ui/src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-root', 5 | templateUrl: './app.component.html', 6 | styleUrls: ['./app.component.css'] 7 | }) 8 | export class AppComponent { 9 | title = 'inventory-mgmt-ui'; 10 | } 11 | -------------------------------------------------------------------------------- /inventory-management-app/inventory-mgmt-ui/src/app/app.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { BrowserModule } from '@angular/platform-browser'; 3 | 4 | import { AppRoutingModule } from './app-routing.module'; 5 | import { AppComponent } from './app.component'; 6 | import { NoopAnimationsModule } from '@angular/platform-browser/animations'; 7 | 8 | @NgModule({ 9 | declarations: [ 10 | AppComponent 11 | ], 12 | imports: [ 13 | BrowserModule, 14 | AppRoutingModule, 15 | NoopAnimationsModule 16 | ], 17 | providers: [], 18 | bootstrap: [AppComponent] 19 | }) 20 | export class AppModule { } 21 | -------------------------------------------------------------------------------- /inventory-management-app/inventory-mgmt-ui/src/assets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lokeshgupta1981/Spring-Boot3-Demos/6974e42d87a604213d2cdb2c0b2a1e26418e172c/inventory-management-app/inventory-mgmt-ui/src/assets/.gitkeep -------------------------------------------------------------------------------- /inventory-management-app/inventory-mgmt-ui/src/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lokeshgupta1981/Spring-Boot3-Demos/6974e42d87a604213d2cdb2c0b2a1e26418e172c/inventory-management-app/inventory-mgmt-ui/src/favicon.ico -------------------------------------------------------------------------------- /inventory-management-app/inventory-mgmt-ui/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | InventoryMgmtUi 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /inventory-management-app/inventory-mgmt-ui/src/main.ts: -------------------------------------------------------------------------------- 1 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 2 | 3 | import { AppModule } from './app/app.module'; 4 | 5 | 6 | platformBrowserDynamic().bootstrapModule(AppModule) 7 | .catch(err => console.error(err)); 8 | -------------------------------------------------------------------------------- /inventory-management-app/inventory-mgmt-ui/src/styles.css: -------------------------------------------------------------------------------- 1 | /* You can add global styles to this file, and also import other style files */ 2 | 3 | html, body { height: 100%; } 4 | body { margin: 0; font-family: Roboto, "Helvetica Neue", sans-serif; } 5 | -------------------------------------------------------------------------------- /inventory-management-app/inventory-mgmt-ui/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "./out-tsc/app", 5 | "types": [] 6 | }, 7 | "files": [ 8 | "src/main.ts" 9 | ], 10 | "include": [ 11 | "src/**/*.d.ts" 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /inventory-management-app/inventory-mgmt-ui/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compileOnSave": false, 3 | "compilerOptions": { 4 | "baseUrl": "./", 5 | "outDir": "./dist/out-tsc", 6 | "forceConsistentCasingInFileNames": true, 7 | "strict": true, 8 | "noImplicitOverride": true, 9 | "noPropertyAccessFromIndexSignature": true, 10 | "noImplicitReturns": true, 11 | "noFallthroughCasesInSwitch": true, 12 | "sourceMap": true, 13 | "declaration": false, 14 | "downlevelIteration": true, 15 | "experimentalDecorators": true, 16 | "moduleResolution": "node", 17 | "importHelpers": true, 18 | "target": "ES2022", 19 | "module": "ES2022", 20 | "useDefineForClassFields": false, 21 | "lib": [ 22 | "ES2022", 23 | "dom" 24 | ] 25 | }, 26 | "angularCompilerOptions": { 27 | "enableI18nLegacyMessageIdFormat": false, 28 | "strictInjectionParameters": true, 29 | "strictInputAccessModifiers": true, 30 | "strictTemplates": true 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /inventory-management-app/inventory-mgmt-ui/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "./out-tsc/spec", 5 | "types": [ 6 | "jasmine" 7 | ] 8 | }, 9 | "include": [ 10 | "src/**/*.spec.ts", 11 | "src/**/*.d.ts" 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /item-report.jasper: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lokeshgupta1981/Spring-Boot3-Demos/6974e42d87a604213d2cdb2c0b2a1e26418e172c/item-report.jasper -------------------------------------------------------------------------------- /jasper-reports-example/README.md: -------------------------------------------------------------------------------- 1 | # Related Tutorials 2 | 3 | * [Jasper Reports with Spring Boot 3](https://howtodoinjava.com/spring-boot/spring-boot-jasper-report/) -------------------------------------------------------------------------------- /jasper-reports-example/pom.xml: -------------------------------------------------------------------------------- 1 | 4 | 4.0.0 5 | 6 | 7 | com.howtodoinjava 8 | Spring-Boot3-Demos 9 | 1.0-SNAPSHOT 10 | 11 | 12 | jasper-reports-example 13 | jar 14 | jasper-reports-example 15 | https://howtodoinjava.com 16 | 17 | 18 | UTF-8 19 | 20 | 21 | 22 | 23 | org.springframework.boot 24 | spring-boot-starter-web 25 | 26 | 27 | org.springframework.boot 28 | spring-boot-starter-data-jpa 29 | 30 | 31 | com.h2database 32 | h2 33 | 34 | 35 | net.sf.jasperreports 36 | jasperreports 37 | 6.20.5 38 | 39 | 40 | commons-logging 41 | commons-logging 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /jasper-reports-example/src/main/java/com/howtodoinjava/app/App.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.app; 2 | 3 | import com.howtodoinjava.app.dao.ItemRepository; 4 | import com.howtodoinjava.app.model.Item; 5 | import org.springframework.beans.factory.annotation.Autowired; 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 App implements CommandLineRunner { 12 | 13 | @Autowired 14 | ItemRepository itemRepository; 15 | 16 | public static void main(String[] args) { 17 | SpringApplication.run(App.class, args); 18 | } 19 | 20 | @Override 21 | public void run(String... args) throws Exception { 22 | itemRepository.save(new Item("Item 1")); 23 | itemRepository.save(new Item("Item 2")); 24 | itemRepository.save(new Item("Item 3")); 25 | itemRepository.save(new Item("Item 4")); 26 | itemRepository.save(new Item("Item 5")); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /jasper-reports-example/src/main/java/com/howtodoinjava/app/dao/ItemRepository.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.app.dao; 2 | 3 | import com.howtodoinjava.app.model.Item; 4 | import org.springframework.data.repository.ListCrudRepository; 5 | import org.springframework.stereotype.Repository; 6 | 7 | @Repository 8 | public interface ItemRepository extends ListCrudRepository { 9 | 10 | } 11 | -------------------------------------------------------------------------------- /jasper-reports-example/src/main/java/com/howtodoinjava/app/model/Item.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.app.model; 2 | 3 | import jakarta.persistence.Entity; 4 | import jakarta.persistence.GeneratedValue; 5 | import jakarta.persistence.GenerationType; 6 | import jakarta.persistence.Id; 7 | import lombok.AllArgsConstructor; 8 | import lombok.Data; 9 | import lombok.NoArgsConstructor; 10 | 11 | @Entity 12 | @Data 13 | @AllArgsConstructor 14 | @NoArgsConstructor 15 | public class Item { 16 | 17 | @Id 18 | @GeneratedValue(strategy = GenerationType.IDENTITY) 19 | private Long id; 20 | private String name; 21 | 22 | public Item(String name) { 23 | this.name = name; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /jasper-reports-example/src/main/java/com/howtodoinjava/app/web/ReportController.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.app.web; 2 | 3 | import com.howtodoinjava.app.dao.ItemRepository; 4 | import com.howtodoinjava.app.jasper.JasperReportService; 5 | import java.io.IOException; 6 | import net.sf.jasperreports.engine.JRException; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.core.io.ByteArrayResource; 9 | import org.springframework.core.io.Resource; 10 | import org.springframework.http.ContentDisposition; 11 | import org.springframework.http.HttpHeaders; 12 | import org.springframework.http.MediaType; 13 | import org.springframework.http.ResponseEntity; 14 | import org.springframework.stereotype.Controller; 15 | import org.springframework.web.bind.annotation.GetMapping; 16 | import org.springframework.web.bind.annotation.PathVariable; 17 | 18 | @Controller 19 | public class ReportController { 20 | 21 | @Autowired 22 | ItemRepository itemRepository; 23 | 24 | @Autowired 25 | JasperReportService jasperReportService; 26 | 27 | @GetMapping("item-report/{format}") 28 | public ResponseEntity getItemReport(@PathVariable String format) 29 | throws JRException, IOException { 30 | 31 | byte[] reportContent = jasperReportService.getItemReport(itemRepository.findAll(), format); 32 | 33 | ByteArrayResource resource = new ByteArrayResource(reportContent); 34 | return ResponseEntity.ok() 35 | .contentType(MediaType.APPLICATION_OCTET_STREAM) 36 | .contentLength(resource.contentLength()) 37 | .header(HttpHeaders.CONTENT_DISPOSITION, 38 | ContentDisposition.attachment() 39 | .filename("item-report." + format) 40 | .build().toString()) 41 | .body(resource); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /jasper-reports-example/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.datasource.url=jdbc:h2:mem:testDB_CLOSE_DELAY=-1 2 | spring.datasource.username=sa 3 | spring.datasource.password= 4 | spring.datasource.driverClassName=org.h2.Driver 5 | spring.jpa.database-platform=org.hibernate.dialect.H2Dialect -------------------------------------------------------------------------------- /jasper-reports-example/src/main/resources/item-report.jrxml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 10 | 11 | 12 | 13 | <band height="30" splitType="Stretch"> 14 | <textField> 15 | <reportElement x="200" y="0" width="200" height="30"/> 16 | <textElement/> 17 | <textFieldExpression class="java.lang.String"><![CDATA[$P{title}]]></textFieldExpression> 18 | </textField> 19 | </band> 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /jasper-reports-example/src/test/java/com/howtodoinjava/app/AppTest.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.app; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | public class AppTest { 8 | 9 | @Test 10 | public void contextLoads() { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /jsp-demo/pom.xml: -------------------------------------------------------------------------------- 1 | 4 | 4.0.0 5 | 6 | com.howtodoinjava 7 | Spring-Boot3-Demos 8 | 1.0-SNAPSHOT 9 | 10 | 11 | com.howtodoinjava.app 12 | jsp-demo 13 | war 14 | jsp-demo 15 | https://howtodoinjava.com 16 | 17 | 18 | UTF-8 19 | 20 | 21 | 22 | 23 | org.springframework.boot 24 | spring-boot-starter-web 25 | 26 | 27 | org.apache.tomcat.embed 28 | tomcat-embed-jasper 29 | provided 30 | 31 | 32 | jakarta.servlet.jsp.jstl 33 | jakarta.servlet.jsp.jstl-api 34 | 3.0.0 35 | 36 | 37 | org.glassfish.web 38 | jakarta.servlet.jsp.jstl 39 | 3.0.1 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /jsp-demo/src/main/java/com/howtodoinjava/app/App.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.app; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.boot.builder.SpringApplicationBuilder; 6 | import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; 7 | 8 | @SpringBootApplication 9 | public class App extends SpringBootServletInitializer { 10 | 11 | @Override 12 | protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) { 13 | return builder.sources(App.class); 14 | } 15 | 16 | public static void main(String[] args) { 17 | SpringApplication.run(App.class); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /jsp-demo/src/main/java/com/howtodoinjava/app/config/WebMvcConfig.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.app.config; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.web.servlet.ViewResolver; 6 | import org.springframework.web.servlet.config.annotation.EnableWebMvc; 7 | import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; 8 | import org.springframework.web.servlet.config.annotation.ViewResolverRegistry; 9 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; 10 | import org.springframework.web.servlet.resource.PathResourceResolver; 11 | import org.springframework.web.servlet.view.InternalResourceViewResolver; 12 | import org.springframework.web.servlet.view.JstlView; 13 | 14 | @Configuration 15 | @EnableWebMvc 16 | public class WebMvcConfig implements WebMvcConfigurer { 17 | 18 | @Bean 19 | public ViewResolver viewResolver() { 20 | final InternalResourceViewResolver bean = new InternalResourceViewResolver(); 21 | bean.setViewClass(JstlView.class); 22 | bean.setPrefix("/WEB-INF/jsp/"); 23 | bean.setSuffix(".jsp"); 24 | return bean; 25 | } 26 | 27 | @Override 28 | public void configureViewResolvers(ViewResolverRegistry registry) { 29 | registry.viewResolver(viewResolver()); 30 | } 31 | 32 | @Override 33 | public void addResourceHandlers(ResourceHandlerRegistry registry) { 34 | registry 35 | .addResourceHandler("/static/**") 36 | .addResourceLocations("classpath:/static/") 37 | .setCachePeriod(3600) 38 | .resourceChain(true) 39 | .addResolver(new PathResourceResolver()); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /jsp-demo/src/main/java/com/howtodoinjava/app/model/Item.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.app.model; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | @Data 8 | @AllArgsConstructor 9 | @NoArgsConstructor 10 | public class Item { 11 | 12 | private Long id; 13 | private String name; 14 | } 15 | -------------------------------------------------------------------------------- /jsp-demo/src/main/java/com/howtodoinjava/app/service/ItemService.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.app.service; 2 | 3 | import com.howtodoinjava.app.model.Item; 4 | import java.util.List; 5 | import org.springframework.stereotype.Service; 6 | 7 | @Service 8 | public class ItemService { 9 | 10 | public List getAll() { 11 | return List.of(new Item(1L, "Item - 1"), new Item(2L, "Item - 2")); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /jsp-demo/src/main/java/com/howtodoinjava/app/web/ItemController.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.app.web; 2 | 3 | import com.howtodoinjava.app.service.ItemService; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.stereotype.Controller; 6 | import org.springframework.web.bind.annotation.RequestMapping; 7 | import org.springframework.web.servlet.ModelAndView; 8 | 9 | @Controller 10 | public class ItemController { 11 | 12 | @Autowired 13 | ItemService itemService; 14 | 15 | @RequestMapping("/view-items") 16 | public ModelAndView viewBooks(ModelAndView model) { 17 | model.setViewName("view-items"); 18 | model.addObject("items", itemService.getAll()); 19 | return model; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /jsp-demo/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.mvc.view.prefix=/WEB-INF/jsp/ 2 | spring.mvc.view.suffix=.jsp 3 | 4 | logging.level.root=info -------------------------------------------------------------------------------- /jsp-demo/src/main/resources/static/css/style.css: -------------------------------------------------------------------------------- 1 | table { 2 | font-family: arial, sans-serif; 3 | border-collapse: collapse; 4 | } 5 | 6 | td, th { 7 | border: 1px solid #dddddd; 8 | text-align: left; 9 | padding: 8px; 10 | } -------------------------------------------------------------------------------- /jsp-demo/src/main/webapp/WEB-INF/jsp/view-items.jsp: -------------------------------------------------------------------------------- 1 | <%@ page contentType="text/html;charset=UTF-8" language="java" %> 2 | <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> 3 | 4 | 5 | View Items 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 |
IdName
${item.id}${item.name}
25 | 26 | -------------------------------------------------------------------------------- /jsp-demo/src/test/java/com/howtodoinjava/app/AppTest.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.app; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | public class AppTest { 8 | 9 | @Test 10 | void contextLoads(){ 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /mybatis-example/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 4.0.0 7 | 8 | com.howtodoinjava 9 | mybatis-example 10 | 1.0-SNAPSHOT 11 | 12 | mybatis-example 13 | https://howtodoinjava.com 14 | 15 | 16 | com.howtodoinjava 17 | Spring-Boot3-Demos 18 | 1.0-SNAPSHOT 19 | 20 | 21 | 22 | 23 | org.mybatis.spring.boot 24 | mybatis-spring-boot-starter 25 | 3.0.0 26 | 27 | 28 | com.h2database 29 | h2 30 | runtime 31 | 32 | 33 | org.springframework.boot 34 | spring-boot-devtools 35 | runtime 36 | true 37 | 38 | 39 | org.mockito 40 | mockito-junit-jupiter 41 | test 42 | 43 | 44 | jakarta.servlet 45 | jakarta.servlet-api 46 | 5.0.0 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /mybatis-example/src/main/java/com/howtodoinjava/app/App.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.app; 2 | 3 | import com.howtodoinjava.app.mapper.ToDoMapper; 4 | import com.howtodoinjava.app.model.TODO; 5 | import org.springframework.beans.factory.annotation.Autowired; 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 App implements CommandLineRunner 12 | { 13 | public static void main(String[] args) { 14 | SpringApplication.run(App.class, args); 15 | } 16 | 17 | @Autowired 18 | private ToDoMapper todoMapper; 19 | 20 | @Override 21 | public void run(String... args) throws Exception { 22 | 23 | TODO newItem = new TODO(2L, "title_2", "body_2"); 24 | int createdCount = todoMapper.createNew(newItem); 25 | System.out.println("Created items count : " + createdCount); 26 | 27 | TODO item = todoMapper.findById(2L); 28 | System.out.println(item); 29 | 30 | int deletedCount = todoMapper.deleteById(2L); 31 | System.out.println("Deleted items count : " + deletedCount); 32 | 33 | TODO deletedItem = todoMapper.findById(2L); 34 | System.out.println("Deleted item should be null : " + deletedItem); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /mybatis-example/src/main/java/com/howtodoinjava/app/config/PersistenceConfig.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.app.config; 2 | 3 | import javax.sql.DataSource; 4 | import org.apache.ibatis.session.SqlSessionFactory; 5 | import org.mybatis.spring.SqlSessionFactoryBean; 6 | import org.mybatis.spring.annotation.MapperScan; 7 | import org.springframework.context.annotation.Bean; 8 | import org.springframework.context.annotation.Configuration; 9 | import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; 10 | import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType; 11 | 12 | @Configuration 13 | //@MapperScan("com.howtodoinjava.app.mapper") 14 | public class PersistenceConfig { 15 | 16 | @Bean 17 | public DataSource dataSource() { 18 | return new EmbeddedDatabaseBuilder() 19 | .setType(EmbeddedDatabaseType.H2) 20 | .addScript("schema.sql") 21 | .addScript("data.sql") 22 | .build(); 23 | } 24 | 25 | @Bean 26 | public SqlSessionFactory sqlSessionFactory() throws Exception { 27 | SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean(); 28 | factoryBean.setDataSource(dataSource()); 29 | return factoryBean.getObject(); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /mybatis-example/src/main/java/com/howtodoinjava/app/mapper/ToDoMapper.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.app.mapper; 2 | 3 | import com.howtodoinjava.app.model.TODO; 4 | import java.util.List; 5 | import org.apache.ibatis.annotations.Delete; 6 | import org.apache.ibatis.annotations.Insert; 7 | import org.apache.ibatis.annotations.Mapper; 8 | import org.apache.ibatis.annotations.Param; 9 | import org.apache.ibatis.annotations.Select; 10 | import org.apache.ibatis.annotations.Update; 11 | 12 | @Mapper 13 | public interface ToDoMapper { 14 | 15 | @Select("select * from TBL_TODO") 16 | List findAll(); 17 | 18 | @Select("SELECT * FROM TBL_TODO WHERE id = #{id}") 19 | TODO findById(@Param("id") Long id); 20 | 21 | @Delete("DELETE FROM TBL_TODO WHERE id = #{id}") 22 | int deleteById(@Param("id") Long id); 23 | 24 | @Insert("INSERT INTO TBL_TODO(id, title, body) " + 25 | " VALUES (#{id}, #{title}, #{body})") 26 | int createNew(TODO item); 27 | 28 | @Update("Update TBL_TODO set title=#{title}, " + 29 | " body=#{body} where id=#{id}") 30 | int update(TODO item); 31 | } 32 | -------------------------------------------------------------------------------- /mybatis-example/src/main/java/com/howtodoinjava/app/model/TODO.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.app.model; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | @Data 8 | @NoArgsConstructor 9 | @AllArgsConstructor 10 | public class TODO { 11 | private Long id; 12 | private String title; 13 | private String body; 14 | } 15 | -------------------------------------------------------------------------------- /mybatis-example/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | #spring.datasource.url=jdbc:h2:file:/data/articles 2 | #spring.datasource.driverClassName=org.h2.Driver 3 | #spring.datasource.username=sa 4 | #spring.datasource.password= 5 | #spring.jpa.database-platform=org.hibernate.dialect.H2Dialect 6 | 7 | #spring.sql.init.mode=always 8 | -------------------------------------------------------------------------------- /mybatis-example/src/main/resources/data.sql: -------------------------------------------------------------------------------- 1 | TRUNCATE TABLE TBL_TODO; 2 | 3 | INSERT INTO TBL_TODO VALUES (1, 'TITLE', 'BODY'); -------------------------------------------------------------------------------- /mybatis-example/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /mybatis-example/src/main/resources/schema.sql: -------------------------------------------------------------------------------- 1 | create TABLE IF NOT EXISTS `TBL_TODO`( 2 | `id` INTEGER PRIMARY KEY, 3 | `title` VARCHAR(100) NOT NULL, 4 | `body` VARCHAR(2000) NOT NULL 5 | ); -------------------------------------------------------------------------------- /mybatis-example/src/test/java/com/howtodoinjava/AppTest.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava; 2 | 3 | import org.junit.jupiter.api.Test; 4 | 5 | public class AppTest 6 | { 7 | @Test 8 | public void contextLoads() 9 | { 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /problem-detail-error-responses-example/.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | !**/src/main/**/target/ 4 | !**/src/test/**/target/ 5 | 6 | ### IntelliJ IDEA ### 7 | .idea/modules.xml 8 | .idea/jarRepositories.xml 9 | .idea/compiler.xml 10 | .idea/libraries/ 11 | *.iws 12 | *.iml 13 | *.ipr 14 | 15 | ### Eclipse ### 16 | .apt_generated 17 | .classpath 18 | .factorypath 19 | .project 20 | .settings 21 | .springBeans 22 | .sts4-cache 23 | 24 | ### NetBeans ### 25 | /nbproject/private/ 26 | /nbbuild/ 27 | /dist/ 28 | /nbdist/ 29 | /.nb-gradle/ 30 | build/ 31 | !**/src/main/**/build/ 32 | !**/src/test/**/build/ 33 | 34 | ### VS Code ### 35 | .vscode/ 36 | 37 | ### Mac OS ### 38 | .DS_Store -------------------------------------------------------------------------------- /problem-detail-error-responses-example/README.md: -------------------------------------------------------------------------------- 1 | # Related Tutorials 2 | 3 | * [Guide to Spring ProblemDetail and ErrorResponse](https://howtodoinjava.com/spring-mvc/spring-problemdetail-errorresponse/) 4 | 5 | -------------------------------------------------------------------------------- /problem-detail-error-responses-example/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 4.0.0 7 | 8 | com.howtodoinjava 9 | problem-detail-error-responses-example 10 | 1.0-SNAPSHOT 11 | 12 | problem-detail-error-responses-example 13 | https://howtodoinjava.com 14 | 15 | 16 | com.howtodoinjava 17 | Spring-Boot3-Demos 18 | 1.0-SNAPSHOT 19 | 20 | 21 | 22 | UTF-8 23 | 17 24 | 17 25 | 26 | 27 | 28 | 29 | org.springframework.boot 30 | spring-boot-starter-web 31 | 32 | 33 | org.springframework.boot 34 | spring-boot-starter-webflux 35 | 36 | 37 | org.springframework.boot 38 | spring-boot-devtools 39 | runtime 40 | true 41 | 42 | 43 | org.mockito 44 | mockito-junit-jupiter 45 | test 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /problem-detail-error-responses-example/src/main/java/com/howtodoinjava/App.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class App 8 | { 9 | public static void main(String[] args) { 10 | SpringApplication.run(App.class, args); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /problem-detail-error-responses-example/src/main/java/com/howtodoinjava/app/model/Employee.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.app.model; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | @Data 8 | @AllArgsConstructor 9 | @NoArgsConstructor 10 | public class Employee { 11 | 12 | private Long id; 13 | private String firstName; 14 | private String lastName; 15 | private String email; 16 | } 17 | -------------------------------------------------------------------------------- /problem-detail-error-responses-example/src/main/java/com/howtodoinjava/errors/RecordNotFoundException.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.errors; 2 | 3 | public class RecordNotFoundException extends RuntimeException { 4 | 5 | private final String message; 6 | 7 | public RecordNotFoundException(String message) { 8 | this.message = message; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /problem-detail-error-responses-example/src/main/java/com/howtodoinjava/web/GlobalExceptionHandler.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.web; 2 | 3 | import com.howtodoinjava.errors.RecordNotFoundException; 4 | import java.net.URI; 5 | import org.springframework.beans.factory.annotation.Value; 6 | import org.springframework.http.HttpStatusCode; 7 | import org.springframework.http.ProblemDetail; 8 | import org.springframework.web.bind.annotation.ControllerAdvice; 9 | import org.springframework.web.bind.annotation.ExceptionHandler; 10 | import org.springframework.web.context.request.WebRequest; 11 | import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; 12 | 13 | @ControllerAdvice 14 | public class GlobalExceptionHandler extends ResponseEntityExceptionHandler { 15 | 16 | @Value("${hostname}") 17 | private String hostname; 18 | 19 | @ExceptionHandler(RecordNotFoundException.class) 20 | public ProblemDetail handleRecordNotFoundException( 21 | RecordNotFoundException ex, WebRequest request) { 22 | 23 | ProblemDetail body = ProblemDetail 24 | .forStatusAndDetail(HttpStatusCode.valueOf(404),ex.getLocalizedMessage()); 25 | body.setType(URI.create("http://my-app-host.com/errors/not-found")); 26 | body.setTitle("Record Not Found"); 27 | body.setProperty("hostname", hostname); 28 | 29 | return body; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /problem-detail-error-responses-example/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | hostname=localhost -------------------------------------------------------------------------------- /problem-detail-error-responses-example/src/test/java/com/howtodoinjava/AppTest.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | public class AppTest 8 | { 9 | @Test 10 | void contextLoads() { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /problem-detail-error-responses-example/src/test/resources/application-test.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lokeshgupta1981/Spring-Boot3-Demos/6974e42d87a604213d2cdb2c0b2a1e26418e172c/problem-detail-error-responses-example/src/test/resources/application-test.properties -------------------------------------------------------------------------------- /programmatic-validator/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | org.springframework.boot 8 | spring-boot-starter-parent 9 | 3.2.0-M3 10 | 11 | 12 | 13 | com.howtodoinjava.app 14 | programmatic-validator 15 | jar 16 | 17 | 18 | 21 19 | 21 20 | UTF-8 21 | 22 | 23 | 24 | 25 | org.projectlombok 26 | lombok 27 | true 28 | 1.18.30 29 | 30 | 31 | org.springframework.boot 32 | spring-boot-starter-web 33 | 34 | 35 | org.springframework.boot 36 | spring-boot-starter-thymeleaf 37 | 38 | 39 | org.springframework.boot 40 | spring-boot-starter-webflux 41 | 42 | 43 | org.springframework.boot 44 | spring-boot-starter-test 45 | 46 | 47 | 48 | 49 | 50 | spring-milestone 51 | Spring Milestones 52 | https://repo.spring.io/milestone 53 | 54 | 55 | -------------------------------------------------------------------------------- /programmatic-validator/src/main/java/com/howtodoinjava/app/customValidator/model/Department.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.app.customValidator.model; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | @Data 9 | @Builder 10 | @NoArgsConstructor 11 | @AllArgsConstructor 12 | public class Department { 13 | 14 | Long id; 15 | String name; 16 | boolean active; 17 | } 18 | -------------------------------------------------------------------------------- /programmatic-validator/src/main/java/com/howtodoinjava/app/customValidator/model/Employee.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.app.customValidator.model; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | @Data 9 | @Builder 10 | @NoArgsConstructor 11 | @AllArgsConstructor 12 | public class Employee { 13 | 14 | Long id; 15 | String firstName; 16 | String lastName; 17 | String email; 18 | Boolean active; 19 | 20 | Department department; 21 | } 22 | -------------------------------------------------------------------------------- /programmatic-validator/src/main/java/com/howtodoinjava/app/customValidator/model/validation/DepartmentValidator.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.app.customValidator.model.validation; 2 | 3 | import com.howtodoinjava.app.customValidator.model.Department; 4 | import org.springframework.validation.Errors; 5 | import org.springframework.validation.ValidationUtils; 6 | import org.springframework.validation.Validator; 7 | 8 | public class DepartmentValidator implements Validator { 9 | @Override 10 | public boolean supports(Class clazz) { 11 | return Department.class.equals(clazz); 12 | } 13 | 14 | @Override 15 | public void validate(Object target, Errors errors) { 16 | //ValidationUtils.rejectIfEmpty(errors, "id", ValidationErrorCodes.ERROR_CODE_EMPTY); 17 | ValidationUtils.rejectIfEmptyOrWhitespace(errors, "name", ValidationErrorCodes.ERROR_CODE_EMPTY); 18 | 19 | Department department = (Department) target; 20 | 21 | if(department.getName() != null && department.getName().length() < 3) { 22 | errors.rejectValue("name", ValidationErrorCodes.ERROR_CODE_SIZE); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /programmatic-validator/src/main/java/com/howtodoinjava/app/customValidator/model/validation/ValidationErrorCodes.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.app.customValidator.model.validation; 2 | 3 | public class ValidationErrorCodes { 4 | 5 | public static String ERROR_CODE_EMPTY = "error.field.empty"; 6 | public static String ERROR_CODE_SIZE = "error.field.size"; 7 | } 8 | -------------------------------------------------------------------------------- /programmatic-validator/src/main/java/com/howtodoinjava/app/customValidator/web/EmployeeController.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.app.customValidator.web; 2 | 3 | import com.howtodoinjava.app.customValidator.model.Employee; 4 | import com.howtodoinjava.app.customValidator.model.validation.DepartmentValidator; 5 | import com.howtodoinjava.app.customValidator.model.validation.EmployeeValidator; 6 | import org.springframework.stereotype.Controller; 7 | import org.springframework.ui.Model; 8 | import org.springframework.validation.BindingResult; 9 | import org.springframework.validation.annotation.Validated; 10 | import org.springframework.web.bind.WebDataBinder; 11 | import org.springframework.web.bind.annotation.*; 12 | 13 | @Controller 14 | @RequestMapping("/employees") 15 | public class EmployeeController { 16 | 17 | @InitBinder 18 | protected void initBinder(WebDataBinder binder) { 19 | // Injecting Programmatic Validators 20 | binder.setValidator(new EmployeeValidator(new DepartmentValidator())); 21 | } 22 | 23 | @GetMapping("/registration") 24 | public String showRegistrationForm(Model model) { 25 | model.addAttribute("employee", Employee.builder().build()); 26 | return "employee-registration-form"; 27 | } 28 | 29 | @PostMapping("/processRegistration") 30 | public String processRegistration( 31 | @Validated @ModelAttribute("employee") Employee employee, 32 | BindingResult bindingResult) { 33 | 34 | if (bindingResult.hasErrors()) { 35 | return "employee-registration-form"; 36 | } 37 | 38 | // Logic for handling a successful form submission 39 | // Typically involving database operations, authentication, etc. 40 | 41 | return "employee-registration-confirmation"; // Redirect to a success page 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /programmatic-validator/src/main/resources/messages.properties: -------------------------------------------------------------------------------- 1 | error.field.empty=Field cannot be empty 2 | error.field.size=Field must be between 3 and 20 -------------------------------------------------------------------------------- /programmatic-validator/src/test/java/com/howtodoinjava/app/customValidator/model/validation/TestEmployeeValidator.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.app.customValidator.model.validation; 2 | 3 | import com.howtodoinjava.app.customValidator.model.Department; 4 | import com.howtodoinjava.app.customValidator.model.Employee; 5 | import org.junit.jupiter.api.Assertions; 6 | import org.junit.jupiter.api.BeforeAll; 7 | import org.junit.jupiter.api.Test; 8 | import org.springframework.validation.BeanPropertyBindingResult; 9 | import org.springframework.validation.Errors; 10 | 11 | public class TestEmployeeValidator { 12 | 13 | static EmployeeValidator employeeValidator; 14 | 15 | @BeforeAll 16 | static void setup() { 17 | employeeValidator = new EmployeeValidator(new DepartmentValidator()); 18 | } 19 | 20 | @Test 21 | void validate_ValidInput_NoErrors() { 22 | // Set up a valid user 23 | Employee employee = Employee.builder().id(1L) 24 | .firstName("Lokesh").lastName("Gupta").email("admin@howtodoinjava.com") 25 | .department(Department.builder().id(2L).name("Finance").build()).build(); 26 | 27 | Errors errors = new BeanPropertyBindingResult(employee, "employee"); 28 | employeeValidator.validate(employee, errors); 29 | 30 | Assertions.assertFalse(errors.hasErrors()); 31 | } 32 | 33 | @Test 34 | void validate_InvalidInput_HasErrors() { 35 | // Set up a valid user 36 | Employee employee = Employee.builder().id(1L) 37 | .firstName("A").lastName("B").email("C") 38 | .department(Department.builder().id(2L).name("HR").build()).build(); 39 | 40 | Errors errors = new BeanPropertyBindingResult(employee, "employee"); 41 | employeeValidator.validate(employee, errors); 42 | 43 | Assertions.assertTrue(errors.hasErrors()); 44 | Assertions.assertEquals(3, errors.getErrorCount()); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /rest-api-crud-example/pom.xml: -------------------------------------------------------------------------------- 1 | 4 | 4.0.0 5 | 6 | com.howtodoinjava 7 | Spring-Boot3-Demos 8 | 1.0-SNAPSHOT 9 | 10 | 11 | rest-api-crud-example 12 | jar 13 | rest-api-crud-example 14 | https://howtodoinjava.com 15 | 16 | 17 | UTF-8 18 | 19 | 20 | 21 | 22 | org.springframework.boot 23 | spring-boot-starter-web 24 | 25 | 26 | org.springframework.boot 27 | spring-boot-starter-data-jpa 28 | 29 | 30 | com.h2database 31 | h2 32 | runtime 33 | 34 | 35 | org.springframework.boot 36 | spring-boot-starter-validation 37 | 38 | 39 | org.springdoc 40 | springdoc-openapi-starter-webmvc-ui 41 | 2.1.0 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /rest-api-crud-example/src/main/java/com/howtodoinjava/App.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava; 2 | 3 | import com.howtodoinjava.dao.model.Item; 4 | import com.howtodoinjava.dao.model.ItemRepository; 5 | import org.springframework.beans.factory.annotation.Autowired; 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 App implements CommandLineRunner { 12 | 13 | public static void main(String[] args) { 14 | SpringApplication.run(App.class, args); 15 | } 16 | 17 | @Autowired 18 | ItemRepository itemRepository; 19 | 20 | @Override 21 | public void run(String... args) throws Exception { 22 | itemRepository.save(new Item(null, "Item 1")); 23 | itemRepository.save(new Item(null, "Item 2")); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /rest-api-crud-example/src/main/java/com/howtodoinjava/dao/model/Item.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.dao.model; 2 | 3 | import jakarta.persistence.Entity; 4 | import jakarta.persistence.GeneratedValue; 5 | import jakarta.persistence.GenerationType; 6 | import jakarta.persistence.Id; 7 | import jakarta.validation.constraints.NotBlank; 8 | import lombok.AllArgsConstructor; 9 | import lombok.Data; 10 | import lombok.NoArgsConstructor; 11 | 12 | @Entity 13 | @Data 14 | @NoArgsConstructor 15 | @AllArgsConstructor 16 | public class Item { 17 | 18 | @Id 19 | @GeneratedValue(strategy = GenerationType.IDENTITY) 20 | private Long id; 21 | 22 | @NotBlank(message = "Item name must not be blank") 23 | private String name; 24 | } 25 | -------------------------------------------------------------------------------- /rest-api-crud-example/src/main/java/com/howtodoinjava/dao/model/ItemRepository.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.dao.model; 2 | 3 | import org.springframework.data.jpa.repository.JpaRepository; 4 | import org.springframework.stereotype.Repository; 5 | 6 | @Repository 7 | public interface ItemRepository extends JpaRepository { 8 | 9 | } 10 | -------------------------------------------------------------------------------- /rest-api-crud-example/src/main/java/com/howtodoinjava/web/ItemController.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.web; 2 | 3 | import com.howtodoinjava.dao.model.Item; 4 | import com.howtodoinjava.dao.model.ItemRepository; 5 | import com.howtodoinjava.web.errors.ItemNotFoundException; 6 | import jakarta.validation.Valid; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.web.bind.annotation.*; 9 | 10 | import java.util.List; 11 | 12 | @RestController 13 | public class ItemController { 14 | 15 | @Autowired 16 | ItemRepository itemRepository; 17 | 18 | @GetMapping("/items") 19 | List all() { 20 | return itemRepository.findAll(); 21 | } 22 | 23 | @GetMapping("/items/{id}") 24 | Item getById(@PathVariable Long id) { 25 | 26 | return itemRepository.findById(id) 27 | .orElseThrow(() -> new ItemNotFoundException(id)); 28 | } 29 | 30 | @PostMapping("/items") 31 | Item createNew(@Valid @RequestBody Item newItem) { 32 | return itemRepository.save(newItem); 33 | } 34 | 35 | @DeleteMapping("/items/{id}") 36 | void delete(@PathVariable Long id) { 37 | itemRepository.deleteById(id); 38 | } 39 | 40 | @PutMapping("/items/{id}") 41 | Item updateOrCreate(@RequestBody Item newItem, @PathVariable Long id) { 42 | 43 | return itemRepository.findById(id) 44 | .map(item -> { 45 | item.setName(newItem.getName()); 46 | return itemRepository.save(item); 47 | }) 48 | .orElseGet(() -> { 49 | newItem.setId(id); 50 | return itemRepository.save(newItem); 51 | }); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /rest-api-crud-example/src/main/java/com/howtodoinjava/web/errors/ApplicationExceptionHandler.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.web.errors; 2 | 3 | import org.springframework.http.HttpStatus; 4 | import org.springframework.http.HttpStatusCode; 5 | import org.springframework.http.ProblemDetail; 6 | import org.springframework.http.ResponseEntity; 7 | import org.springframework.validation.FieldError; 8 | import org.springframework.web.ErrorResponse; 9 | import org.springframework.web.bind.MethodArgumentNotValidException; 10 | import org.springframework.web.bind.annotation.ExceptionHandler; 11 | import org.springframework.web.bind.annotation.ResponseStatus; 12 | import org.springframework.web.bind.annotation.RestControllerAdvice; 13 | import org.springframework.web.context.request.WebRequest; 14 | 15 | import java.net.URI; 16 | import java.util.ArrayList; 17 | import java.util.List; 18 | 19 | @RestControllerAdvice 20 | public class ApplicationExceptionHandler { 21 | 22 | @ExceptionHandler(MethodArgumentNotValidException.class) 23 | @ResponseStatus(HttpStatus.BAD_REQUEST) 24 | ResponseEntity handleMethodArgumentNotValid(MethodArgumentNotValidException ex) { 25 | List details = new ArrayList<>(); 26 | for (FieldError error : ex.getBindingResult().getFieldErrors()) { 27 | details.add(error.getDefaultMessage()); 28 | } 29 | ProblemDetail body = ProblemDetail 30 | .forStatusAndDetail(HttpStatusCode.valueOf(404), ex.getLocalizedMessage()); 31 | body.setType(URI.create("http://my-app-host.com/errors/bad-request")); 32 | body.setTitle("Bad Request"); 33 | body.setProperty("details", details); 34 | return ResponseEntity.badRequest() 35 | .body(body); 36 | } 37 | 38 | @ExceptionHandler(ItemNotFoundException.class) 39 | public ProblemDetail handleItemNotFoundException( 40 | ItemNotFoundException ex, WebRequest request) { 41 | 42 | ProblemDetail body = ProblemDetail 43 | .forStatusAndDetail(HttpStatusCode.valueOf(404), ex.getLocalizedMessage()); 44 | body.setType(URI.create("http://my-app-host.com/errors/not-found")); 45 | body.setTitle("Item Not Found"); 46 | body.setProperty("hostname", "localhost"); 47 | return body; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /rest-api-crud-example/src/main/java/com/howtodoinjava/web/errors/ErrorResponse.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.web.errors; 2 | 3 | import jakarta.xml.bind.annotation.XmlRootElement; 4 | import java.util.List; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | @XmlRootElement(name = "error") 10 | @AllArgsConstructor 11 | @NoArgsConstructor 12 | @Data 13 | public class ErrorResponse { 14 | 15 | private String message; 16 | private List details; 17 | } 18 | -------------------------------------------------------------------------------- /rest-api-crud-example/src/main/java/com/howtodoinjava/web/errors/ItemNotFoundException.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.web.errors; 2 | 3 | public class ItemNotFoundException extends RuntimeException { 4 | 5 | private Long id; 6 | 7 | public ItemNotFoundException(Long id) { 8 | super("Could not find item " + id); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /rest-api-crud-example/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.datasource.url=jdbc:h2:mem:test 2 | spring.datasource.username=sa 3 | spring.datasource.password= 4 | spring.datasource.driverClassName=org.h2.Driver 5 | spring.jpa.database-platform=org.hibernate.dialect.H2Dialect 6 | 7 | spring.jpa.hibernate.ddl-auto=update -------------------------------------------------------------------------------- /rest-api-crud-example/src/test/java/com/howtodoinjava/AppTest.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | public class AppTest 8 | { 9 | @Test 10 | void contextLoads() { 11 | } 12 | } -------------------------------------------------------------------------------- /rsocket/.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled class file 2 | *.class 3 | 4 | # Log file 5 | *.log 6 | 7 | # BlueJ files 8 | *.ctxt 9 | 10 | # Mobile Tools for Java (J2ME) 11 | .mtj.tmp/ 12 | 13 | # Package Files # 14 | *.jar 15 | *.war 16 | *.nar 17 | *.ear 18 | *.zip 19 | *.tar.gz 20 | *.rar 21 | 22 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 23 | hs_err_pid* 24 | replay_pid* 25 | -------------------------------------------------------------------------------- /rsocket/README.md: -------------------------------------------------------------------------------- 1 | # Related Tutorials 2 | * [RSocket with Spring Boot](https://howtodoinjava.com/spring-boot/rsocket-tutorial/) 3 | * [Spring @RSocketExchange with Example](https://howtodoinjava.com/spring-boot/rsocketexchange-example/) 4 | -------------------------------------------------------------------------------- /rsocket/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 4.0.0 8 | com.howtodoinjava 9 | rsocket 10 | 1.0-SNAPSHOT 11 | rsocket 12 | 13 | 14 | com.howtodoinjava 15 | Spring-Boot3-Demos 16 | 1.0-SNAPSHOT 17 | 18 | 19 | 20 | 21 | org.springframework.boot 22 | spring-boot-starter-rsocket 23 | 24 | 25 | 26 | 27 | 28 | org.springframework.boot 29 | spring-boot-maven-plugin 30 | 31 | com.howtodoinjava.app.rsocketexchange.App 32 | 33 | 34 | org.projectlombok 35 | lombok 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /rsocket/src/main/java/com/howtodoinjava/app/bidirectional/App.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.app.bidirectional; 2 | 3 | import com.howtodoinjava.app.bidirectional.model.LoanDetails; 4 | import com.howtodoinjava.app.fireAndForget.model.Event; 5 | import com.howtodoinjava.app.fireAndForget.model.Event.Type; 6 | import java.time.Duration; 7 | import java.time.Instant; 8 | import lombok.extern.slf4j.Slf4j; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.boot.CommandLineRunner; 11 | import org.springframework.boot.SpringApplication; 12 | import org.springframework.boot.autoconfigure.SpringBootApplication; 13 | import org.springframework.messaging.rsocket.RSocketRequester; 14 | import reactor.core.publisher.Flux; 15 | 16 | @SpringBootApplication 17 | @Slf4j 18 | public class App implements CommandLineRunner { 19 | 20 | public static void main(String[] args) { 21 | SpringApplication.run(App.class, args); 22 | } 23 | 24 | @Autowired 25 | RSocketRequester.Builder requesterBuilder; 26 | 27 | @Override 28 | public void run(String... args) throws Exception { 29 | RSocketRequester rSocketRequester = requesterBuilder.tcp("localhost", 7000); 30 | 31 | Flux lonaDetailsFlux = 32 | Flux.fromArray(new LoanDetails[]{ 33 | new LoanDetails(100, 5, 1), 34 | new LoanDetails(200, 7, 1), 35 | new LoanDetails(300, 10, 1), 36 | new LoanDetails(400, 8, 1), 37 | new LoanDetails(600, 11, 1) 38 | }) 39 | .delayElements(Duration.ofSeconds(2)); 40 | 41 | rSocketRequester 42 | .route("check-loan-eligibility") 43 | .data(lonaDetailsFlux) 44 | .retrieveFlux(Boolean.class) 45 | .subscribe(result -> 46 | log.info("Loan eligibility : {}", result)); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /rsocket/src/main/java/com/howtodoinjava/app/bidirectional/controller/LoanCheckController.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.app.bidirectional.controller; 2 | 3 | import com.howtodoinjava.app.bidirectional.model.LoanDetails; 4 | import lombok.extern.slf4j.Slf4j; 5 | import org.springframework.messaging.handler.annotation.MessageMapping; 6 | import org.springframework.stereotype.Controller; 7 | import reactor.core.publisher.Flux; 8 | 9 | @Controller 10 | @Slf4j 11 | public class LoanCheckController { 12 | 13 | @MessageMapping("check-loan-eligibility") 14 | public Flux calculate(Flux loanDetails) { 15 | return loanDetails 16 | .doOnNext(ld -> log.info("Calculating eligibility: {}", ld)) 17 | .map(ld -> { 18 | return ld.getRate() > 9; 19 | }); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /rsocket/src/main/java/com/howtodoinjava/app/bidirectional/model/LoanDetails.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.app.bidirectional.model; 2 | 3 | import java.time.Period; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | 7 | @Data 8 | @AllArgsConstructor 9 | public class LoanDetails { 10 | 11 | private double amount; 12 | private float rate; 13 | private int years; 14 | } 15 | -------------------------------------------------------------------------------- /rsocket/src/main/java/com/howtodoinjava/app/fireAndForget/App.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.app.fireAndForget; 2 | 3 | import com.howtodoinjava.app.fireAndForget.model.Event; 4 | import com.howtodoinjava.app.fireAndForget.model.Event.Type; 5 | import java.time.Instant; 6 | import lombok.extern.slf4j.Slf4j; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.boot.CommandLineRunner; 9 | import org.springframework.boot.SpringApplication; 10 | import org.springframework.boot.autoconfigure.SpringBootApplication; 11 | import org.springframework.messaging.rsocket.RSocketRequester; 12 | 13 | @SpringBootApplication 14 | @Slf4j 15 | public class App implements CommandLineRunner { 16 | 17 | public static void main(String[] args) { 18 | SpringApplication.run(App.class, args); 19 | } 20 | 21 | @Autowired 22 | RSocketRequester.Builder requesterBuilder; 23 | 24 | @Override 25 | public void run(String... args) throws Exception { 26 | RSocketRequester rSocketRequester = requesterBuilder.tcp("localhost", 7000); 27 | 28 | rSocketRequester 29 | .route("event") 30 | .data(new Event(11L, Type.ERROR, Instant.now())) 31 | .send() 32 | .subscribe(); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /rsocket/src/main/java/com/howtodoinjava/app/fireAndForget/controller/EventController.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.app.fireAndForget.controller; 2 | 3 | import com.howtodoinjava.app.fireAndForget.model.Event; 4 | import lombok.extern.slf4j.Slf4j; 5 | import org.springframework.messaging.handler.annotation.MessageMapping; 6 | import org.springframework.stereotype.Controller; 7 | import reactor.core.publisher.Mono; 8 | 9 | @Controller 10 | @Slf4j 11 | public class EventController { 12 | 13 | @MessageMapping("event") 14 | public Mono setAlert(Mono alertMono) { 15 | return alertMono 16 | .doOnNext(event -> 17 | log.info("Event Id '{}' occurred of type '{}' at '{}'", 18 | event.getId(), 19 | event.getType(), 20 | event.getTimestamp()) 21 | ) 22 | .thenEmpty(Mono.empty()); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /rsocket/src/main/java/com/howtodoinjava/app/fireAndForget/model/Event.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.app.fireAndForget.model; 2 | 3 | import java.time.Instant; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | 7 | @Data 8 | @AllArgsConstructor 9 | public class Event { 10 | 11 | private Long id; 12 | private Type type; 13 | private Instant timestamp; 14 | 15 | public enum Type { 16 | SUCCESS, FAILURE, ERROR 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /rsocket/src/main/java/com/howtodoinjava/app/requestResponse/App.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.app.requestResponse; 2 | 3 | import lombok.extern.slf4j.Slf4j; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.boot.CommandLineRunner; 6 | import org.springframework.boot.SpringApplication; 7 | import org.springframework.boot.autoconfigure.SpringBootApplication; 8 | import org.springframework.messaging.rsocket.RSocketRequester; 9 | 10 | @SpringBootApplication 11 | @Slf4j 12 | public class App implements CommandLineRunner { 13 | 14 | public static void main(String[] args) { 15 | SpringApplication.run(App.class, args); 16 | } 17 | 18 | @Autowired 19 | RSocketRequester.Builder requesterBuilder; 20 | 21 | @Override 22 | public void run(String... args) throws Exception { 23 | RSocketRequester rsocketRequester = requesterBuilder.tcp("localhost", 7000); 24 | 25 | rsocketRequester 26 | .route("greeting/{name}", "Lokesh") 27 | .data("Hello there!") 28 | .retrieveMono(String.class) 29 | .subscribe(response -> log.info("RSocket response : {}", response)); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /rsocket/src/main/java/com/howtodoinjava/app/requestResponse/controller/MessageController.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.app.requestResponse.controller; 2 | 3 | import lombok.extern.slf4j.Slf4j; 4 | import org.springframework.messaging.handler.annotation.DestinationVariable; 5 | import org.springframework.messaging.handler.annotation.MessageMapping; 6 | import org.springframework.stereotype.Controller; 7 | import reactor.core.publisher.Mono; 8 | 9 | @Controller 10 | @Slf4j 11 | public class MessageController { 12 | 13 | @MessageMapping("greeting/{name}") 14 | public Mono greet(@DestinationVariable("name") String name, Mono greetingMono) { 15 | 16 | return greetingMono 17 | .doOnNext(greeting -> 18 | log.info("Received a greeting from {} : {}", name, greeting)) 19 | .map(greeting -> "Hello "+ name +"!"); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /rsocket/src/main/java/com/howtodoinjava/app/requestStream/App.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.app.requestStream; 2 | 3 | import com.howtodoinjava.app.requestStream.model.StockPrice; 4 | import lombok.extern.slf4j.Slf4j; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.boot.CommandLineRunner; 7 | import org.springframework.boot.SpringApplication; 8 | import org.springframework.boot.autoconfigure.SpringBootApplication; 9 | import org.springframework.messaging.rsocket.RSocketRequester; 10 | 11 | @SpringBootApplication 12 | @Slf4j 13 | public class App implements CommandLineRunner { 14 | 15 | public static void main(String[] args) { 16 | SpringApplication.run(App.class, args); 17 | } 18 | 19 | @Autowired 20 | RSocketRequester.Builder requesterBuilder; 21 | 22 | @Override 23 | public void run(String... args) throws Exception { 24 | RSocketRequester rSocketRequester = requesterBuilder.tcp("localhost", 7000); 25 | 26 | String stockSymbol = "TESLA"; 27 | 28 | rSocketRequester 29 | .route("stock/{symbol}", stockSymbol) 30 | .retrieveFlux(StockPrice.class) 31 | .doOnNext(stockPrice -> 32 | log.info( 33 | "Price of {} : {} (at {})", 34 | stockPrice.getSymbol(), 35 | stockPrice.getPrice(), 36 | stockPrice.getTimestamp()) 37 | ) 38 | .subscribe(); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /rsocket/src/main/java/com/howtodoinjava/app/requestStream/controller/StockPriceController.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.app.requestStream.controller; 2 | 3 | import com.howtodoinjava.app.requestStream.model.StockPrice; 4 | import java.math.BigDecimal; 5 | import java.time.Duration; 6 | import java.time.Instant; 7 | import org.springframework.messaging.handler.annotation.DestinationVariable; 8 | import org.springframework.messaging.handler.annotation.MessageMapping; 9 | import org.springframework.stereotype.Controller; 10 | import reactor.core.publisher.Flux; 11 | 12 | @Controller 13 | public class StockPriceController { 14 | 15 | @MessageMapping("stock/{symbol}") 16 | public Flux getStockPrice(@DestinationVariable("symbol") String symbol) { 17 | 18 | return Flux 19 | .interval(Duration.ofSeconds(1)) 20 | .map(i -> { 21 | BigDecimal price = BigDecimal.valueOf(Math.random() * 10); 22 | return new StockPrice(symbol, price, Instant.now()); 23 | }); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /rsocket/src/main/java/com/howtodoinjava/app/requestStream/model/StockPrice.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.app.requestStream.model; 2 | 3 | import java.math.BigDecimal; 4 | import java.time.Instant; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Data; 7 | 8 | @Data 9 | @AllArgsConstructor 10 | public class StockPrice { 11 | 12 | private String symbol; 13 | private BigDecimal price; 14 | private Instant timestamp; 15 | } 16 | -------------------------------------------------------------------------------- /rsocket/src/main/java/com/howtodoinjava/app/rsocketexchange/App.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.app.rsocketexchange; 2 | 3 | import com.howtodoinjava.app.rsocketexchange.declarativeClient.MessageService; 4 | import lombok.extern.slf4j.Slf4j; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.boot.CommandLineRunner; 7 | import org.springframework.boot.SpringApplication; 8 | import org.springframework.boot.autoconfigure.SpringBootApplication; 9 | import org.springframework.messaging.rsocket.RSocketRequester; 10 | import org.springframework.messaging.rsocket.service.RSocketServiceProxyFactory; 11 | import reactor.core.publisher.Mono; 12 | 13 | @SpringBootApplication 14 | @Slf4j 15 | public class App implements CommandLineRunner { 16 | 17 | public static void main(String[] args) { 18 | SpringApplication.run(App.class, args); 19 | } 20 | 21 | @Autowired 22 | RSocketRequester.Builder requesterBuilder; 23 | 24 | @Override 25 | public void run(String... args) throws Exception { 26 | RSocketRequester rsocketRequester = requesterBuilder.tcp("localhost", 7000); 27 | RSocketServiceProxyFactory factory = RSocketServiceProxyFactory.builder(rsocketRequester).build(); 28 | 29 | MessageService service = factory.createClient(MessageService.class); 30 | 31 | Mono response = service.sendMessage("Lokesh", Mono.just("Hello there!")); 32 | response.subscribe(message -> log.info("RSocket response : {}", message)); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /rsocket/src/main/java/com/howtodoinjava/app/rsocketexchange/controller/MessageController.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.app.rsocketexchange.controller; 2 | 3 | import lombok.extern.slf4j.Slf4j; 4 | import org.springframework.messaging.handler.annotation.DestinationVariable; 5 | import org.springframework.messaging.handler.annotation.MessageMapping; 6 | import org.springframework.stereotype.Controller; 7 | import reactor.core.publisher.Mono; 8 | 9 | @Controller 10 | @Slf4j 11 | public class MessageController { 12 | 13 | @MessageMapping("greeting/{name}") 14 | public Mono handleGreeting(@DestinationVariable("name") String name, 15 | Mono greetingMono) { 16 | return greetingMono 17 | .doOnNext(greeting -> 18 | log.info("Received a greeting from {} : {}", name, greeting)) 19 | .map(greeting -> "Hello "+ name +"!"); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /rsocket/src/main/java/com/howtodoinjava/app/rsocketexchange/declarativeClient/MessageService.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.app.rsocketexchange.declarativeClient; 2 | 3 | import org.springframework.messaging.handler.annotation.DestinationVariable; 4 | import org.springframework.messaging.handler.annotation.Payload; 5 | import org.springframework.messaging.rsocket.service.RSocketExchange; 6 | import reactor.core.publisher.Mono; 7 | 8 | public interface MessageService { 9 | 10 | @RSocketExchange("greeting/{name}") 11 | Mono sendMessage(@DestinationVariable("name") String name, 12 | @Payload Mono greetingMono); 13 | } 14 | -------------------------------------------------------------------------------- /rsocket/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.rsocket.server.port=7000 -------------------------------------------------------------------------------- /rsocket/src/test/java/com/howtodoinjava/AppTest.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertTrue; 4 | import org.junit.jupiter.api.Test; 5 | 6 | public class AppTest { 7 | 8 | @Test 9 | public void contextLoads() { 10 | assertTrue(true); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /security/pom.xml: -------------------------------------------------------------------------------- 1 | 4 | 4.0.0 5 | 6 | 7 | com.howtodoinjava 8 | Spring-Boot3-Demos 9 | 1.0-SNAPSHOT 10 | 11 | 12 | security 13 | jar 14 | security 15 | https://howtodoinjava.com 16 | 17 | 18 | 19 | org.springframework.boot 20 | spring-boot-starter-web 21 | 22 | 23 | org.springframework.boot 24 | spring-boot-starter-data-jpa 25 | 26 | 27 | com.h2database 28 | h2 29 | runtime 30 | 31 | 32 | org.springframework.boot 33 | spring-boot-starter-security 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /security/src/main/java/com/howtodoinjava/App.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class App { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(App.class, args); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /security/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.datasource.url=jdbc:h2:mem:testdb 2 | spring.datasource.driverClassName=org.h2.Driver 3 | spring.datasource.username=sa 4 | spring.datasource.password= 5 | spring.jpa.database-platform=org.hibernate.dialect.H2Dialect -------------------------------------------------------------------------------- /security/src/test/java/com/howtodoinjava/AppTest.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava; 2 | 3 | import org.junit.jupiter.api.Assertions; 4 | import org.junit.jupiter.api.Test; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | 7 | @SpringBootTest 8 | public class AppTest { 9 | 10 | @Test 11 | public void contextLoads() { 12 | Assertions.assertTrue(true); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /soap-client-example/pom.xml: -------------------------------------------------------------------------------- 1 | 4 | 4.0.0 5 | 6 | com.howtodoinjava 7 | Spring-Boot3-Demos 8 | 1.0-SNAPSHOT 9 | 10 | 11 | soap-client-example 12 | jar 13 | 14 | soap-client-example 15 | http://maven.apache.org 16 | 17 | 18 | UTF-8 19 | 20 | 21 | 22 | 23 | org.springframework.boot 24 | spring-boot-starter-web-services 25 | 26 | 27 | wsdl4j 28 | wsdl4j 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | org.jvnet.jaxb2.maven2 37 | maven-jaxb2-plugin 38 | 0.15.3 39 | 40 | 41 | 42 | generate 43 | 44 | 45 | 46 | 47 | com.example.howtodoinjava.schemas.school 48 | ${project.basedir}/src/main/java 49 | ${project.basedir}/src/main/resources/wsdl 50 | 51 | *.wsdl 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /soap-client-example/src/main/java/META-INF/sun-jaxb.episode: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /soap-client-example/src/main/java/com/example/howtodoinjava/schemas/school/ObjectFactory.java: -------------------------------------------------------------------------------- 1 | // 2 | // This file was generated by the Eclipse Implementation of JAXB, v2.3.7 3 | // See https://eclipse-ee4j.github.io/jaxb-ri 4 | // Any modifications to this file will be lost upon recompilation of the source schema. 5 | // Generated on: 2024.05.29 at 03:20:02 PM IST 6 | // 7 | 8 | 9 | package com.example.howtodoinjava.schemas.school; 10 | 11 | import jakarta.xml.bind.annotation.XmlRegistry; 12 | 13 | 14 | /** 15 | * This object contains factory methods for each 16 | * Java content interface and Java element interface 17 | * generated in the com.example.howtodoinjava.schemas.school package. 18 | *

An ObjectFactory allows you to programatically 19 | * construct new instances of the Java representation 20 | * for XML content. The Java representation of XML 21 | * content can consist of schema derived interfaces 22 | * and classes representing the binding of schema 23 | * type definitions, element declarations and model 24 | * groups. Factory methods for each of these are 25 | * provided in this class. 26 | * 27 | */ 28 | @XmlRegistry 29 | public class ObjectFactory { 30 | 31 | 32 | /** 33 | * Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: com.example.howtodoinjava.schemas.school 34 | * 35 | */ 36 | public ObjectFactory() { 37 | } 38 | 39 | /** 40 | * Create an instance of {@link StudentDetailsRequest } 41 | * 42 | */ 43 | public StudentDetailsRequest createStudentDetailsRequest() { 44 | return new StudentDetailsRequest(); 45 | } 46 | 47 | /** 48 | * Create an instance of {@link StudentDetailsResponse } 49 | * 50 | */ 51 | public StudentDetailsResponse createStudentDetailsResponse() { 52 | return new StudentDetailsResponse(); 53 | } 54 | 55 | /** 56 | * Create an instance of {@link Student } 57 | * 58 | */ 59 | public Student createStudent() { 60 | return new Student(); 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /soap-client-example/src/main/java/com/example/howtodoinjava/schemas/school/StudentDetailsRequest.java: -------------------------------------------------------------------------------- 1 | // 2 | // This file was generated by the Eclipse Implementation of JAXB, v2.3.7 3 | // See https://eclipse-ee4j.github.io/jaxb-ri 4 | // Any modifications to this file will be lost upon recompilation of the source schema. 5 | // Generated on: 2024.05.29 at 03:20:02 PM IST 6 | // 7 | 8 | 9 | package com.example.howtodoinjava.schemas.school; 10 | 11 | import jakarta.xml.bind.annotation.XmlAccessType; 12 | import jakarta.xml.bind.annotation.XmlAccessorType; 13 | import jakarta.xml.bind.annotation.XmlElement; 14 | import jakarta.xml.bind.annotation.XmlRootElement; 15 | import jakarta.xml.bind.annotation.XmlType; 16 | 17 | 18 | /** 19 | *

Java class for anonymous complex type. 20 | * 21 | *

The following schema fragment specifies the expected content contained within this class. 22 | * 23 | *

24 |  * <complexType>
25 |  *   <complexContent>
26 |  *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
27 |  *       <sequence>
28 |  *         <element name="name" type="{http://www.w3.org/2001/XMLSchema}string"/>
29 |  *       </sequence>
30 |  *     </restriction>
31 |  *   </complexContent>
32 |  * </complexType>
33 |  * 
34 | * 35 | * 36 | */ 37 | @XmlAccessorType(XmlAccessType.FIELD) 38 | @XmlType(name = "", propOrder = { 39 | "name" 40 | }) 41 | @XmlRootElement(name = "StudentDetailsRequest") 42 | public class StudentDetailsRequest { 43 | 44 | @XmlElement(required = true) 45 | protected String name; 46 | 47 | /** 48 | * Gets the value of the name property. 49 | * 50 | * @return 51 | * possible object is 52 | * {@link String } 53 | * 54 | */ 55 | public String getName() { 56 | return name; 57 | } 58 | 59 | /** 60 | * Sets the value of the name property. 61 | * 62 | * @param value 63 | * allowed object is 64 | * {@link String } 65 | * 66 | */ 67 | public void setName(String value) { 68 | this.name = value; 69 | } 70 | 71 | } 72 | -------------------------------------------------------------------------------- /soap-client-example/src/main/java/com/example/howtodoinjava/schemas/school/StudentDetailsResponse.java: -------------------------------------------------------------------------------- 1 | // 2 | // This file was generated by the Eclipse Implementation of JAXB, v2.3.7 3 | // See https://eclipse-ee4j.github.io/jaxb-ri 4 | // Any modifications to this file will be lost upon recompilation of the source schema. 5 | // Generated on: 2024.05.29 at 03:20:02 PM IST 6 | // 7 | 8 | 9 | package com.example.howtodoinjava.schemas.school; 10 | 11 | import jakarta.xml.bind.annotation.XmlAccessType; 12 | import jakarta.xml.bind.annotation.XmlAccessorType; 13 | import jakarta.xml.bind.annotation.XmlElement; 14 | import jakarta.xml.bind.annotation.XmlRootElement; 15 | import jakarta.xml.bind.annotation.XmlType; 16 | 17 | 18 | /** 19 | *

Java class for anonymous complex type. 20 | * 21 | *

The following schema fragment specifies the expected content contained within this class. 22 | * 23 | *

24 |  * <complexType>
25 |  *   <complexContent>
26 |  *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
27 |  *       <sequence>
28 |  *         <element name="Student" type="{http://www.howtodoinjava.com/xml/school}Student"/>
29 |  *       </sequence>
30 |  *     </restriction>
31 |  *   </complexContent>
32 |  * </complexType>
33 |  * 
34 | * 35 | * 36 | */ 37 | @XmlAccessorType(XmlAccessType.FIELD) 38 | @XmlType(name = "", propOrder = { 39 | "student" 40 | }) 41 | @XmlRootElement(name = "StudentDetailsResponse") 42 | public class StudentDetailsResponse { 43 | 44 | @XmlElement(name = "Student", required = true) 45 | protected Student student; 46 | 47 | /** 48 | * Gets the value of the student property. 49 | * 50 | * @return 51 | * possible object is 52 | * {@link Student } 53 | * 54 | */ 55 | public Student getStudent() { 56 | return student; 57 | } 58 | 59 | /** 60 | * Sets the value of the student property. 61 | * 62 | * @param value 63 | * allowed object is 64 | * {@link Student } 65 | * 66 | */ 67 | public void setStudent(Student value) { 68 | this.student = value; 69 | } 70 | 71 | } 72 | -------------------------------------------------------------------------------- /soap-client-example/src/main/java/com/example/howtodoinjava/schemas/school/package-info.java: -------------------------------------------------------------------------------- 1 | // 2 | // This file was generated by the Eclipse Implementation of JAXB, v2.3.7 3 | // See https://eclipse-ee4j.github.io/jaxb-ri 4 | // Any modifications to this file will be lost upon recompilation of the source schema. 5 | // Generated on: 2024.05.29 at 03:20:02 PM IST 6 | // 7 | 8 | @jakarta.xml.bind.annotation.XmlSchema(namespace = "http://www.howtodoinjava.com/xml/school", elementFormDefault = jakarta.xml.bind.annotation.XmlNsForm.QUALIFIED) 9 | package com.example.howtodoinjava.schemas.school; 10 | -------------------------------------------------------------------------------- /soap-client-example/src/main/java/com/howtodoinjava/App.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava; 2 | 3 | import com.howtodoinjava.soap.client.SOAPConnector; 4 | import org.springframework.boot.CommandLineRunner; 5 | import org.springframework.boot.SpringApplication; 6 | import org.springframework.boot.autoconfigure.SpringBootApplication; 7 | import org.springframework.context.annotation.Bean; 8 | import com.example.howtodoinjava.schemas.school.StudentDetailsRequest; 9 | import com.example.howtodoinjava.schemas.school.StudentDetailsResponse; 10 | 11 | @SpringBootApplication 12 | public class App { 13 | 14 | public static void main(String[] args) { 15 | SpringApplication.run(App.class, args); 16 | } 17 | 18 | @Bean 19 | CommandLineRunner lookup(SOAPConnector soapConnector) { 20 | return args -> { 21 | String name = "Lokesh"; //Default Name 22 | if (args.length > 0) { 23 | name = args[0]; 24 | } 25 | StudentDetailsRequest request = new StudentDetailsRequest(); 26 | request.setName(name); 27 | StudentDetailsResponse response = (StudentDetailsResponse) soapConnector.callWebService("http://localhost:8080/service/student-details", request); 28 | System.out.println("Got Response As below ========= : "); 29 | System.out.println("Name : " + response.getStudent().getName()); 30 | System.out.println("Standard : " + response.getStudent().getStandard()); 31 | System.out.println("Address : " + response.getStudent().getAddress()); 32 | }; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /soap-client-example/src/main/java/com/howtodoinjava/soap/client/Config.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.soap.client; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.oxm.jaxb.Jaxb2Marshaller; 6 | 7 | @Configuration 8 | public class Config { 9 | @Bean 10 | public Jaxb2Marshaller marshaller() { 11 | Jaxb2Marshaller marshaller = new Jaxb2Marshaller(); 12 | // this is the package name specified in the specified in 13 | // pom.xml 14 | marshaller.setContextPath("com.example.howtodoinjava.schemas.school"); 15 | return marshaller; 16 | } 17 | 18 | @Bean 19 | public SOAPConnector soapConnector(Jaxb2Marshaller marshaller) { 20 | SOAPConnector client = new SOAPConnector(); 21 | client.setDefaultUri("http://localhost:8080/service/student-details"); 22 | client.setMarshaller(marshaller); 23 | client.setUnmarshaller(marshaller); 24 | return client; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /soap-client-example/src/main/java/com/howtodoinjava/soap/client/SOAPConnector.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.soap.client; 2 | 3 | import org.springframework.ws.client.core.support.WebServiceGatewaySupport; 4 | 5 | public class SOAPConnector extends WebServiceGatewaySupport { 6 | 7 | public Object callWebService(String url, Object request){ 8 | return getWebServiceTemplate().marshalSendAndReceive(url, request); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /soap-client-example/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | server.port = 9090 2 | logging.level.org.springframework.ws=TRACE 3 | -------------------------------------------------------------------------------- /soap-ws-example/pom.xml: -------------------------------------------------------------------------------- 1 | 4 | 4.0.0 5 | 6 | com.howtodoinjava 7 | Spring-Boot3-Demos 8 | 1.0-SNAPSHOT 9 | 10 | 11 | soap-ws-example 12 | jar 13 | 14 | soap-ws-example 15 | http://maven.apache.org 16 | 17 | 18 | UTF-8 19 | 20 | 21 | 22 | 23 | org.springframework.boot 24 | spring-boot-starter-web-services 25 | 26 | 27 | wsdl4j 28 | wsdl4j 29 | 30 | 31 | 32 | 33 | 34 | 35 | org.codehaus.mojo 36 | jaxb2-maven-plugin 37 | 3.1.0 38 | 39 | 40 | xjc 41 | 42 | xjc 43 | 44 | 45 | 46 | 47 | 48 | src/main/resources/student.xsd 49 | 50 | src/main/java 51 | false 52 | 53 | 54 | 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /soap-ws-example/src/main/java/META-INF/JAXB/episode_xjc.xjb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /soap-ws-example/src/main/java/com/howtodoinjava/App.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class App { 8 | public static void main(String[] args) { 9 | SpringApplication.run(App.class); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /soap-ws-example/src/main/java/com/howtodoinjava/config/SoapConfig.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.config; 2 | 3 | import org.springframework.boot.web.servlet.ServletRegistrationBean; 4 | import org.springframework.context.ApplicationContext; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.context.annotation.Configuration; 7 | import org.springframework.core.io.ClassPathResource; 8 | import org.springframework.ws.config.annotation.EnableWs; 9 | import org.springframework.ws.config.annotation.WsConfigurerAdapter; 10 | import org.springframework.ws.transport.http.MessageDispatcherServlet; 11 | import org.springframework.ws.wsdl.wsdl11.DefaultWsdl11Definition; 12 | import org.springframework.xml.xsd.SimpleXsdSchema; 13 | import org.springframework.xml.xsd.XsdSchema; 14 | 15 | @EnableWs 16 | @Configuration 17 | public class SoapConfig extends WsConfigurerAdapter { 18 | 19 | @Bean 20 | public ServletRegistrationBean messageDispatcherServlet(ApplicationContext applicationContext) { 21 | MessageDispatcherServlet servlet = new MessageDispatcherServlet(); 22 | servlet.setApplicationContext(applicationContext); 23 | servlet.setTransformWsdlLocations(true); 24 | return new ServletRegistrationBean(servlet, "/service/*"); 25 | } 26 | 27 | @Bean(name = "studentDetailsWsdl") 28 | public DefaultWsdl11Definition defaultWsdl11Definition(XsdSchema studentSchema) { 29 | DefaultWsdl11Definition wsdl11Definition = new DefaultWsdl11Definition(); 30 | wsdl11Definition.setPortTypeName("StudentDetailsPort"); 31 | wsdl11Definition.setLocationUri("/service/student-details"); 32 | wsdl11Definition.setTargetNamespace("http://www.howtodoinjava.com/xml/school"); 33 | wsdl11Definition.setSchema(studentSchema); 34 | return wsdl11Definition; 35 | } 36 | 37 | @Bean 38 | public XsdSchema studentSchema() { 39 | return new SimpleXsdSchema(new ClassPathResource("student.xsd")); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /soap-ws-example/src/main/java/com/howtodoinjava/endpoints/StudentEndpoint.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.endpoints; 2 | 3 | import com.howtodoinjava.repository.StudentRepository; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.ws.server.endpoint.annotation.Endpoint; 6 | import org.springframework.ws.server.endpoint.annotation.PayloadRoot; 7 | import org.springframework.ws.server.endpoint.annotation.RequestPayload; 8 | import org.springframework.ws.server.endpoint.annotation.ResponsePayload; 9 | import com.howtodoinjava.xml.school.StudentDetailsRequest; 10 | import com.howtodoinjava.xml.school.StudentDetailsResponse; 11 | 12 | @Endpoint 13 | public class StudentEndpoint 14 | { 15 | private static final String NAMESPACE_URI = "http://www.howtodoinjava.com/xml/school"; 16 | 17 | private StudentRepository StudentRepository; 18 | 19 | @Autowired 20 | public StudentEndpoint(StudentRepository StudentRepository) { 21 | this.StudentRepository = StudentRepository; 22 | } 23 | 24 | @PayloadRoot(namespace = NAMESPACE_URI, localPart = "StudentDetailsRequest") 25 | @ResponsePayload 26 | public StudentDetailsResponse getStudent(@RequestPayload StudentDetailsRequest request) { 27 | StudentDetailsResponse response = new StudentDetailsResponse(); 28 | response.setStudent(StudentRepository.findStudent(request.getName())); 29 | 30 | return response; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /soap-ws-example/src/main/java/com/howtodoinjava/repository/StudentRepository.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.repository; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | import jakarta.annotation.PostConstruct; 6 | import org.springframework.stereotype.Component; 7 | import org.springframework.util.Assert; 8 | import com.howtodoinjava.xml.school.Student; 9 | 10 | @Component 11 | public class StudentRepository { 12 | private static final Map students = new HashMap<>(); 13 | 14 | @PostConstruct 15 | public void initData() { 16 | 17 | Student student = new Student(); 18 | student.setName("Sajal"); 19 | student.setStandard(5); 20 | student.setAddress("Pune"); 21 | students.put(student.getName(), student); 22 | 23 | student = new Student(); 24 | student.setName("Kajal"); 25 | student.setStandard(5); 26 | student.setAddress("Chicago"); 27 | students.put(student.getName(), student); 28 | 29 | student = new Student(); 30 | student.setName("Lokesh"); 31 | student.setStandard(6); 32 | student.setAddress("Delhi"); 33 | students.put(student.getName(), student); 34 | 35 | student = new Student(); 36 | student.setName("Sukesh"); 37 | student.setStandard(7); 38 | student.setAddress("Noida"); 39 | students.put(student.getName(), student); 40 | } 41 | 42 | public Student findStudent(String name) { 43 | Assert.notNull(name, "The Student's name must not be null"); 44 | return students.get(name); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /soap-ws-example/src/main/java/com/howtodoinjava/xml/school/ObjectFactory.java: -------------------------------------------------------------------------------- 1 | // 2 | // This file was generated by the Eclipse Implementation of JAXB, v3.0.0 3 | // See https://eclipse-ee4j.github.io/jaxb-ri 4 | // Any modifications to this file will be lost upon recompilation of the source schema. 5 | // Generated on: 2024.05.29 at 01:06:41 PM IST 6 | // 7 | 8 | 9 | package com.howtodoinjava.xml.school; 10 | 11 | import jakarta.xml.bind.annotation.XmlRegistry; 12 | 13 | 14 | /** 15 | * This object contains factory methods for each 16 | * Java content interface and Java element interface 17 | * generated in the com.howtodoinjava.xml.school package. 18 | *

An ObjectFactory allows you to programatically 19 | * construct new instances of the Java representation 20 | * for XML content. The Java representation of XML 21 | * content can consist of schema derived interfaces 22 | * and classes representing the binding of schema 23 | * type definitions, element declarations and model 24 | * groups. Factory methods for each of these are 25 | * provided in this class. 26 | * 27 | */ 28 | @XmlRegistry 29 | public class ObjectFactory { 30 | 31 | 32 | /** 33 | * Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: com.howtodoinjava.xml.school 34 | * 35 | */ 36 | public ObjectFactory() { 37 | } 38 | 39 | /** 40 | * Create an instance of {@link StudentDetailsRequest } 41 | * 42 | */ 43 | public StudentDetailsRequest createStudentDetailsRequest() { 44 | return new StudentDetailsRequest(); 45 | } 46 | 47 | /** 48 | * Create an instance of {@link StudentDetailsResponse } 49 | * 50 | */ 51 | public StudentDetailsResponse createStudentDetailsResponse() { 52 | return new StudentDetailsResponse(); 53 | } 54 | 55 | /** 56 | * Create an instance of {@link Student } 57 | * 58 | */ 59 | public Student createStudent() { 60 | return new Student(); 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /soap-ws-example/src/main/java/com/howtodoinjava/xml/school/StudentDetailsRequest.java: -------------------------------------------------------------------------------- 1 | // 2 | // This file was generated by the Eclipse Implementation of JAXB, v3.0.0 3 | // See https://eclipse-ee4j.github.io/jaxb-ri 4 | // Any modifications to this file will be lost upon recompilation of the source schema. 5 | // Generated on: 2024.05.29 at 01:06:41 PM IST 6 | // 7 | 8 | 9 | package com.howtodoinjava.xml.school; 10 | 11 | import jakarta.xml.bind.annotation.XmlAccessType; 12 | import jakarta.xml.bind.annotation.XmlAccessorType; 13 | import jakarta.xml.bind.annotation.XmlElement; 14 | import jakarta.xml.bind.annotation.XmlRootElement; 15 | import jakarta.xml.bind.annotation.XmlType; 16 | 17 | 18 | /** 19 | *

Java class for anonymous complex type. 20 | * 21 | *

The following schema fragment specifies the expected content contained within this class. 22 | * 23 | *

24 |  * <complexType>
25 |  *   <complexContent>
26 |  *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
27 |  *       <sequence>
28 |  *         <element name="name" type="{http://www.w3.org/2001/XMLSchema}string"/>
29 |  *       </sequence>
30 |  *     </restriction>
31 |  *   </complexContent>
32 |  * </complexType>
33 |  * 
34 | * 35 | * 36 | */ 37 | @XmlAccessorType(XmlAccessType.FIELD) 38 | @XmlType(name = "", propOrder = { 39 | "name" 40 | }) 41 | @XmlRootElement(name = "StudentDetailsRequest") 42 | public class StudentDetailsRequest { 43 | 44 | @XmlElement(required = true) 45 | protected String name; 46 | 47 | /** 48 | * Gets the value of the name property. 49 | * 50 | * @return 51 | * possible object is 52 | * {@link String } 53 | * 54 | */ 55 | public String getName() { 56 | return name; 57 | } 58 | 59 | /** 60 | * Sets the value of the name property. 61 | * 62 | * @param value 63 | * allowed object is 64 | * {@link String } 65 | * 66 | */ 67 | public void setName(String value) { 68 | this.name = value; 69 | } 70 | 71 | } 72 | -------------------------------------------------------------------------------- /soap-ws-example/src/main/java/com/howtodoinjava/xml/school/StudentDetailsResponse.java: -------------------------------------------------------------------------------- 1 | // 2 | // This file was generated by the Eclipse Implementation of JAXB, v3.0.0 3 | // See https://eclipse-ee4j.github.io/jaxb-ri 4 | // Any modifications to this file will be lost upon recompilation of the source schema. 5 | // Generated on: 2024.05.29 at 01:06:41 PM IST 6 | // 7 | 8 | 9 | package com.howtodoinjava.xml.school; 10 | 11 | import jakarta.xml.bind.annotation.XmlAccessType; 12 | import jakarta.xml.bind.annotation.XmlAccessorType; 13 | import jakarta.xml.bind.annotation.XmlElement; 14 | import jakarta.xml.bind.annotation.XmlRootElement; 15 | import jakarta.xml.bind.annotation.XmlType; 16 | 17 | 18 | /** 19 | *

Java class for anonymous complex type. 20 | * 21 | *

The following schema fragment specifies the expected content contained within this class. 22 | * 23 | *

24 |  * <complexType>
25 |  *   <complexContent>
26 |  *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
27 |  *       <sequence>
28 |  *         <element name="Student" type="{http://www.howtodoinjava.com/xml/school}Student"/>
29 |  *       </sequence>
30 |  *     </restriction>
31 |  *   </complexContent>
32 |  * </complexType>
33 |  * 
34 | * 35 | * 36 | */ 37 | @XmlAccessorType(XmlAccessType.FIELD) 38 | @XmlType(name = "", propOrder = { 39 | "student" 40 | }) 41 | @XmlRootElement(name = "StudentDetailsResponse") 42 | public class StudentDetailsResponse { 43 | 44 | @XmlElement(name = "Student", required = true) 45 | protected Student student; 46 | 47 | /** 48 | * Gets the value of the student property. 49 | * 50 | * @return 51 | * possible object is 52 | * {@link Student } 53 | * 54 | */ 55 | public Student getStudent() { 56 | return student; 57 | } 58 | 59 | /** 60 | * Sets the value of the student property. 61 | * 62 | * @param value 63 | * allowed object is 64 | * {@link Student } 65 | * 66 | */ 67 | public void setStudent(Student value) { 68 | this.student = value; 69 | } 70 | 71 | } 72 | -------------------------------------------------------------------------------- /soap-ws-example/src/main/java/com/howtodoinjava/xml/school/package-info.java: -------------------------------------------------------------------------------- 1 | // 2 | // This file was generated by the Eclipse Implementation of JAXB, v3.0.0 3 | // See https://eclipse-ee4j.github.io/jaxb-ri 4 | // Any modifications to this file will be lost upon recompilation of the source schema. 5 | // Generated on: 2024.05.29 at 01:06:41 PM IST 6 | // 7 | 8 | @jakarta.xml.bind.annotation.XmlSchema(namespace = "http://www.howtodoinjava.com/xml/school", elementFormDefault = jakarta.xml.bind.annotation.XmlNsForm.QUALIFIED) 9 | package com.howtodoinjava.xml.school; 10 | -------------------------------------------------------------------------------- /soap-ws-example/src/main/resources/student.xsd: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /spring-boot-hateoas/pom.xml: -------------------------------------------------------------------------------- 1 | 4 | 4.0.0 5 | 6 | com.howtodoinjava 7 | Spring-Boot3-Demos 8 | 1.0-SNAPSHOT 9 | 10 | 11 | spring-boot-hateoas 12 | jar 13 | spring-boot-hateoas 14 | https://howtodoinjava.com 15 | 16 | 17 | 18 | org.springframework.boot 19 | spring-boot-starter-web 20 | 21 | 22 | org.springframework.boot 23 | spring-boot-starter-data-jpa 24 | 25 | 26 | org.springframework.boot 27 | spring-boot-starter-hateoas 28 | 29 | 30 | com.h2database 31 | h2 32 | runtime 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /spring-boot-hateoas/src/main/java/com/howtodoinjava/App.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.web.filter.ForwardedHeaderFilter; 7 | 8 | @SpringBootApplication 9 | //@EnableAutoConfiguration(exclude = HypermediaAutoConfiguration.class) 10 | public class App { 11 | 12 | public static void main(String[] args) { 13 | SpringApplication.run(App.class, args); 14 | } 15 | 16 | @Bean 17 | ForwardedHeaderFilter forwardedHeaderFilter() { 18 | return new ForwardedHeaderFilter(); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /spring-boot-hateoas/src/main/java/com/howtodoinjava/rest/entity/ActorEntity.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.rest.entity; 2 | 3 | import java.io.Serializable; 4 | import java.util.List; 5 | 6 | import jakarta.persistence.CascadeType; 7 | import jakarta.persistence.Entity; 8 | import jakarta.persistence.GeneratedValue; 9 | import jakarta.persistence.GenerationType; 10 | import jakarta.persistence.Id; 11 | import jakarta.persistence.JoinColumn; 12 | import jakarta.persistence.JoinTable; 13 | import jakarta.persistence.ManyToMany; 14 | import jakarta.persistence.Table; 15 | 16 | import lombok.AllArgsConstructor; 17 | import lombok.Builder; 18 | import lombok.Data; 19 | import lombok.NoArgsConstructor; 20 | import lombok.ToString; 21 | 22 | @Data 23 | @Builder 24 | @AllArgsConstructor 25 | @NoArgsConstructor 26 | @ToString(exclude = "albums") 27 | @Entity 28 | @Table(name="actor") 29 | public class ActorEntity implements Serializable 30 | { 31 | private static final long serialVersionUID = 1L; 32 | 33 | @Id 34 | @GeneratedValue(strategy = GenerationType.IDENTITY) 35 | private Long id; 36 | private String firstName; 37 | private String lastName; 38 | private String birthDate; 39 | 40 | @ManyToMany(cascade=CascadeType.ALL) 41 | @JoinTable( 42 | name = "actor_album", 43 | joinColumns = @JoinColumn(name = "actor_id"), 44 | inverseJoinColumns = @JoinColumn(name = "album_id")) 45 | private List albums; 46 | } 47 | -------------------------------------------------------------------------------- /spring-boot-hateoas/src/main/java/com/howtodoinjava/rest/entity/AlbumEntity.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.rest.entity; 2 | 3 | import java.io.Serializable; 4 | import java.util.List; 5 | 6 | import jakarta.persistence.Entity; 7 | import jakarta.persistence.FetchType; 8 | import jakarta.persistence.GeneratedValue; 9 | import jakarta.persistence.GenerationType; 10 | import jakarta.persistence.Id; 11 | import jakarta.persistence.ManyToMany; 12 | import jakarta.persistence.Table; 13 | 14 | import lombok.AllArgsConstructor; 15 | import lombok.Builder; 16 | import lombok.Data; 17 | import lombok.NoArgsConstructor; 18 | import lombok.ToString; 19 | 20 | @Data 21 | @Builder 22 | @AllArgsConstructor 23 | @NoArgsConstructor 24 | @Entity 25 | @ToString(exclude = "actors") 26 | @Table(name="album") 27 | public class AlbumEntity implements Serializable 28 | { 29 | private static final long serialVersionUID = 1L; 30 | 31 | @Id 32 | @GeneratedValue(strategy = GenerationType.IDENTITY) 33 | private Long id; 34 | private String title; 35 | private String description; 36 | private String releaseDate; 37 | 38 | @ManyToMany(mappedBy = "albums",fetch = FetchType.EAGER) 39 | private List actors; 40 | } 41 | -------------------------------------------------------------------------------- /spring-boot-hateoas/src/main/java/com/howtodoinjava/rest/model/ActorModel.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.rest.model; 2 | 3 | import java.util.List; 4 | 5 | import org.springframework.hateoas.RepresentationModel; 6 | import org.springframework.hateoas.server.core.Relation; 7 | 8 | import com.fasterxml.jackson.annotation.JsonInclude; 9 | import com.fasterxml.jackson.annotation.JsonInclude.Include; 10 | 11 | import lombok.AllArgsConstructor; 12 | import lombok.Builder; 13 | import lombok.Data; 14 | import lombok.EqualsAndHashCode; 15 | import lombok.NoArgsConstructor; 16 | 17 | @Data 18 | @Builder 19 | @NoArgsConstructor 20 | @AllArgsConstructor 21 | @EqualsAndHashCode(callSuper = false) 22 | @Relation(collectionRelation = "actors", itemRelation = "actor") 23 | @JsonInclude(Include.NON_NULL) 24 | public class ActorModel extends RepresentationModel 25 | { 26 | private Long id; 27 | private String firstName; 28 | private String lastName; 29 | private String birthDate; 30 | 31 | private List albums; 32 | } 33 | -------------------------------------------------------------------------------- /spring-boot-hateoas/src/main/java/com/howtodoinjava/rest/model/AlbumModel.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.rest.model; 2 | 3 | import java.util.List; 4 | 5 | import org.springframework.hateoas.RepresentationModel; 6 | import org.springframework.hateoas.server.core.Relation; 7 | 8 | import com.fasterxml.jackson.annotation.JsonInclude; 9 | import com.fasterxml.jackson.annotation.JsonInclude.Include; 10 | 11 | import lombok.AllArgsConstructor; 12 | import lombok.Builder; 13 | import lombok.Data; 14 | import lombok.EqualsAndHashCode; 15 | import lombok.NoArgsConstructor; 16 | 17 | @Data 18 | @Builder 19 | @NoArgsConstructor 20 | @AllArgsConstructor 21 | @EqualsAndHashCode(callSuper = false) 22 | @Relation(collectionRelation = "albums", itemRelation = "album") 23 | @JsonInclude(Include.NON_NULL) 24 | public class AlbumModel extends RepresentationModel 25 | { 26 | private Long id; 27 | private String title; 28 | private String description; 29 | private String releaseDate; 30 | 31 | private List actors; 32 | } 33 | -------------------------------------------------------------------------------- /spring-boot-hateoas/src/main/java/com/howtodoinjava/rest/repository/ActorRepository.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.rest.repository; 2 | 3 | import com.howtodoinjava.rest.entity.ActorEntity; 4 | import org.springframework.data.repository.ListCrudRepository; 5 | import org.springframework.data.repository.ListPagingAndSortingRepository; 6 | 7 | public interface ActorRepository extends ListCrudRepository, 8 | ListPagingAndSortingRepository { 9 | 10 | } 11 | -------------------------------------------------------------------------------- /spring-boot-hateoas/src/main/java/com/howtodoinjava/rest/repository/AlbumRepository.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.rest.repository; 2 | 3 | import com.howtodoinjava.rest.entity.AlbumEntity; 4 | import org.springframework.data.repository.ListCrudRepository; 5 | import org.springframework.data.repository.ListPagingAndSortingRepository; 6 | 7 | public interface AlbumRepository extends ListCrudRepository, 8 | ListPagingAndSortingRepository { 9 | 10 | } -------------------------------------------------------------------------------- /spring-boot-hateoas/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.datasource.url=jdbc:h2:mem:test 2 | spring.datasource.driverClassName=org.h2.Driver 3 | spring.datasource.username=sa 4 | spring.datasource.password= 5 | spring.jpa.database-platform=org.hibernate.dialect.H2Dialect 6 | 7 | spring.jpa.hibernate.ddl-auto=none 8 | 9 | #spring.hateoas.use-hal-as-default-json-media-type=false -------------------------------------------------------------------------------- /spring-boot-hateoas/src/main/resources/data.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO actor VALUES ('1', 'John', 'Doe', '10-Jan-1952'); 2 | INSERT INTO actor VALUES ('2', 'Amy', 'Eugene', '05-07-1985'); 3 | INSERT INTO actor VALUES ('3', 'Laverne', 'Mann', '11-12-1988'); 4 | INSERT INTO actor VALUES ('4', 'Janice', 'Preston', '19-02-1960'); 5 | INSERT INTO actor VALUES ('5', 'Pauline', 'Rios', '29-08-1977'); 6 | 7 | INSERT INTO album VALUES ('1', 'Top Hits Vol 1', 'Top hits vol 1. description', '10-03-1981'); 8 | INSERT INTO album VALUES ('2', 'Top Hits Vol 2', 'Top hits vol 2. description', '10-03-1982'); 9 | INSERT INTO album VALUES ('3', 'Top Hits Vol 3', 'Top hits vol 3. description', '10-03-1983'); 10 | INSERT INTO album VALUES ('4', 'Top Hits Vol 4', 'Top hits vol 4. description', '10-03-1984'); 11 | INSERT INTO album VALUES ('5', 'Top Hits Vol 5', 'Top hits vol 5. description', '10-03-1985'); 12 | INSERT INTO album VALUES ('6', 'Top Hits Vol 6', 'Top hits vol 6. description', '10-03-1986'); 13 | INSERT INTO album VALUES ('7', 'Top Hits Vol 7', 'Top hits vol 7. description', '10-03-1987'); 14 | INSERT INTO album VALUES ('8', 'Top Hits Vol 8', 'Top hits vol 8. description', '10-03-1988'); 15 | INSERT INTO album VALUES ('9', 'Top Hits Vol 9', 'Top hits vol 9. description', '10-03-1989'); 16 | INSERT INTO album VALUES ('10', 'Top Hits Vol 10', 'Top hits vol 10. description', '10-03-1990'); 17 | 18 | INSERT INTO actor_album VALUES (1, 1); 19 | INSERT INTO actor_album VALUES (1, 2); 20 | INSERT INTO actor_album VALUES (2, 3); 21 | INSERT INTO actor_album VALUES (2, 4); 22 | INSERT INTO actor_album VALUES (3, 5); 23 | INSERT INTO actor_album VALUES (3, 6); 24 | INSERT INTO actor_album VALUES (4, 7); 25 | INSERT INTO actor_album VALUES (4, 8); 26 | INSERT INTO actor_album VALUES (5, 9); 27 | INSERT INTO actor_album VALUES (5, 10); -------------------------------------------------------------------------------- /spring-boot-hateoas/src/main/resources/schema.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE actor ( 2 | id INT PRIMARY KEY, 3 | first_name VARCHAR(255) NULL, 4 | last_name VARCHAR(255) NULL, 5 | birth_date VARCHAR(255) NULL 6 | ); 7 | 8 | CREATE TABLE album ( 9 | id INT PRIMARY KEY, 10 | title VARCHAR(255) NULL, 11 | description VARCHAR(255) NULL, 12 | release_date VARCHAR(255) NULL 13 | ); 14 | 15 | CREATE TABLE actor_album ( 16 | actor_id INT, 17 | album_id INT 18 | ); -------------------------------------------------------------------------------- /spring-boot-hateoas/src/test/java/com/howtodoinjava/AppTest.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertTrue; 4 | import org.junit.jupiter.api.Test; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | 7 | @SpringBootTest 8 | public class AppTest { 9 | 10 | @Test 11 | public void contextLoads() { 12 | assertTrue(true); 13 | } 14 | } -------------------------------------------------------------------------------- /spring-restclient/README.md: -------------------------------------------------------------------------------- 1 | # Related Tutorials 2 | 3 | * [Spring RestClient](https://howtodoinjava.com/spring/spring-restclient/) 4 | * [Fake REST APIs for Unit Testing](https://howtodoinjava.com/angular/mock-rest-server/) 5 | -------------------------------------------------------------------------------- /spring-restclient/db.json: -------------------------------------------------------------------------------- 1 | { 2 | "employees": [ 3 | { 4 | "id": 1, 5 | "name": "Lokesh", 6 | "status": "Active" 7 | }, 8 | { 9 | "id": 2, 10 | "name": "Andy", 11 | "status": "Inactive" 12 | }, 13 | { 14 | "id": 3, 15 | "name": "Brian", 16 | "status": "Active" 17 | }, 18 | { 19 | "id": 4, 20 | "name": "Charles", 21 | "status": "Inactive" 22 | } 23 | ] 24 | } -------------------------------------------------------------------------------- /spring-restclient/pom.xml: -------------------------------------------------------------------------------- 1 | 4 | 4.0.0 5 | 6 | 7 | org.springframework.boot 8 | spring-boot-starter-parent 9 | 3.2.0-M3 10 | 11 | 12 | 13 | com.howtodoinjava.app 14 | spring-restclient 15 | jar 16 | spring-restclient 17 | https://howtodoinjava.com 18 | 19 | 20 | UTF-8 21 | 21 22 | 23 | 24 | 25 | 26 | org.projectlombok 27 | lombok 28 | true 29 | 1.18.30 30 | 31 | 32 | org.springframework.boot 33 | spring-boot-starter-web 34 | 35 | 36 | org.springframework.boot 37 | spring-boot-starter-webflux 38 | 39 | 40 | org.springframework.boot 41 | spring-boot-starter-test 42 | 43 | 44 | org.apache.httpcomponents.client5 45 | httpclient5 46 | 5.2.1 47 | 48 | 49 | org.apache.httpcomponents.core5 50 | httpcore5-reactive 51 | 5.2.1 52 | 53 | 54 | 55 | 56 | 57 | spring-milestone 58 | Spring Milestones 59 | https://repo.spring.io/milestone 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /spring-restclient/src/main/java/com/howtodoinjava/app/config/WebConfig.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.app.config; 2 | 3 | import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient; 4 | import org.apache.hc.client5.http.impl.async.HttpAsyncClientBuilder; 5 | import org.apache.hc.client5.http.impl.async.HttpAsyncClients; 6 | import org.springframework.context.annotation.Bean; 7 | import org.springframework.context.annotation.Configuration; 8 | import org.springframework.http.client.reactive.ClientHttpConnector; 9 | import org.springframework.http.client.reactive.HttpComponentsClientHttpConnector; 10 | import org.springframework.web.reactive.function.client.WebClient; 11 | 12 | @Configuration 13 | public class WebConfig { 14 | 15 | @Bean 16 | public WebClient webClient() { 17 | HttpAsyncClientBuilder clientBuilder = HttpAsyncClients.custom(); 18 | //clientBuilder.setDefaultRequestConfig(); 19 | CloseableHttpAsyncClient client = clientBuilder.build(); 20 | ClientHttpConnector connector = new HttpComponentsClientHttpConnector(client); 21 | return WebClient.builder().clientConnector(connector).build(); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /spring-restclient/src/main/java/com/howtodoinjava/app/exception/ApplicationException.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.app.exception; 2 | 3 | public class ApplicationException extends RuntimeException { 4 | 5 | public ApplicationException(String message) { 6 | super(message); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /spring-restclient/src/main/java/com/howtodoinjava/app/model/Employee.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.app.model; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | @Data 8 | @AllArgsConstructor 9 | @NoArgsConstructor 10 | public class Employee { 11 | 12 | private long id; 13 | private String name; 14 | private String status; 15 | } 16 | -------------------------------------------------------------------------------- /spring-restclient/src/main/java/com/howtodoinjava/app/web/EmployeeController.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.app.web; 2 | 3 | import com.howtodoinjava.app.model.Employee; 4 | import org.springframework.http.HttpStatusCode; 5 | import org.springframework.web.bind.annotation.RestController; 6 | import org.springframework.web.reactive.function.BodyInserters; 7 | import org.springframework.web.reactive.function.client.WebClient; 8 | import org.springframework.web.reactive.function.client.WebClientResponseException; 9 | 10 | import java.net.URI; 11 | 12 | @RestController 13 | public class EmployeeController { 14 | 15 | private final WebClient webClient; 16 | 17 | public EmployeeController(WebClient webClient) { 18 | this.webClient = webClient; 19 | } 20 | 21 | public void createEmployee(){ 22 | 23 | Employee newEmployee = new Employee(1L, "Lokesh Gupta", "Active"); 24 | 25 | webClient.post() 26 | .uri("/employees") 27 | .bodyValue(BodyInserters.fromValue(newEmployee)) 28 | .retrieve() 29 | .toBodilessEntity() 30 | .subscribe( 31 | responseEntity -> { 32 | // Handle success response here 33 | HttpStatusCode status = responseEntity.getStatusCode(); 34 | URI location = responseEntity.getHeaders().getLocation(); 35 | // handle response as necessary 36 | }, 37 | error -> { 38 | // Handle the error here 39 | if (error instanceof WebClientResponseException ex) { 40 | HttpStatusCode status = ex.getStatusCode(); 41 | System.out.println("Error Status Code: " + status.value()); 42 | //... 43 | } else { 44 | // Handle other types of errors 45 | System.err.println("An unexpected error occurred: " + error.getMessage()); 46 | } 47 | } 48 | ); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /structured-logging/.gitattributes: -------------------------------------------------------------------------------- 1 | /mvnw text eol=lf 2 | *.cmd text eol=crlf 3 | -------------------------------------------------------------------------------- /structured-logging/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | !**/src/main/**/build/ 30 | !**/src/test/**/build/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | -------------------------------------------------------------------------------- /structured-logging/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one 2 | # or more contributor license agreements. See the NOTICE file 3 | # distributed with this work for additional information 4 | # regarding copyright ownership. The ASF licenses this file 5 | # to you under the Apache License, Version 2.0 (the 6 | # "License"); you may not use this file except in compliance 7 | # with the License. You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, 12 | # software distributed under the License is distributed on an 13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | # KIND, either express or implied. See the License for the 15 | # specific language governing permissions and limitations 16 | # under the License. 17 | wrapperVersion=3.3.2 18 | distributionType=only-script 19 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.9/apache-maven-3.9.9-bin.zip 20 | -------------------------------------------------------------------------------- /structured-logging/src/main/java/com/howtodoinjava/demo/CustomLogFormatter.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.demo; 2 | 3 | import ch.qos.logback.classic.spi.ILoggingEvent; 4 | import org.springframework.boot.logging.structured.StructuredLogFormatter; 5 | 6 | public class CustomLogFormatter implements StructuredLogFormatter { 7 | 8 | @Override 9 | public String format(ILoggingEvent event) { 10 | 11 | // Use a StringBuilder for efficient string concatenation 12 | StringBuilder logBuilder = new StringBuilder(); 13 | 14 | // Add basic log details 15 | logBuilder.append("time=").append(event.getTimeStamp()) 16 | .append(",logger=").append(event.getLoggerName()) 17 | .append(",level=").append(event.getLevel()) 18 | .append(",message=\"").append(event.getFormattedMessage()).append("\""); 19 | 20 | // Iterate over key-value pairs and append as CSV 21 | if (event.getKeyValuePairs() != null) { 22 | event.getKeyValuePairs() 23 | .stream() 24 | .forEach((pair) -> { 25 | logBuilder.append(",").append(pair.key).append("=").append(pair.value); 26 | }); 27 | } 28 | 29 | // Iterate over MDC map and append as CSV 30 | if (event.getMDCPropertyMap() != null) { 31 | event.getMDCPropertyMap() 32 | .entrySet() 33 | .stream() 34 | .forEach((entry) -> { 35 | logBuilder.append(",").append(entry.getKey()).append("=").append(entry.getValue()); 36 | }); 37 | } 38 | 39 | // Add a newline at the end of the log 40 | logBuilder.append("\n"); 41 | 42 | return logBuilder.toString(); 43 | } 44 | } -------------------------------------------------------------------------------- /structured-logging/src/main/java/com/howtodoinjava/demo/StructuredLoggingApplication.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.demo; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | import org.slf4j.MDC; 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 StructuredLoggingApplication implements CommandLineRunner { 12 | 13 | final static Logger log = LoggerFactory.getLogger(StructuredLoggingApplication.class); 14 | 15 | public static void main(String[] args) { 16 | SpringApplication.run(StructuredLoggingApplication.class, args); 17 | } 18 | 19 | @Override 20 | public void run(String... args) throws Exception { 21 | log.trace("Trace log"); 22 | log.debug("Debug log"); 23 | 24 | log.info("Info log"); 25 | log.warn("Hey, This is a warning!"); 26 | log.error("Oops! We have an Error. OK"); 27 | 28 | /*MDC.put("MyKey1", "MyValue1"); 29 | MDC.put("MyKey2", "MyValue2");*/ 30 | 31 | /*log.atInfo() 32 | .setMessage("Info log") 33 | .addKeyValue("MyKey1", "MyValue1") 34 | .addKeyValue("MyKey2", "MyValue2") 35 | .log();*/ 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /structured-logging/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.application.name=structured-logging 2 | 3 | # ecs, gelf, logstash or Custom Log Event 4 | logging.structured.format.console=com.howtodoinjava.demo.CustomLogFormatter 5 | logging.structured.format.file=ecs 6 | logging.file.name=${java.io.tmpdir}/app.log 7 | 8 | # ecs properties 9 | 10 | logging.structured.ecs.service.name=MyService 11 | logging.structured.ecs.service.version=1 12 | logging.structured.ecs.service.environment=Production 13 | logging.structured.ecs.service.node-name=Primary 14 | 15 | # gelf properties 16 | 17 | logging.structured.gelf.host=MyService 18 | logging.structured.gelf.service.version=1 19 | 20 | # logstash properties 21 | 22 | logging.structured.json.add.host=MyService 23 | logging.structured.json.add.version=1 24 | logging.structured.json.exclude=level_value 25 | logging.structured.json.rename.logger_name=logger_class 26 | -------------------------------------------------------------------------------- /structured-logging/src/test/java/com/howtodoinjava/demo/StructuredLoggingApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.demo; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class StructuredLoggingApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /task-scheduler/README.md: -------------------------------------------------------------------------------- 1 | # Related Tutorials 2 | 3 | - [Spring Boot @Scheduled Task Execution Example](https://howtodoinjava.com/spring-boot/enable-scheduling-scheduled-job-example/) 4 | - [Spring Task Scheduling](https://howtodoinjava.com/spring-core/spring-scheduled-annotation/) -------------------------------------------------------------------------------- /task-scheduler/pom.xml: -------------------------------------------------------------------------------- 1 | 4 | 4.0.0 5 | 6 | com.howtodoinjava 7 | Spring-Boot3-Demos 8 | 1.0-SNAPSHOT 9 | 10 | 11 | task-scheduler 12 | jar 13 | task-scheduler 14 | https://howtodoinjava.com 15 | 16 | 17 | UTF-8 18 | 19 | 20 | 21 | 22 | org.springframework.boot 23 | spring-boot-starter 24 | 25 | 26 | org.springframework.boot 27 | spring-boot-starter-web 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /task-scheduler/src/main/java/com/howtodoinjava/App.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class App { 8 | 9 | public static void main(String[] args) { 10 | 11 | SpringApplication.run(App.class, args); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /task-scheduler/src/main/java/com/howtodoinjava/config/SchedulerConfig.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.config; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.scheduling.annotation.EnableAsync; 6 | import org.springframework.scheduling.annotation.EnableScheduling; 7 | import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; 8 | 9 | @Configuration 10 | @EnableScheduling 11 | @EnableAsync 12 | public class SchedulerConfig { 13 | 14 | @Bean 15 | public ThreadPoolTaskScheduler threadPoolTaskScheduler() { 16 | 17 | ThreadPoolTaskScheduler threadPoolTaskScheduler = new ThreadPoolTaskScheduler(); 18 | threadPoolTaskScheduler.setPoolSize(5); 19 | threadPoolTaskScheduler.setThreadNamePrefix("ThreadPoolTaskScheduler"); 20 | return threadPoolTaskScheduler; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /task-scheduler/src/main/java/com/howtodoinjava/tasks/Task.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.tasks; 2 | 3 | import java.time.LocalDateTime; 4 | import lombok.extern.java.Log; 5 | import org.springframework.scheduling.annotation.Async; 6 | import org.springframework.scheduling.annotation.Scheduled; 7 | import org.springframework.stereotype.Component; 8 | 9 | @Component 10 | @Log 11 | public class Task { 12 | 13 | @Scheduled(initialDelay = 1000, fixedRate = 10000) 14 | public void run() { 15 | log.info("Current time is :: " + LocalDateTime.now()); 16 | } 17 | 18 | @Scheduled(fixedRate = 10000) 19 | @Async 20 | public void taskWithConcurrentExecutions() { 21 | log.info("Current time is :: " + LocalDateTime.now()); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /task-scheduler/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.task.scheduling.pool.size=5 -------------------------------------------------------------------------------- /task-scheduler/src/test/java/com/howtodoinjava/AppTest.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | public class AppTest 8 | { 9 | @Test 10 | void contextLoads(){ 11 | 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /task-scheduler/target/classes/application.properties: -------------------------------------------------------------------------------- 1 | spring.task.scheduling.pool.size=5 -------------------------------------------------------------------------------- /virtual-threads-demo/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 4.0.0 6 | 7 | virtual-threads-demo 8 | 1.0-SNAPSHOT 9 | virtual-threads-demo 10 | https://howtodoinjava.com 11 | 12 | 13 | com.howtodoinjava 14 | Spring-Boot3-Demos 15 | 1.0-SNAPSHOT 16 | 17 | 18 | 19 | 20 | org.springframework.boot 21 | spring-boot-starter-web 22 | 23 | 24 | org.springframework.boot 25 | spring-boot-devtools 26 | runtime 27 | true 28 | 29 | 30 | 31 | 32 | 33 | 42 | 43 | org.springframework.boot 44 | spring-boot-maven-plugin 45 | 46 | 47 | 48 | org.projectlombok 49 | lombok 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /virtual-threads-demo/src/main/java/com/howtodoinjava/App.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava; 2 | 3 | import java.time.Duration; 4 | import java.time.Instant; 5 | import java.time.LocalDateTime; 6 | import java.util.stream.IntStream; 7 | import lombok.extern.slf4j.Slf4j; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.boot.CommandLineRunner; 10 | import org.springframework.boot.SpringApplication; 11 | import org.springframework.boot.autoconfigure.SpringBootApplication; 12 | import org.springframework.context.ApplicationEventPublisher; 13 | 14 | @Slf4j 15 | @SpringBootApplication 16 | public class App implements CommandLineRunner { 17 | 18 | public static void main(String[] args) { 19 | SpringApplication.run(App.class, args); 20 | } 21 | 22 | @Autowired 23 | ApplicationEventPublisher publisher; 24 | 25 | @Override 26 | public void run(String... args) throws Exception { 27 | Instant start = Instant.now(); 28 | IntStream.rangeClosed(1, 10_000) 29 | .forEachOrdered(i -> 30 | publisher.publishEvent("Hello #" + i + " at:" + LocalDateTime.now()) 31 | ); 32 | 33 | Instant finish = Instant.now(); 34 | long timeElapsed = Duration.between(start, finish).toMillis(); 35 | 36 | log.info("=====Elapsed time : {} ========", timeElapsed); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /virtual-threads-demo/src/main/java/com/howtodoinjava/AppEventListener.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava; 2 | 3 | import lombok.extern.slf4j.Slf4j; 4 | import org.springframework.context.event.EventListener; 5 | import org.springframework.scheduling.annotation.Async; 6 | import org.springframework.stereotype.Component; 7 | 8 | @Component 9 | @Slf4j 10 | public class AppEventListener { 11 | @EventListener 12 | @Async 13 | public void onGreetingEvent(String message) { 14 | log.info(Thread.currentThread() + " :: Received: {}", message); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /virtual-threads-demo/src/main/java/com/howtodoinjava/config/AsyncConfig.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.config; 2 | 3 | import java.util.concurrent.Executors; 4 | import org.springframework.boot.autoconfigure.task.TaskExecutionAutoConfiguration; 5 | import org.springframework.boot.web.embedded.tomcat.TomcatProtocolHandlerCustomizer; 6 | import org.springframework.context.annotation.Bean; 7 | import org.springframework.context.annotation.Configuration; 8 | import org.springframework.core.task.AsyncTaskExecutor; 9 | import org.springframework.core.task.support.TaskExecutorAdapter; 10 | import org.springframework.scheduling.annotation.EnableAsync; 11 | 12 | @Configuration 13 | @EnableAsync 14 | public class AsyncConfig { 15 | 16 | @Bean(TaskExecutionAutoConfiguration.APPLICATION_TASK_EXECUTOR_BEAN_NAME) 17 | public AsyncTaskExecutor asyncTaskExecutor() { 18 | //TODO: Enable in Java 20 19 | //return new TaskExecutorAdapter(Executors.newVirtualThreadPerTaskExecutor()); 20 | return new TaskExecutorAdapter(Executors.newSingleThreadExecutor()); 21 | } 22 | 23 | @Bean 24 | public TomcatProtocolHandlerCustomizer protocolHandlerVirtualThreadExecutorCustomizer() { 25 | return protocolHandler -> { 26 | //TODO: Enable in Java 20 27 | //protocolHandler.setExecutor(Executors.newVirtualThreadPerTaskExecutor()); 28 | }; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /virtual-threads-demo/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | logging.level.web=TRACE 2 | logging.level.com.howtodoinjava=DEBUG 3 | 4 | spring.main.allow-bean-definition-overriding=true -------------------------------------------------------------------------------- /virtual-threads-demo/src/test/java/com/howtodoinjava/AppTest.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava; 2 | 3 | import org.junit.jupiter.api.Nested; 4 | import org.junit.jupiter.api.Test; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | 7 | public class AppTest 8 | { 9 | @Nested 10 | @SpringBootTest 11 | class DemoApplicationTests { 12 | 13 | @Test 14 | void contextLoads() { 15 | } 16 | 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /webflux-part-event-api-example/.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | !**/src/main/**/target/ 4 | !**/src/test/**/target/ 5 | 6 | ### IntelliJ IDEA ### 7 | .idea/modules.xml 8 | .idea/jarRepositories.xml 9 | .idea/compiler.xml 10 | .idea/libraries/ 11 | *.iws 12 | *.iml 13 | *.ipr 14 | 15 | ### Eclipse ### 16 | .apt_generated 17 | .classpath 18 | .factorypath 19 | .project 20 | .settings 21 | .springBeans 22 | .sts4-cache 23 | 24 | ### NetBeans ### 25 | /nbproject/private/ 26 | /nbbuild/ 27 | /dist/ 28 | /nbdist/ 29 | /.nb-gradle/ 30 | build/ 31 | !**/src/main/**/build/ 32 | !**/src/test/**/build/ 33 | 34 | ### VS Code ### 35 | .vscode/ 36 | 37 | ### Mac OS ### 38 | .DS_Store -------------------------------------------------------------------------------- /webflux-part-event-api-example/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 4.0.0 7 | 8 | com.howtodoinjava 9 | webflux-part-event-api-example 10 | 1.0-SNAPSHOT 11 | 12 | webflux-part-event-api-example 13 | https://howtodoinjava.com 14 | 15 | 16 | com.howtodoinjava 17 | Spring-Boot3-Demos 18 | 1.0-SNAPSHOT 19 | 20 | 21 | 22 | 23 | org.springframework.boot 24 | spring-boot-starter-web 25 | 26 | 27 | org.springframework.boot 28 | spring-boot-starter-webflux 29 | 30 | 31 | org.springframework.boot 32 | spring-boot-starter-reactor-netty 33 | 34 | 35 | org.springframework.boot 36 | spring-boot-devtools 37 | runtime 38 | true 39 | 40 | 41 | io.projectreactor 42 | reactor-test 43 | test 44 | 45 | 46 | org.mockito 47 | mockito-junit-jupiter 48 | test 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /webflux-part-event-api-example/src/main/java/com/howtodoinjava/App.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class App 8 | { 9 | public static void main(String[] args) { 10 | SpringApplication.run(App.class, args); 11 | } 12 | } -------------------------------------------------------------------------------- /webflux-part-event-api-example/src/main/java/com/howtodoinjava/app/config/WebFuxConfig.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.app.config; 2 | 3 | import com.fasterxml.jackson.databind.ObjectMapper; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.context.annotation.Configuration; 6 | import org.springframework.http.MediaType; 7 | import org.springframework.http.codec.ServerCodecConfigurer; 8 | import org.springframework.http.codec.json.Jackson2JsonDecoder; 9 | import org.springframework.http.codec.json.Jackson2JsonEncoder; 10 | import org.springframework.web.reactive.config.WebFluxConfigurer; 11 | 12 | @Configuration 13 | public class WebFuxConfig implements WebFluxConfigurer { 14 | 15 | } -------------------------------------------------------------------------------- /webflux-part-event-api-example/src/main/java/com/howtodoinjava/app/model/FileUploadCommand.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava.app.model; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | import org.springframework.http.codec.multipart.FilePart; 7 | 8 | @Data 9 | @AllArgsConstructor 10 | @NoArgsConstructor 11 | public class FileUploadCommand { 12 | private String name; 13 | private FilePart file; 14 | } 15 | -------------------------------------------------------------------------------- /webflux-part-event-api-example/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.servlet.multipart.max-file-size=50MB 2 | spring.servlet.multipart.max-request-size=50MB -------------------------------------------------------------------------------- /webflux-part-event-api-example/src/main/resources/spring.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lokeshgupta1981/Spring-Boot3-Demos/6974e42d87a604213d2cdb2c0b2a1e26418e172c/webflux-part-event-api-example/src/main/resources/spring.png -------------------------------------------------------------------------------- /webflux-part-event-api-example/src/test/java/com/howtodoinjava/AppTest.java: -------------------------------------------------------------------------------- 1 | package com.howtodoinjava; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | public class AppTest 8 | { 9 | @Test 10 | void contextLoads() { 11 | } 12 | } 13 | --------------------------------------------------------------------------------