├── .gitignore
├── .mvn
└── wrapper
│ ├── maven-wrapper.jar
│ └── maven-wrapper.properties
├── README.md
├── bookRequest.json
├── pom.xml
└── src
├── main
├── java
│ └── com
│ │ ├── business
│ │ └── common
│ │ │ └── Demo.java
│ │ └── javatechie
│ │ ├── InterviewQaApplication.java
│ │ ├── advice
│ │ ├── LogExecutionTracker.java
│ │ ├── LogPayloadAdvice.java
│ │ └── LoggingAdvice.java
│ │ ├── annotation
│ │ ├── LogPayloads.java
│ │ └── TrackExecutionTime.java
│ │ ├── client
│ │ └── UserClient.java
│ │ ├── common
│ │ ├── User.java
│ │ └── Volunteer.java
│ │ ├── config
│ │ ├── AppConfig.java
│ │ ├── CorsConfig.java
│ │ ├── DataSourceConfig.java
│ │ ├── KafkaConfig.java
│ │ ├── SecurityConfig.java
│ │ ├── SwaggerConfig.java
│ │ ├── WebClientConfig.java
│ │ └── WebConfig.java
│ │ ├── controller
│ │ ├── ControllerDemo.java
│ │ ├── DemoController.java
│ │ ├── FileUploadController.java
│ │ ├── FlightBookingController.java
│ │ ├── ProductController.java
│ │ ├── RestControllerDemo.java
│ │ └── UserClientController.java
│ │ ├── di
│ │ ├── OrderInstanceFactory.java
│ │ ├── OrderRepository.java
│ │ ├── OrderRepositoryImpl1.java
│ │ ├── OrderRepositoryImpl2.java
│ │ ├── OrderService.java
│ │ ├── RestClientService.java
│ │ └── TrailerService.java
│ │ ├── dto
│ │ ├── Address.java
│ │ ├── Author.java
│ │ ├── Book.java
│ │ ├── Company.java
│ │ ├── ErrorDto.java
│ │ ├── Geo.java
│ │ ├── KafkaProps.java
│ │ ├── Product.java
│ │ └── UserResponse.java
│ │ ├── entity
│ │ └── UserDetails.java
│ │ ├── exception
│ │ └── ProductNotFoundException.java
│ │ ├── handler
│ │ ├── DuplicateProductException.java
│ │ ├── ProductExceptionHandler.java
│ │ └── ProductServiceException.java
│ │ ├── processor
│ │ └── PasswordValidationBeanPostProcessor.java
│ │ ├── repository
│ │ ├── DemoRepository.java
│ │ └── UserDetailsRepository.java
│ │ ├── scope
│ │ ├── BeanScopeTestService.java
│ │ ├── CustomThreadScope.java
│ │ ├── ProtoTypeBean.java
│ │ ├── RequestScopedBean.java
│ │ ├── SessionScopedBean.java
│ │ └── SingletonBean.java
│ │ ├── service
│ │ ├── DemoService.java
│ │ └── ProductService.java
│ │ └── validation
│ │ ├── ProductTypeValidator.java
│ │ └── ValidateProductType.java
└── resources
│ ├── application-prod.properties
│ ├── application-stg.properties
│ ├── application.properties
│ ├── application.yaml
│ └── templates
│ ├── hello.html
│ └── upload.html
└── test
└── java
└── com
└── javatechie
└── InterviewQaApplicationTests.java
/.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/wrapper/maven-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Java-Techie-jt/spring-boot-interview-qa/d2a445b4b1782db579e11a5b807e8e8c0995b11f/.mvn/wrapper/maven-wrapper.jar
--------------------------------------------------------------------------------
/.mvn/wrapper/maven-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.4/apache-maven-3.9.4-bin.zip
2 | wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar
3 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # spring-boot-interview-qa
2 |
--------------------------------------------------------------------------------
/bookRequest.json:
--------------------------------------------------------------------------------
1 | {
2 | "bookId": 123,
3 | "title": "Spring in Action",
4 | "publicationYear": 2022,
5 | "authors": [
6 | {
7 | "authorId": 1,
8 | "name": "Craig Walls",
9 | "birthYear": 1978
10 | },
11 | {
12 | "authorId": 2,
13 | "name": "John Doe",
14 | "birthYear": 1985
15 | }
16 | ]
17 | }
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | org.springframework.boot
7 | spring-boot-starter-parent
8 | 3.1.2
9 |
10 |
11 | com.javatechie
12 | interview-qa
13 | 0.0.1-SNAPSHOT
14 | interview-qa
15 | Demo project for Spring Boot
16 |
17 | 17
18 | 2022.0.4
19 |
20 |
21 |
22 | org.springframework.boot
23 | spring-boot-starter-web
24 |
25 |
26 | org.springframework.boot
27 | spring-boot-starter-actuator
28 |
29 |
30 | org.springframework.boot
31 | spring-boot-starter-validation
32 |
33 |
34 | org.projectlombok
35 | lombok
36 | true
37 |
38 |
39 | org.springframework.boot
40 | spring-boot-starter-test
41 | test
42 |
43 |
44 | org.springframework.boot
45 | spring-boot-starter-data-jpa
46 |
47 |
48 | com.mysql
49 | mysql-connector-j
50 | runtime
51 |
52 |
53 | org.springframework.boot
54 | spring-boot-starter-thymeleaf
55 |
56 |
57 | org.springdoc
58 | springdoc-openapi-starter-webmvc-ui
59 | 2.0.4
60 |
61 |
62 | org.springframework.cloud
63 | spring-cloud-starter-openfeign
64 |
65 |
66 | org.springframework.boot
67 | spring-boot-starter-webflux
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 | org.springframework.cloud
80 | spring-cloud-dependencies
81 | ${spring-cloud.version}
82 | pom
83 | import
84 |
85 |
86 |
87 |
88 |
89 |
90 | org.springframework.boot
91 | spring-boot-maven-plugin
92 |
93 |
94 |
95 | org.projectlombok
96 | lombok
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
--------------------------------------------------------------------------------
/src/main/java/com/business/common/Demo.java:
--------------------------------------------------------------------------------
1 | package com.business.common;
2 |
3 | import org.springframework.stereotype.Component;
4 |
5 | @Component
6 | public class Demo {
7 |
8 | public Demo() {
9 | System.out.println("Demo class scanned !!!!");
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/src/main/java/com/javatechie/InterviewQaApplication.java:
--------------------------------------------------------------------------------
1 | package com.javatechie;
2 |
3 | import com.javatechie.common.User;
4 | import com.javatechie.common.Volunteer;
5 | import com.javatechie.config.DataSourceConfig;
6 | import com.javatechie.di.OrderService;
7 | import com.javatechie.scope.BeanScopeTestService;
8 | import com.javatechie.scope.CustomThreadScope;
9 | import com.javatechie.scope.SingletonBean;
10 | import jakarta.annotation.PostConstruct;
11 | import org.springframework.beans.factory.annotation.Autowired;
12 | import org.springframework.beans.factory.annotation.Value;
13 | import org.springframework.beans.factory.config.Scope;
14 | import org.springframework.boot.CommandLineRunner;
15 | import org.springframework.boot.SpringApplication;
16 | import org.springframework.boot.autoconfigure.SpringBootApplication;
17 | import org.springframework.cloud.openfeign.EnableFeignClients;
18 | import org.springframework.context.ConfigurableApplicationContext;
19 | import org.springframework.core.env.Environment;
20 | import org.springframework.stereotype.Component;
21 | import org.springframework.stereotype.Controller;
22 | import org.springframework.stereotype.Repository;
23 | import org.springframework.stereotype.Service;
24 | import org.springframework.web.bind.annotation.RestController;
25 |
26 | //@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class,AopAutoConfiguration.class})
27 | @SpringBootApplication
28 | @EnableFeignClients
29 | public class InterviewQaApplication implements CommandLineRunner {
30 |
31 | @Value("${discount.offer.price}")
32 | private int discountPrice;
33 |
34 |
35 | @Autowired
36 | private Environment environment;
37 |
38 | @Autowired
39 | private DataSourceConfig config;
40 |
41 |
42 | @PostConstruct
43 | public void initLogic() {
44 | System.out.println("PostConstruct logic executed ...!");
45 | //connection pool logic
46 | //kafka producer/consumer instantiate
47 | //data shedding
48 | //external API call
49 | }
50 |
51 |
52 | public static void main(String[] args) {
53 | //ConfigurableApplicationContext context =
54 | System.out.println("SpringApplication run() method ....... executed");
55 | ConfigurableApplicationContext context = SpringApplication.run(InterviewQaApplication.class, args);
56 | //OrderService service = context.getBean("orderService", OrderService.class);
57 | // service.test();
58 |
59 | // Scope scope = new CustomThreadScope();
60 | // context.getBeanFactory().registerScope("threadScope", scope);
61 | //
62 | // Runnable childThread = () -> {
63 | // Volunteer v1 = context.getBean(Volunteer.class);
64 | // Volunteer v2 = context.getBean(Volunteer.class);
65 | // System.out.println("Hashcode of two object created by child thread " + v1.hashCode() + " & " + v2.hashCode());
66 | // };
67 | // new Thread(childThread).start();
68 |
69 | // This code will be executed by main thread
70 | // Volunteer v1 = context.getBean(Volunteer.class);
71 | // Volunteer v2 = context.getBean(Volunteer.class);
72 | // System.out.println("Hashcode of two object created by main thread " + v1.hashCode() + " & " + v2.hashCode());
73 | //
74 | ////
75 | ////
76 | SingletonBean sb1 = context.getBean(SingletonBean.class);
77 | SingletonBean sb2 = context.getBean(SingletonBean.class);
78 | System.out.println(sb1.getProtoTypeBean().hashCode()+" - "+sb2.getProtoTypeBean().hashCode());
79 |
80 | // BeanScopeTestService service1=context.getBean(BeanScopeTestService.class);
81 | // BeanScopeTestService service2=context.getBean(BeanScopeTestService.class);
82 | // BeanScopeTestService service3=context.getBean(BeanScopeTestService.class);
83 |
84 | }
85 |
86 | @Override
87 | public void run(String... args) throws Exception {
88 | //DB connection
89 | //populate some data to the db
90 | // pre-processing logic you want to perform
91 | // System.out.println("DISCOUNT PRICE : "+environment.getProperty("discount.offer.price"));
92 |
93 | System.out.println("DISCOUNT PRICE : " + discountPrice);
94 | System.out.println("Environment variable : " + environment.getProperty("spring.profiles.active"));
95 | System.out.println("CONFIG VALUE : " + config);
96 | System.out.println("CommandLineRunner run() method ....... executed");
97 |
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/src/main/java/com/javatechie/advice/LogExecutionTracker.java:
--------------------------------------------------------------------------------
1 | package com.javatechie.advice;
2 |
3 | import lombok.extern.slf4j.Slf4j;
4 | import org.aspectj.lang.JoinPoint;
5 | import org.aspectj.lang.ProceedingJoinPoint;
6 | import org.aspectj.lang.annotation.Around;
7 | import org.aspectj.lang.annotation.Aspect;
8 | import org.aspectj.lang.annotation.Before;
9 | import org.springframework.scheduling.annotation.Async;
10 | import org.springframework.stereotype.Component;
11 |
12 | @Aspect
13 | @Component
14 | @Slf4j
15 | public class LogExecutionTracker {
16 |
17 | @Around("@annotation(com.javatechie.annotation.TrackExecutionTime)")
18 | public Object logExecutionDuration(ProceedingJoinPoint pjp) throws Throwable {
19 | //before advice
20 | long startTime = System.currentTimeMillis();
21 | Object obj = pjp.proceed();
22 | //after advice
23 | long endTime = System.currentTimeMillis();
24 | log.info(" method {} execution takes {} ms times to complete ", pjp.getSignature(), (endTime - startTime));
25 | return obj;
26 | }
27 |
28 | }
29 |
30 |
--------------------------------------------------------------------------------
/src/main/java/com/javatechie/advice/LogPayloadAdvice.java:
--------------------------------------------------------------------------------
1 | package com.javatechie.advice;
2 |
3 | import com.fasterxml.jackson.databind.ObjectMapper;
4 | import lombok.extern.slf4j.Slf4j;
5 | import org.aspectj.lang.ProceedingJoinPoint;
6 | import org.aspectj.lang.annotation.Around;
7 | import org.aspectj.lang.annotation.Aspect;
8 | import org.springframework.stereotype.Component;
9 |
10 | @Aspect
11 | @Component
12 | @Slf4j
13 | public class LogPayloadAdvice {
14 |
15 | @Around("@annotation(com.javatechie.annotation.LogPayloads)")
16 | public Object logPayloads(ProceedingJoinPoint pjp) throws Throwable {
17 | //before advice
18 | log.info("Request Body {} ", new ObjectMapper().writeValueAsString(pjp.getArgs()));
19 | Object obj = pjp.proceed();
20 | //after advice
21 | log.info("Response Body {} ", new ObjectMapper().writeValueAsString(pjp.getArgs()));
22 | return obj;
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/main/java/com/javatechie/advice/LoggingAdvice.java:
--------------------------------------------------------------------------------
1 | package com.javatechie.advice;
2 |
3 | import com.fasterxml.jackson.core.JsonProcessingException;
4 | import com.fasterxml.jackson.databind.ObjectMapper;
5 | import lombok.extern.slf4j.Slf4j;
6 | import org.aspectj.lang.JoinPoint;
7 | import org.aspectj.lang.annotation.*;
8 | import org.springframework.stereotype.Component;
9 |
10 | @Aspect
11 | @Component
12 | @Slf4j
13 | public class LoggingAdvice {
14 |
15 | @Pointcut("execution(* com.javatechie.service.ProductService.*(..))")
16 | private void logPointcut() {
17 | }
18 |
19 | @Before("logPointcut()")
20 | public void logRequest(JoinPoint joinPoint) throws JsonProcessingException {
21 | log.info("Before Advice - class name {} ,method name {} ", joinPoint.getTarget(), joinPoint.getSignature().getName());
22 | log.info("Before Advice - Request Body {} ", new ObjectMapper().writeValueAsString(joinPoint.getArgs()));
23 | }
24 |
25 | // @AfterReturning(value = "execution (* com.javatechie.controller.ProductController.*(..))",returning = "object")
26 | // public void logResponse(JoinPoint joinPoint,Object object) throws JsonProcessingException {
27 | // log.info("LoggingAdvice::logResponse class name {} ,method name {} ", joinPoint.getTarget(), joinPoint.getSignature().getName());
28 | // log.info("LoggingAdvice::logResponse Response Body {} ", new ObjectMapper().writeValueAsString(object));
29 | // }
30 |
31 | @AfterReturning(value = "execution (* com.javatechie.service.ProductService.*(..))")
32 | public void logResponse(JoinPoint joinPoint) throws JsonProcessingException {
33 | log.info("After Advice - LoggingAdvice::logResponse class name {} ,method name {} ", joinPoint.getTarget(), joinPoint.getSignature().getName());
34 | log.info("After Advice - LoggingAdvice::logResponse Response Body {} ", new ObjectMapper().writeValueAsString(joinPoint.getArgs()));
35 | }
36 |
37 |
38 | @AfterThrowing(value = "execution (* com.javatechie.service.ProductService.*(..))")
39 | public void logError(JoinPoint joinPoint) throws JsonProcessingException {
40 | log.info("Throws Advice - LoggingAdvice::logResponse class name {} ,method name {} ", joinPoint.getTarget(), joinPoint.getSignature().getName());
41 | log.info("Throws Advice - LoggingAdvice::logResponse Response Body {} ", new ObjectMapper().writeValueAsString(joinPoint.getArgs()));
42 | }
43 |
44 |
45 | }
--------------------------------------------------------------------------------
/src/main/java/com/javatechie/annotation/LogPayloads.java:
--------------------------------------------------------------------------------
1 | package com.javatechie.annotation;
2 |
3 | import java.lang.annotation.ElementType;
4 | import java.lang.annotation.Retention;
5 | import java.lang.annotation.RetentionPolicy;
6 | import java.lang.annotation.Target;
7 |
8 | @Target(ElementType.METHOD)
9 | @Retention(RetentionPolicy.RUNTIME)
10 | public @interface LogPayloads {
11 | }
--------------------------------------------------------------------------------
/src/main/java/com/javatechie/annotation/TrackExecutionTime.java:
--------------------------------------------------------------------------------
1 | package com.javatechie.annotation;
2 |
3 | import java.lang.annotation.ElementType;
4 | import java.lang.annotation.Retention;
5 | import java.lang.annotation.RetentionPolicy;
6 | import java.lang.annotation.Target;
7 |
8 | @Target(ElementType.METHOD)
9 | @Retention(RetentionPolicy.RUNTIME)
10 | public @interface TrackExecutionTime {
11 | }
--------------------------------------------------------------------------------
/src/main/java/com/javatechie/client/UserClient.java:
--------------------------------------------------------------------------------
1 | package com.javatechie.client;
2 |
3 | import com.javatechie.dto.UserResponse;
4 | import org.springframework.cloud.openfeign.FeignClient;
5 | import org.springframework.web.bind.annotation.GetMapping;
6 |
7 | import java.util.List;
8 | //https://jsonplaceholder.typicode.com/users
9 | @FeignClient(url="https://jsonplaceholder.typicode.com",name = "USER-CLIENT")
10 | public interface UserClient {
11 |
12 | @GetMapping("/users")
13 | public List getUsers();
14 | }
15 |
--------------------------------------------------------------------------------
/src/main/java/com/javatechie/common/User.java:
--------------------------------------------------------------------------------
1 | package com.javatechie.common;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Data;
5 | import lombok.NoArgsConstructor;
6 | import org.springframework.stereotype.Component;
7 |
8 |
9 | @Data
10 | @AllArgsConstructor
11 | @NoArgsConstructor
12 |
13 | public class User {
14 |
15 | private String username;
16 | private String password;
17 | }
18 |
--------------------------------------------------------------------------------
/src/main/java/com/javatechie/common/Volunteer.java:
--------------------------------------------------------------------------------
1 | package com.javatechie.common;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Data;
5 | import lombok.NoArgsConstructor;
6 | import org.springframework.context.annotation.Scope;
7 | import org.springframework.stereotype.Component;
8 |
9 | @Component
10 | @Scope("threadScope")
11 | public class Volunteer {
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/src/main/java/com/javatechie/config/AppConfig.java:
--------------------------------------------------------------------------------
1 | package com.javatechie.config;
2 |
3 | import com.javatechie.common.User;
4 | import com.javatechie.service.DemoService;
5 | import org.springframework.context.annotation.Bean;
6 | import org.springframework.context.annotation.Configuration;
7 | import org.springframework.web.client.RestTemplate;
8 |
9 | @Configuration
10 | public class AppConfig {
11 |
12 | @Bean
13 | public DemoService demoService(){
14 | return new DemoService();
15 | }
16 |
17 | @Bean
18 | public User user() {
19 | User user = new User();
20 | user.setUsername("john");
21 | user.setPassword("t27t"); // The original, unencrypted password
22 | return user;
23 | }
24 |
25 | @Bean
26 | public RestTemplate template(){
27 | return new RestTemplate();
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/main/java/com/javatechie/config/CorsConfig.java:
--------------------------------------------------------------------------------
1 | //package com.javatechie.config;
2 | //
3 | //import org.springframework.context.annotation.Bean;
4 | //import org.springframework.context.annotation.Configuration;
5 | //import org.springframework.web.servlet.config.annotation.CorsRegistry;
6 | //import org.springframework.web.servlet.config.annotation.EnableWebMvc;
7 | //import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
8 | //
9 | //@Configuration
10 | //@EnableWebMvc
11 | //public class CorsConfig implements WebMvcConfigurer {
12 | //
13 | // @Override
14 | // public void addCorsMappings(CorsRegistry registry) {
15 | // registry.addMapping("/api/**")
16 | // .allowedOrigins("*") // Add your front-end application's origin
17 | // .allowedMethods("GET", "POST", "PUT", "DELETE")
18 | // .allowedHeaders("Origin", "Content-Type", "Accept", "Authorization")
19 | // .allowCredentials(true)
20 | // .maxAge(3600);
21 | // }
22 | //}
23 |
--------------------------------------------------------------------------------
/src/main/java/com/javatechie/config/DataSourceConfig.java:
--------------------------------------------------------------------------------
1 | package com.javatechie.config;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Data;
5 | import lombok.NoArgsConstructor;
6 | import org.springframework.boot.context.properties.ConfigurationProperties;
7 | import org.springframework.context.annotation.Configuration;
8 | import org.springframework.stereotype.Component;
9 |
10 | @Configuration
11 | @ConfigurationProperties(prefix = "spring.datasource")
12 | @Data
13 | @AllArgsConstructor
14 | @Component
15 | @NoArgsConstructor
16 | public class DataSourceConfig {
17 |
18 | private String username;
19 | private String password;
20 |
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/src/main/java/com/javatechie/config/KafkaConfig.java:
--------------------------------------------------------------------------------
1 | package com.javatechie.config;
2 |
3 | import com.javatechie.dto.KafkaProps;
4 | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
5 | import org.springframework.context.annotation.Bean;
6 | import org.springframework.context.annotation.Configuration;
7 | import org.springframework.context.annotation.Profile;
8 |
9 | @Configuration
10 | public class KafkaConfig {
11 |
12 | @Bean
13 | //@Profile("dev")
14 | @ConditionalOnProperty(prefix = "app.active",name = "env",havingValue = "dev")
15 | public KafkaProps devKafkaProps() {
16 | KafkaProps props = new KafkaProps("2.237.64.90:8181", 8181, "dev-user-topic");
17 | System.out.println("kafka dev bean initialized !");
18 | return props;
19 | }
20 |
21 | @Bean
22 | // @Profile("stg")
23 | @ConditionalOnProperty(prefix = "app.active",name = "env",havingValue = "stg")
24 | public KafkaProps stgKafkaProps() {
25 | KafkaProps props = new KafkaProps("200.40.7.181:8282", 8282, "stg-user-topic");
26 | System.out.println("kafka stg bean initialized !");
27 | return props;
28 | }
29 |
30 | @Bean
31 | //@Profile("prod")
32 | @ConditionalOnProperty(prefix = "app.active",name = "env",havingValue = "prod")
33 | public KafkaProps prodKafkaProps() {
34 | KafkaProps props = new KafkaProps("247.69.84.118:8383", 8383, "prod-user-topic");
35 | System.out.println("kafka prod bean initialized !");
36 | return props;
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/main/java/com/javatechie/config/SecurityConfig.java:
--------------------------------------------------------------------------------
1 | package com.javatechie.config;
2 |
3 | import org.springframework.context.annotation.Configuration;
4 |
5 | @Configuration
6 | public class SecurityConfig {
7 |
8 | public SecurityConfig() {
9 | System.out.println("SecurityConfig loaded .....");
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/src/main/java/com/javatechie/config/SwaggerConfig.java:
--------------------------------------------------------------------------------
1 | package com.javatechie.config;
2 |
3 | import org.springframework.context.annotation.Configuration;
4 |
5 | @Configuration
6 | public class SwaggerConfig {
7 |
8 | public SwaggerConfig() {
9 | System.out.println("SwaggerConfig loaded .....");
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/src/main/java/com/javatechie/config/WebClientConfig.java:
--------------------------------------------------------------------------------
1 | package com.javatechie.config;
2 |
3 | import org.springframework.context.annotation.Bean;
4 | import org.springframework.context.annotation.Configuration;
5 | import org.springframework.web.reactive.function.client.WebClient;
6 |
7 | @Configuration
8 | public class WebClientConfig {
9 |
10 | @Bean
11 | public WebClient webClient() {
12 | return WebClient.builder().baseUrl("https://jsonplaceholder.typicode.com").build();
13 | }
14 | }
15 |
16 |
--------------------------------------------------------------------------------
/src/main/java/com/javatechie/config/WebConfig.java:
--------------------------------------------------------------------------------
1 | //package com.javatechie.config;
2 | //
3 | //import org.springframework.context.annotation.Configuration;
4 | //import org.springframework.http.MediaType;
5 | //import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer;
6 | //import org.springframework.web.servlet.config.annotation.EnableWebMvc;
7 | //import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
8 | //
9 | //@Configuration
10 | //@EnableWebMvc
11 | //public class WebConfig implements WebMvcConfigurer {
12 | //
13 | // @Override
14 | // public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
15 | // configurer
16 | // .favorParameter(false)
17 | // .defaultContentType(MediaType.APPLICATION_JSON)
18 | // .mediaType("json", MediaType.APPLICATION_JSON)
19 | // .mediaType("xml", MediaType.APPLICATION_XML);
20 | // }
21 | //}
22 | //
23 | //}
24 | //
25 |
--------------------------------------------------------------------------------
/src/main/java/com/javatechie/controller/ControllerDemo.java:
--------------------------------------------------------------------------------
1 | package com.javatechie.controller;
2 |
3 | import org.springframework.http.MediaType;
4 | import org.springframework.stereotype.Controller;
5 | import org.springframework.web.bind.annotation.GetMapping;
6 | import org.springframework.web.bind.annotation.ResponseBody;
7 |
8 | @Controller
9 | public class ControllerDemo {
10 |
11 | @GetMapping("/controller/welcome")
12 | //modelAndView
13 | public String welcome(){
14 | return "hello";
15 | }
16 |
17 | @GetMapping(value = "/greetingMessage",produces = MediaType.TEXT_PLAIN_VALUE)
18 | @ResponseBody
19 | public String message(){
20 | return "Welcome to javatechie";
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/main/java/com/javatechie/controller/DemoController.java:
--------------------------------------------------------------------------------
1 | package com.javatechie.controller;
2 |
3 | import com.javatechie.dto.KafkaProps;
4 | import com.javatechie.entity.UserDetails;
5 | import com.javatechie.repository.UserDetailsRepository;
6 | import com.javatechie.scope.SessionScopedBean;
7 | import io.swagger.v3.oas.annotations.Operation;
8 | import org.springframework.beans.factory.annotation.Autowired;
9 | import org.springframework.http.HttpStatus;
10 | import org.springframework.web.bind.annotation.*;
11 |
12 | @RestController
13 | //@CrossOrigin(origins = "*")
14 | public class DemoController {
15 |
16 | // @Autowired
17 | // private RequestScopedBean requestScopedBean;
18 | @Autowired
19 | private SessionScopedBean sessionScopedBean;
20 |
21 | @Autowired
22 | private UserDetailsRepository repository;
23 |
24 |
25 | @GetMapping("/message")
26 | public String getMessage() {
27 | return sessionScopedBean.getMessage();
28 | }
29 |
30 | @GetMapping("/users/name")
31 | public String checkBodyInGET(@RequestBody UserDetails userDetails) {
32 | return userDetails.getName();
33 | }
34 |
35 |
36 | @PostMapping("/users") // not idempotent
37 | @Operation(description = "INSERT NEW USER")
38 | @ResponseStatus(HttpStatus.CREATED)
39 | public UserDetails addNewUser(@RequestBody UserDetails userDetails) {
40 | return repository.save(userDetails);
41 | }
42 |
43 | @PutMapping("/users/{id}") // idempotent
44 | @ResponseStatus(HttpStatus.NO_CONTENT)
45 | public UserDetails addAndUpdateUser(@PathVariable int id, @RequestBody UserDetails userDetails) {
46 | UserDetails existingUserDetails = repository.findById(id).get();
47 | existingUserDetails.setName(userDetails.getName());
48 | existingUserDetails.setAge(userDetails.getAge());
49 | return repository.save(existingUserDetails);
50 | }
51 |
52 | // @GetMapping("/users")
53 | // @PostMapping
54 | // @PutMapping
55 | // @PatchMapping
56 | // @DeleteMapping
57 | // public ResponseEntity> doSomeOperation(@RequestBody Object input){
58 | //
59 | // }
60 |
61 | }
62 |
--------------------------------------------------------------------------------
/src/main/java/com/javatechie/controller/FileUploadController.java:
--------------------------------------------------------------------------------
1 | package com.javatechie.controller;
2 |
3 | import io.swagger.v3.oas.annotations.Hidden;
4 | import org.springframework.stereotype.Controller;
5 | import org.springframework.ui.Model;
6 | import org.springframework.web.bind.annotation.GetMapping;
7 | import org.springframework.web.bind.annotation.PostMapping;
8 | import org.springframework.web.bind.annotation.RequestParam;
9 | import org.springframework.web.multipart.MultipartFile;
10 |
11 | import java.io.IOException;
12 | import java.nio.file.Files;
13 | import java.nio.file.Path;
14 | import java.nio.file.Paths;
15 |
16 | @Controller
17 | public class FileUploadController {
18 |
19 | @GetMapping("/home")
20 | public String index() {
21 | return "upload";
22 | }
23 |
24 | @PostMapping("/upload")
25 | @Hidden
26 | public String uploadFile(@RequestParam("file") MultipartFile file, Model model) throws IOException {
27 | Path path = Paths.get("/Users/javatechie/Desktop/Files/" + file.getOriginalFilename());
28 | Files.write(path, file.getBytes());
29 | model.addAttribute("message", "File has been uploaded successfully");
30 | return "upload";
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/main/java/com/javatechie/controller/FlightBookingController.java:
--------------------------------------------------------------------------------
1 | package com.javatechie.controller;
2 |
3 | import io.swagger.v3.oas.annotations.Hidden;
4 | import io.swagger.v3.oas.annotations.Operation;
5 | import org.springframework.http.ResponseEntity;
6 | import org.springframework.web.bind.annotation.*;
7 |
8 | @RestController
9 | @RequestMapping("/flight")
10 | public class FlightBookingController {
11 |
12 |
13 | @PostMapping("/v1/bookNow")
14 | public ResponseEntity bookingTicket(@RequestBody Object request) {
15 | //execute actual logic
16 | return ResponseEntity.ok("Flight booking successfully completed !");
17 | }
18 |
19 | @PostMapping("/v2/bookNow")
20 | @Hidden
21 | public ResponseEntity bookingTicket2(@RequestBody Object request) {
22 | //latestLogic
23 | return ResponseEntity.ok("New Flight booking approach successfully completed !");
24 | }
25 |
26 |
27 | @PostMapping("/bookingNow")
28 | public ResponseEntity bookTicketVersionWithRequestParam(@RequestBody Object request, @RequestParam(name = "version") int version) {
29 | //execute actual logic
30 | if (version == 1) {
31 | return ResponseEntity.ok("This is version 1 of the resource");
32 | } else {
33 | return ResponseEntity.ok("This is version 2 of the resource");
34 | }
35 | }
36 |
37 | @PostMapping("/bookingNow2")
38 | public ResponseEntity bookTicketVersionWithHeaderParam(@RequestBody Object request, @RequestHeader(name = "Api-Version") int version) {
39 | //execute actual logic
40 | if (version == 1) {
41 | return ResponseEntity.ok("This is version 1 of the resource");//old
42 | } else {
43 | return ResponseEntity.ok("This is version 2 of the resource");//new
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/main/java/com/javatechie/controller/ProductController.java:
--------------------------------------------------------------------------------
1 | package com.javatechie.controller;
2 |
3 | import com.javatechie.dto.Product;
4 | import com.javatechie.service.ProductService;
5 | import io.swagger.v3.oas.annotations.Hidden;
6 | import jakarta.validation.Valid;
7 | import org.springframework.beans.factory.annotation.Autowired;
8 | import org.springframework.dao.DataAccessException;
9 | import org.springframework.dao.DataRetrievalFailureException;
10 | import org.springframework.http.HttpStatus;
11 | import org.springframework.http.ResponseEntity;
12 | import org.springframework.web.bind.annotation.*;
13 | import org.springframework.web.client.HttpClientErrorException;
14 |
15 | import java.util.List;
16 |
17 | @RestController
18 | @RequestMapping("/products")
19 | public class ProductController {
20 |
21 | @Autowired
22 | private ProductService service;
23 |
24 | @PostMapping
25 | public List saveProduct(@RequestBody @Valid Product product){
26 | return service.saveProduct(product);
27 | }
28 |
29 |
30 | @GetMapping("/search/{productType}")//404
31 | public ResponseEntity> getProducts(@PathVariable String productType) {
32 | List products = service.getProductByType(productType);
33 | return ResponseEntity.ok(products);
34 | }
35 |
36 | @GetMapping("/filter")
37 | public ResponseEntity> findProducts(@RequestParam(value = "productType", required = false) String productType) {
38 | List productList = productType != null
39 | ? service.getProductByType(productType)
40 | : service.getProducts();
41 | return ResponseEntity.ok(productList);
42 | }
43 |
44 |
45 | @GetMapping(produces = {"application/json","application/xml"})
46 | @Hidden
47 | public List products(@RequestParam(value = "productType", required = false) String productType) {
48 | return productType != null
49 | ? service.getProductByType(productType)
50 | : service.getProducts();
51 | }
52 |
53 |
54 |
55 | @GetMapping("/stores/{flag}/{storeId}")
56 | public String fetchStoreLocation(@PathVariable boolean flag,@PathVariable String storeId){
57 | return service.fetchLocation(flag, storeId);
58 | }
59 |
60 |
61 | }
62 |
--------------------------------------------------------------------------------
/src/main/java/com/javatechie/controller/RestControllerDemo.java:
--------------------------------------------------------------------------------
1 | package com.javatechie.controller;
2 |
3 | import com.javatechie.dto.Book;
4 | import org.springframework.web.bind.annotation.*;
5 |
6 | @RestController
7 | public class RestControllerDemo {
8 |
9 | @GetMapping("/restController/welcome")
10 | public String welcome(){
11 | return "hello";
12 | }
13 |
14 | @PostMapping("/books")
15 | public String processBook(@RequestBody Book book){
16 | return book.getTitle()+" New book has been published on year "+book.getPublicationYear();
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/main/java/com/javatechie/controller/UserClientController.java:
--------------------------------------------------------------------------------
1 | package com.javatechie.controller;
2 |
3 | import com.javatechie.client.UserClient;
4 | import com.javatechie.dto.UserResponse;
5 | import org.springframework.beans.factory.annotation.Autowired;
6 | import org.springframework.stereotype.Service;
7 | import org.springframework.web.bind.annotation.GetMapping;
8 | import org.springframework.web.bind.annotation.RestController;
9 | import org.springframework.web.client.RestTemplate;
10 | import org.springframework.web.reactive.function.client.WebClient;
11 | import reactor.core.publisher.Flux;
12 |
13 | import java.util.List;
14 |
15 | @RestController
16 | public class UserClientController {
17 |
18 | @Autowired
19 | private RestTemplate template;
20 |
21 | @Autowired
22 | private UserClient userClient;
23 |
24 | @Autowired
25 | private WebClient webClient;
26 |
27 | @GetMapping("/fetchMockUsers1")
28 | public List fetchMockUsersWithRestTemplate() {
29 | return template.getForObject("https://jsonplaceholder.typicode.com/users", List.class);
30 | }
31 |
32 |
33 | @GetMapping("/fetchMockUsers2")
34 | public List fetchMockUsersWithFeignClient() {
35 | return userClient.getUsers();
36 | }
37 |
38 | @GetMapping("/fetchMockUsers3")
39 | public List fetchMockUsersWithWebclient() {
40 | Flux response = webClient.get()
41 | .uri("/users")
42 | .retrieve()
43 | .bodyToFlux(UserResponse.class);
44 | // Block and get the result (synchronous call - for demonstration purposes only)
45 | return response.collectList().block();
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/main/java/com/javatechie/di/OrderInstanceFactory.java:
--------------------------------------------------------------------------------
1 | package com.javatechie.di;
2 |
3 | public class OrderInstanceFactory {
4 |
5 | public static OrderRepository getInstance() {
6 | return new OrderRepositoryImpl1();
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/src/main/java/com/javatechie/di/OrderRepository.java:
--------------------------------------------------------------------------------
1 | package com.javatechie.di;
2 |
3 | import org.springframework.stereotype.Repository;
4 |
5 | public interface OrderRepository {
6 |
7 | public void saveOrder();
8 | }
9 |
--------------------------------------------------------------------------------
/src/main/java/com/javatechie/di/OrderRepositoryImpl1.java:
--------------------------------------------------------------------------------
1 | package com.javatechie.di;
2 |
3 | import org.springframework.stereotype.Repository;
4 |
5 | @Repository
6 | public class OrderRepositoryImpl1 implements OrderRepository {
7 | @Override
8 | public void saveOrder() {
9 | System.out.println("OrderRepositoryImpl1::saveOrder() method executed..");
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/src/main/java/com/javatechie/di/OrderRepositoryImpl2.java:
--------------------------------------------------------------------------------
1 | package com.javatechie.di;
2 |
3 | import org.springframework.stereotype.Component;
4 |
5 | @Component
6 | public class OrderRepositoryImpl2 implements OrderRepository{
7 | @Override
8 | public void saveOrder() {
9 | System.out.println("OrderRepositoryImpl2::saveOrder() method executed..");
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/src/main/java/com/javatechie/di/OrderService.java:
--------------------------------------------------------------------------------
1 | package com.javatechie.di;
2 |
3 |
4 | import org.springframework.beans.factory.annotation.Autowired;
5 | import org.springframework.context.annotation.Lazy;
6 | import org.springframework.stereotype.Service;
7 |
8 | @Service
9 | public class OrderService {
10 |
11 | private RestClientService restClientService;
12 |
13 | @Autowired
14 | @Lazy
15 | public void setRestClientService(RestClientService restClientService) {
16 | this.restClientService = restClientService;
17 | }
18 |
19 | // private OrderRepository orderRepository;
20 |
21 | // // //Setter DI
22 | // //optional dependency injection
23 | // //not immutable in nature
24 | // //circular dependency can't resolve
25 | // @Autowired
26 | // public void setOrderRepository(OrderRepository orderRepository) {
27 | // this.orderRepository = orderRepository;
28 | // }
29 | //
30 | // //Constructor DI
31 | // //Mandatory dependency injection
32 | // //immutable in nature
33 | // //circular dependency can't resolve
34 | // @Autowired
35 | // public OrderService(OrderRepository orderRepository) {
36 | // this.orderRepository = orderRepository;
37 | // }
38 | //
39 | //
40 | // public void test() {
41 | // orderRepository.saveOrder();
42 | // }
43 | }
44 |
--------------------------------------------------------------------------------
/src/main/java/com/javatechie/di/RestClientService.java:
--------------------------------------------------------------------------------
1 | package com.javatechie.di;
2 |
3 | import org.springframework.beans.factory.annotation.Autowired;
4 | import org.springframework.context.annotation.Lazy;
5 | import org.springframework.stereotype.Component;
6 |
7 | @Component
8 | public class RestClientService {
9 |
10 | private OrderService orderService;
11 |
12 | @Autowired
13 | @Lazy
14 | public void setOrderService(OrderService orderService) {
15 | this.orderService = orderService;
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/main/java/com/javatechie/di/TrailerService.java:
--------------------------------------------------------------------------------
1 | package com.javatechie.di;
2 |
3 | import jakarta.annotation.Resource;
4 | import org.springframework.beans.factory.annotation.Autowired;
5 | import org.springframework.beans.factory.annotation.Qualifier;
6 | import org.springframework.stereotype.Service;
7 |
8 | @Service
9 | public class TrailerService {
10 |
11 | @Autowired
12 | //@Qualifier("orderRepositoryImpl2")//byType
13 | @Resource(name = "orderRepositoryImpl1")//byName
14 | private OrderRepository orderRepository;
15 | }
16 |
--------------------------------------------------------------------------------
/src/main/java/com/javatechie/dto/Address.java:
--------------------------------------------------------------------------------
1 |
2 | package com.javatechie.dto;
3 |
4 | import lombok.AllArgsConstructor;
5 | import lombok.Data;
6 | import lombok.NoArgsConstructor;
7 |
8 | @Data
9 | @AllArgsConstructor
10 | @NoArgsConstructor
11 | public class Address {
12 |
13 | public String street;
14 | public String suite;
15 | public String city;
16 | public String zipcode;
17 | public Geo geo;
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/src/main/java/com/javatechie/dto/Author.java:
--------------------------------------------------------------------------------
1 | package com.javatechie.dto;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Data;
5 | import lombok.NoArgsConstructor;
6 |
7 | @Data
8 | @AllArgsConstructor
9 | @NoArgsConstructor
10 | public class Author {
11 | private long authorId;
12 | private String name;
13 | private int birthYear;
14 | }
15 |
--------------------------------------------------------------------------------
/src/main/java/com/javatechie/dto/Book.java:
--------------------------------------------------------------------------------
1 | package com.javatechie.dto;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Data;
5 | import lombok.NoArgsConstructor;
6 |
7 | import java.util.List;
8 |
9 | @Data
10 | @AllArgsConstructor
11 | @NoArgsConstructor
12 | public class Book {
13 | private long bookId;
14 | private String title;
15 | private int publicationYear;
16 | private List authors;
17 | }
18 |
19 |
20 |
--------------------------------------------------------------------------------
/src/main/java/com/javatechie/dto/Company.java:
--------------------------------------------------------------------------------
1 |
2 | package com.javatechie.dto;
3 |
4 | import lombok.AllArgsConstructor;
5 | import lombok.Data;
6 | import lombok.NoArgsConstructor;
7 |
8 | @Data
9 | @AllArgsConstructor
10 | @NoArgsConstructor
11 | public class Company {
12 |
13 | public String name;
14 | public String catchPhrase;
15 | public String bs;
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/src/main/java/com/javatechie/dto/ErrorDto.java:
--------------------------------------------------------------------------------
1 | package com.javatechie.dto;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Builder;
5 | import lombok.Data;
6 | import lombok.NoArgsConstructor;
7 | import org.springframework.http.HttpStatus;
8 | @Data
9 | @AllArgsConstructor
10 | @NoArgsConstructor
11 | @Builder
12 | public class ErrorDto {
13 |
14 | private String status;
15 | private String errorMessage;
16 | private HttpStatus statusCode;
17 | }
18 |
--------------------------------------------------------------------------------
/src/main/java/com/javatechie/dto/Geo.java:
--------------------------------------------------------------------------------
1 |
2 | package com.javatechie.dto;
3 |
4 | import lombok.AllArgsConstructor;
5 | import lombok.Data;
6 | import lombok.NoArgsConstructor;
7 |
8 | @Data
9 | @AllArgsConstructor
10 | @NoArgsConstructor
11 | public class Geo {
12 |
13 | public String lat;
14 | public String lng;
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/src/main/java/com/javatechie/dto/KafkaProps.java:
--------------------------------------------------------------------------------
1 | package com.javatechie.dto;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Data;
5 | import lombok.NoArgsConstructor;
6 | import org.springframework.stereotype.Component;
7 |
8 | @Data
9 | @AllArgsConstructor
10 | @NoArgsConstructor
11 | public class KafkaProps {
12 |
13 | private String bootStrapServers;
14 | private int port;
15 | private String topicName;
16 | }
17 |
--------------------------------------------------------------------------------
/src/main/java/com/javatechie/dto/Product.java:
--------------------------------------------------------------------------------
1 | package com.javatechie.dto;
2 |
3 | import com.javatechie.validation.ValidateProductType;
4 | import jakarta.validation.constraints.*;
5 | import lombok.AllArgsConstructor;
6 | import lombok.Data;
7 | import lombok.NoArgsConstructor;
8 |
9 | import java.math.BigDecimal;
10 | import java.util.Date;
11 |
12 | @Data
13 | @AllArgsConstructor
14 | @NoArgsConstructor
15 | public class Product {
16 | @NotNull(message = "id shouldn't be null")
17 | @NotEmpty(message = "id shouldn't be empty")
18 | private String id;
19 | @NotBlank(message = "name shouldn't be null or empty")
20 | private String name;
21 | @Min(value = 499,message = "price shouldn't be less than 499")
22 | @Max(value = 100000,message = "price shouldn't be exceed more than 100000")
23 | private double price;
24 | @NotBlank(message = "model shouldn't be null or empty")
25 | // @Pattern(regexp = "[A-Za-z0-9]+")
26 | private String model;
27 | @NotBlank(message = "productType shouldn't be null or empty")
28 | @ValidateProductType
29 | private String productType;
30 |
31 | // @Email
32 | // private String emailId;
33 | //
34 | // @AssertFalse
35 | // @AssertTrue
36 | // private boolean isActive;
37 | //
38 | // @Future
39 | // @Past
40 | // private Date birthDate;
41 |
42 | }
43 |
--------------------------------------------------------------------------------
/src/main/java/com/javatechie/dto/UserResponse.java:
--------------------------------------------------------------------------------
1 |
2 | package com.javatechie.dto;
3 |
4 | import lombok.AllArgsConstructor;
5 | import lombok.Data;
6 | import lombok.NoArgsConstructor;
7 |
8 | @Data
9 | @AllArgsConstructor
10 | @NoArgsConstructor
11 | public class UserResponse {
12 |
13 | public Integer id;
14 | public String name;
15 | public String username;
16 | public String email;
17 | public Address address;
18 | public String phone;
19 | public String website;
20 | public Company company;
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/src/main/java/com/javatechie/entity/UserDetails.java:
--------------------------------------------------------------------------------
1 | package com.javatechie.entity;
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 | @Data
12 | @AllArgsConstructor
13 | @NoArgsConstructor
14 | @Entity
15 | public class UserDetails {
16 | @Id
17 | @GeneratedValue(strategy = GenerationType.IDENTITY)
18 | private int id;
19 | private String name;
20 | private int age;
21 | }
22 |
--------------------------------------------------------------------------------
/src/main/java/com/javatechie/exception/ProductNotFoundException.java:
--------------------------------------------------------------------------------
1 | package com.javatechie.exception;
2 |
3 | public class ProductNotFoundException extends RuntimeException{
4 |
5 | public ProductNotFoundException(String message) {
6 | super(message);
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/src/main/java/com/javatechie/handler/DuplicateProductException.java:
--------------------------------------------------------------------------------
1 | package com.javatechie.handler;
2 |
3 | public class DuplicateProductException extends RuntimeException{
4 |
5 | public DuplicateProductException(String message) {
6 | super(message);
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/src/main/java/com/javatechie/handler/ProductExceptionHandler.java:
--------------------------------------------------------------------------------
1 | package com.javatechie.handler;
2 |
3 | import com.javatechie.dto.ErrorDto;
4 | import com.javatechie.exception.ProductNotFoundException;
5 | import org.springframework.http.HttpStatus;
6 | import org.springframework.http.ProblemDetail;
7 | import org.springframework.web.bind.MethodArgumentNotValidException;
8 | import org.springframework.web.bind.annotation.ExceptionHandler;
9 | import org.springframework.web.bind.annotation.RestControllerAdvice;
10 |
11 | import java.util.HashMap;
12 | import java.util.Map;
13 |
14 | @RestControllerAdvice
15 | public class ProductExceptionHandler {
16 |
17 |
18 | @ExceptionHandler(ProductNotFoundException.class)
19 | public ProblemDetail handleProductNotFoundException(ProductNotFoundException ex) {
20 | // return ErrorDto.builder()
21 | // .status("FAIL")
22 | // .errorMessage(ex.getMessage())
23 | // .statusCode(HttpStatus.INTERNAL_SERVER_ERROR).build();
24 |
25 | return ProblemDetail.forStatusAndDetail(HttpStatus.INTERNAL_SERVER_ERROR, ex.getMessage());
26 | }
27 |
28 | @ExceptionHandler(DuplicateProductException.class)
29 | public ProblemDetail handleDuplicateProductException(DuplicateProductException ex) {
30 | // return ErrorDto.builder()
31 | // .status("FAIL")
32 | // .errorMessage(ex.getMessage())
33 | // .statusCode(HttpStatus.INTERNAL_SERVER_ERROR).build();
34 |
35 | return ProblemDetail.forStatusAndDetail(HttpStatus.INTERNAL_SERVER_ERROR, ex.getMessage());
36 | }
37 |
38 |
39 | @ExceptionHandler(ProductServiceException.class)
40 | public ProblemDetail handleProductServiceException(ProductServiceException ex) {
41 | // return ErrorDto.builder()
42 | // .status("FAIL")
43 | // .errorMessage(ex.getMessage())
44 | // .statusCode(HttpStatus.INTERNAL_SERVER_ERROR).build();
45 |
46 | return ProblemDetail.forStatusAndDetail(HttpStatus.INTERNAL_SERVER_ERROR, ex.getMessage());
47 | }
48 |
49 | @ExceptionHandler(MethodArgumentNotValidException.class)
50 | public Map handleMethodArgumentNotValidException(MethodArgumentNotValidException ex) {
51 | Map errorMap = new HashMap<>();
52 | ex.getBindingResult().getFieldErrors()
53 | .forEach(error -> {
54 | errorMap.put(error.getField(), error.getDefaultMessage());
55 | });
56 | return errorMap;
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/src/main/java/com/javatechie/handler/ProductServiceException.java:
--------------------------------------------------------------------------------
1 | package com.javatechie.handler;
2 |
3 | public class ProductServiceException extends RuntimeException {
4 |
5 | public ProductServiceException(String message) {
6 | super(message);
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/src/main/java/com/javatechie/processor/PasswordValidationBeanPostProcessor.java:
--------------------------------------------------------------------------------
1 | ///*
2 | //package com.javatechie.processor;
3 | //
4 | //import com.javatechie.common.User;
5 | //import org.springframework.beans.BeansException;
6 | //import org.springframework.beans.factory.config.BeanPostProcessor;
7 | //import org.springframework.stereotype.Component;
8 | //
9 | //@Component
10 | //public class PasswordValidationBeanPostProcessor implements BeanPostProcessor {
11 | //
12 | // @Override
13 | // public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
14 | //// if (bean instanceof User user) {
15 | //// if (!isValidPassword(user.getPassword())) {
16 | //// throw new IllegalArgumentException("Invalid password for user: " + user.getUsername());
17 | //// }
18 | //// }
19 | // return bean;
20 | // }
21 | //
22 | // @Override
23 | // public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
24 | // return bean;
25 | // }
26 | //
27 | // private boolean isValidPassword(String password) {
28 | // // Implement your password validation logic here
29 | // // For example, check length, special characters, etc.
30 | // return password.length() >= 8 && password.matches(".*[@#$%!].*");
31 | // }
32 | //}
33 | //*/
34 |
--------------------------------------------------------------------------------
/src/main/java/com/javatechie/repository/DemoRepository.java:
--------------------------------------------------------------------------------
1 | package com.javatechie.repository;
2 |
3 | import org.springframework.stereotype.Repository;
4 |
5 | @Repository
6 | public interface DemoRepository {
7 | }
8 |
--------------------------------------------------------------------------------
/src/main/java/com/javatechie/repository/UserDetailsRepository.java:
--------------------------------------------------------------------------------
1 | package com.javatechie.repository;
2 |
3 | import com.javatechie.entity.UserDetails;
4 | import org.springframework.data.jpa.repository.JpaRepository;
5 |
6 | public interface UserDetailsRepository extends JpaRepository {
7 | }
8 |
--------------------------------------------------------------------------------
/src/main/java/com/javatechie/scope/BeanScopeTestService.java:
--------------------------------------------------------------------------------
1 | package com.javatechie.scope;
2 |
3 | import org.springframework.beans.factory.annotation.Autowired;
4 | import org.springframework.context.annotation.Scope;
5 | import org.springframework.stereotype.Component;
6 |
7 | @Component
8 | @Scope("prototype")
9 | public class BeanScopeTestService {
10 |
11 | public BeanScopeTestService() {
12 | System.out.println("BeanScopeTestService() instance created..");
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/src/main/java/com/javatechie/scope/CustomThreadScope.java:
--------------------------------------------------------------------------------
1 | package com.javatechie.scope;
2 |
3 | import org.springframework.beans.factory.ObjectFactory;
4 | import org.springframework.beans.factory.config.Scope;
5 |
6 | import java.util.HashMap;
7 | import java.util.Map;
8 |
9 | public class CustomThreadScope implements Scope {
10 |
11 |
12 | CustomThreadLocal customThreadLocal = new CustomThreadLocal();
13 |
14 | @Override
15 | public Object get(String str, ObjectFactory> objectFactory) {
16 | System.out.println("Fetched object from scope");
17 |
18 | @SuppressWarnings("unchecked")
19 | Map scope = (Map) customThreadLocal.get();
20 | Object object = scope.get(str);
21 | if (object == null) {
22 | object = objectFactory.getObject();
23 | scope.put(str, object);
24 | }
25 |
26 | return object;
27 | }
28 |
29 | @Override
30 | public Object remove(String name) {
31 | Map scope = (Map) customThreadLocal.get();
32 | return scope.remove(name);
33 | }
34 |
35 | @Override
36 | public void registerDestructionCallback(String name, Runnable callback) {
37 |
38 | }
39 |
40 | @Override
41 | public Object resolveContextualObject(String key) {
42 | return null;
43 | }
44 |
45 | @Override
46 | public String getConversationId() {
47 | return null;
48 | }
49 |
50 | class CustomThreadLocal extends ThreadLocal {
51 | protected Map initialValue() {
52 | System.out.println("Initializing ThreadLocal");
53 | return new HashMap();
54 | }
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/main/java/com/javatechie/scope/ProtoTypeBean.java:
--------------------------------------------------------------------------------
1 | package com.javatechie.scope;
2 |
3 | import org.springframework.context.annotation.Scope;
4 | import org.springframework.stereotype.Component;
5 |
6 | @Component
7 | @Scope("prototype")
8 | public class ProtoTypeBean {
9 |
10 | public ProtoTypeBean() {
11 | System.out.println("ProtoTypeBean() instantiate");
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/main/java/com/javatechie/scope/RequestScopedBean.java:
--------------------------------------------------------------------------------
1 | package com.javatechie.scope;
2 |
3 | import org.springframework.context.annotation.Scope;
4 | import org.springframework.context.annotation.ScopedProxyMode;
5 | import org.springframework.stereotype.Component;
6 | import org.springframework.web.context.WebApplicationContext;
7 |
8 | @Component
9 | @Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)
10 | public class RequestScopedBean {
11 |
12 | private String message;
13 |
14 | public RequestScopedBean() {
15 | System.out.println("RequestScopedBean() constructor called !!");
16 | this.message = "This is a request-scoped bean ";
17 | }
18 |
19 | public String getMessage() {
20 | return message;
21 | }
22 |
23 | public void setMessage(String message) {
24 | this.message = message;
25 | }
26 | }
27 |
28 |
--------------------------------------------------------------------------------
/src/main/java/com/javatechie/scope/SessionScopedBean.java:
--------------------------------------------------------------------------------
1 | package com.javatechie.scope;
2 |
3 | import org.springframework.context.annotation.Scope;
4 | import org.springframework.context.annotation.ScopedProxyMode;
5 | import org.springframework.stereotype.Component;
6 | import org.springframework.web.context.WebApplicationContext;
7 |
8 | import java.time.LocalDateTime;
9 |
10 | @Component
11 | @Scope(value = WebApplicationContext.SCOPE_SESSION, proxyMode = ScopedProxyMode.TARGET_CLASS)
12 | public class SessionScopedBean {
13 | private String message;
14 |
15 | public SessionScopedBean() {
16 | System.out.println("SessionScopedBean() constructor called !!"+ LocalDateTime.now());
17 | this.message = "This is a Session-scoped bean ";
18 | }
19 |
20 | public String getMessage() {
21 | return message;
22 | }
23 |
24 | public void setMessage(String message) {
25 | this.message = message;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/main/java/com/javatechie/scope/SingletonBean.java:
--------------------------------------------------------------------------------
1 | package com.javatechie.scope;
2 |
3 | import org.springframework.beans.factory.ObjectFactory;
4 | import org.springframework.beans.factory.annotation.Autowired;
5 | import org.springframework.beans.factory.annotation.Lookup;
6 | import org.springframework.context.ApplicationContext;
7 | import org.springframework.stereotype.Component;
8 |
9 | @Component
10 | public class SingletonBean {
11 |
12 | // @Autowired
13 | // private ProtoTypeBean protoTypeBean;
14 |
15 | // @Autowired
16 | // ApplicationContext context;
17 | @Autowired
18 | private ObjectFactory protoTypeBeanObjectFactory;
19 |
20 | public SingletonBean() {
21 | System.out.println("SingletonBean() instantiated !!");
22 | }
23 |
24 | public ProtoTypeBean getProtoTypeBean() {
25 | return getInstance();
26 | }
27 |
28 | @Lookup
29 | public ProtoTypeBean getInstance(){
30 | return null;
31 | }
32 |
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/src/main/java/com/javatechie/service/DemoService.java:
--------------------------------------------------------------------------------
1 | package com.javatechie.service;
2 |
3 | import org.springframework.stereotype.Component;
4 |
5 | //@Component
6 | public class DemoService {
7 | }
8 |
--------------------------------------------------------------------------------
/src/main/java/com/javatechie/service/ProductService.java:
--------------------------------------------------------------------------------
1 | package com.javatechie.service;
2 |
3 | import com.javatechie.annotation.LogPayloads;
4 | import com.javatechie.annotation.TrackExecutionTime;
5 | import com.javatechie.dto.Product;
6 | import com.javatechie.exception.ProductNotFoundException;
7 | import com.javatechie.handler.DuplicateProductException;
8 | import com.javatechie.handler.ProductServiceException;
9 | import org.springframework.dao.DataRetrievalFailureException;
10 | import org.springframework.http.HttpStatus;
11 | import org.springframework.stereotype.Service;
12 | import org.springframework.web.client.HttpClientErrorException;
13 |
14 | import java.util.List;
15 | import java.util.Optional;
16 | import java.util.stream.Collectors;
17 | import java.util.stream.Stream;
18 |
19 | @Service
20 | public class ProductService {
21 |
22 | List productList = Stream.of(
23 | new Product("PTC49893", "Mobile", 9500, "SAMSUNG Galaxy F13 (Sunrise Copper, 64 GB)", "Electronics"),
24 | new Product("PTC25563", "Keyboard", 9500, "MAC Magic Keyboard", "Electronics"),
25 | new Product("PTC25372", "Books", 250, "It Ends With Us", "Education"),
26 | new Product("PTC49823", "Remote Control Toys", 699, "Wembley High Speed Mini 1:24 Scale Rechargeable Remote Control car with Lithium Battery", "Baby&Kids")
27 | ).collect(Collectors.toList());
28 |
29 |
30 | public List getProducts() {
31 | return productList;
32 | }
33 |
34 | //joinpoint
35 | //pointcut (com.javatechie.service.saveProduct.*())
36 | @TrackExecutionTime
37 | @LogPayloads
38 | public List saveProduct(Product product) {
39 | //TransactionAspect
40 | //loggingAspect
41 | //validationAspect
42 | //auditingAspect
43 | //notificationAspect
44 | boolean containsProductId = productList.stream()
45 | .map(Product::getId)
46 | .anyMatch(productId -> productId.equals(product.getId()));
47 | if (!containsProductId) {
48 | productList.add(product);
49 | } else {
50 | throw new DuplicateProductException("Product code already exist in system ! " + product.getId());
51 | }
52 | return productList;
53 | }
54 |
55 | //Before Advice
56 | public List getProductByType(String productType) {
57 | //Transaction
58 | //logging
59 | //validation
60 | //auditing
61 | //notification
62 | List products = productList.stream()
63 | .filter(product -> product.getProductType().equals(productType))
64 | .collect(Collectors.toList());
65 |
66 | return Optional.of(products)
67 | .filter(list -> !list.isEmpty())
68 | .orElseThrow(() -> new ProductNotFoundException("Products not available for the type " + productType));
69 |
70 | }
71 | //After Advice -> consider Exception
72 | //After returning Advice -> No Exception
73 | //After throwing advice -> if any exception occurs
74 | //around advice -> Before + After returning
75 |
76 | public String fetchLocation(boolean flag, String storeId) {
77 | //Transaction
78 | //logging
79 | //validation
80 | //auditing
81 | //notification
82 | try {
83 | if (flag) {
84 | //fetch from application DB
85 | //logic
86 | throw new DataRetrievalFailureException("Store not available in system with storeId " + storeId);
87 | } else {
88 | //do rest api call to fetch store info by ID
89 | //logic
90 | throw new HttpClientErrorException(HttpStatus.INTERNAL_SERVER_ERROR,
91 | "Rest client error occurred while fetching store information");
92 | }
93 | } catch (Exception exception) {
94 | throw new ProductServiceException(exception.getMessage());
95 | }
96 |
97 | }
98 |
99 |
100 | }
101 |
--------------------------------------------------------------------------------
/src/main/java/com/javatechie/validation/ProductTypeValidator.java:
--------------------------------------------------------------------------------
1 | package com.javatechie.validation;
2 |
3 | import jakarta.validation.ConstraintValidator;
4 | import jakarta.validation.ConstraintValidatorContext;
5 |
6 | import java.util.Arrays;
7 | import java.util.List;
8 |
9 | public class ProductTypeValidator implements ConstraintValidator {
10 | @Override
11 | public boolean isValid(String productType, ConstraintValidatorContext constraintValidatorContext) {
12 | List productTypes = Arrays.asList("Electronics", "Education","Baby&Kids");
13 | return productTypes.contains(productType);
14 | }
15 | }
--------------------------------------------------------------------------------
/src/main/java/com/javatechie/validation/ValidateProductType.java:
--------------------------------------------------------------------------------
1 | package com.javatechie.validation;
2 |
3 | import jakarta.validation.Constraint;
4 | import jakarta.validation.Payload;
5 |
6 | import java.lang.annotation.*;
7 |
8 | @Target({ElementType.FIELD,ElementType.PARAMETER})
9 | @Retention(RetentionPolicy.RUNTIME)
10 | @Documented
11 | @Constraint(validatedBy = ProductTypeValidator.class)
12 | public @interface ValidateProductType {
13 |
14 | public String message() default "Invalid productType: It should be either Electronics OR Education OR Baby&Kids";
15 |
16 | Class>[] groups() default {};
17 |
18 | Class extends Payload>[] payload() default {};
19 | }
--------------------------------------------------------------------------------
/src/main/resources/application-prod.properties:
--------------------------------------------------------------------------------
1 | spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
2 | spring.datasource.url = jdbc:mysql://localhost:3306/javatechie_prod
3 | spring.datasource.username = root
4 | spring.datasource.password = Password
5 | spring.jpa.hibernate.ddl-auto = update
6 |
7 | spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQLDialect
8 | spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
--------------------------------------------------------------------------------
/src/main/resources/application-stg.properties:
--------------------------------------------------------------------------------
1 | spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
2 | spring.datasource.url = jdbc:mysql://localhost:3306/javatechie_stg
3 | spring.datasource.username = root
4 | spring.datasource.password = Password
5 | spring.jpa.hibernate.ddl-auto = update
6 |
7 | spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQLDialect
8 | spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
--------------------------------------------------------------------------------
/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | #debug=true
2 |
3 | spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
4 | spring.datasource.url = jdbc:mysql://localhost:3306/javatechie
5 | spring.datasource.username = root
6 | spring.datasource.password = Password
7 | spring.jpa.hibernate.ddl-auto = update
8 |
9 | spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQLDialect
10 | spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
11 |
12 |
13 |
14 |
15 | #
16 | #spring.config.import=file:/Users/javatechie/Desktop/test.properties
17 |
18 | discount.offer.price= 20
19 |
20 | mylist= apple, banana, orange
21 |
22 | server.session.cookie.max-age= 1
23 | server.session.timeout= 1
24 | #
25 | ## Enable content negotiation
26 | #spring.mvc.contentnegotiation.favor-path-extension=true
27 | #spring.mvc.contentnegotiation.favor-parameter=true
28 | #spring.mvc.contentnegotiation.defaultContentType=application/xml
29 |
30 | app.active.env= prod
31 |
32 |
33 | #spring.profiles.active = stg
--------------------------------------------------------------------------------
/src/main/resources/application.yaml:
--------------------------------------------------------------------------------
1 | server:
2 | port: 8181
3 |
4 |
5 |
6 | discount:
7 | offer:
8 | price: 25
9 |
10 | myList:
11 | - orange
12 | - banana
13 | - apple
14 | - dfhjkd
15 | - hcdkh
16 |
17 |
18 | #spring:
19 | # profiles:
20 | # active:
21 | # - stg
--------------------------------------------------------------------------------
/src/main/resources/templates/hello.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | page loading
6 |
7 |
8 | Welcome message from controller
9 |
10 |
--------------------------------------------------------------------------------
/src/main/resources/templates/upload.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | File Upload Example
7 |
84 |
85 |
86 |
87 |
File Upload Example
88 |
89 |
90 |
91 |
92 |
98 |
99 |
100 |
107 |
108 |
109 |
--------------------------------------------------------------------------------
/src/test/java/com/javatechie/InterviewQaApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.javatechie;
2 |
3 | import org.junit.jupiter.api.Test;
4 | import org.springframework.boot.test.context.SpringBootTest;
5 |
6 | @SpringBootTest
7 | class InterviewQaApplicationTests {
8 |
9 | @Test
10 | void contextLoads() {
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------