diff --git a/pom.xml b/pom.xml index c955b7da4ece..8daec02b429a 100644 --- a/pom.xml +++ b/pom.xml @@ -214,6 +214,7 @@ gateway serialized-lob server-session + service-oriented-architecture virtual-proxy function-composition diff --git a/service-oriented-architecture/pom.xml b/service-oriented-architecture/pom.xml new file mode 100644 index 000000000000..9e5c715a02fd --- /dev/null +++ b/service-oriented-architecture/pom.xml @@ -0,0 +1,102 @@ + + + + 4.0.0 + + + com.iluwatar + java-design-patterns + 1.26.0-SNAPSHOT + + service-oriented-architecture + service-oriented-architecture + service-oriented-architecture + + + + + org.springframework.boot + spring-boot-dependencies + pom + 3.2.4 + import + + + + org.springframework.cloud + spring-cloud-starter-parent + 2023.0.1 + pom + import + + + + + + + + + org.springframework.boot + spring-boot-starter + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-test + test + + + org.junit.jupiter + junit-jupiter-engine + test + + + org.springframework.boot + spring-boot-autoconfigure + + + org.springframework.boot + spring-boot-starter-security + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + \ No newline at end of file diff --git a/service-oriented-architecture/src/main/java/com/iluwatar/soa/SOAExampleApplication.java b/service-oriented-architecture/src/main/java/com/iluwatar/soa/SOAExampleApplication.java new file mode 100644 index 000000000000..a2e79a53a29b --- /dev/null +++ b/service-oriented-architecture/src/main/java/com/iluwatar/soa/SOAExampleApplication.java @@ -0,0 +1,25 @@ +package com.iluwatar.soa; + +import com.iluwatar.soa.services.config.ServiceConfiguration; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +@Slf4j +public class SOAExampleApplication { + + public static void main(String[] args) { + ServiceConfiguration.configureAndRegisterServices(); + SpringApplication.run(SOAExampleApplication.class, args); + LOGGER.info("SOA Example Application started successfully!"); + LOGGER.info("You can access the application via: http://localhost:8080/login"); + LOGGER.info( + "This endpoint will retsurn a personalized greeting based on the weather conditions."); + LOGGER.info("You can explore other endpoints as well for different functionalities."); + } + + +} + + diff --git a/service-oriented-architecture/src/main/java/com/iluwatar/soa/controller/GreetingController.java b/service-oriented-architecture/src/main/java/com/iluwatar/soa/controller/GreetingController.java new file mode 100644 index 000000000000..a30fb77d0f7e --- /dev/null +++ b/service-oriented-architecture/src/main/java/com/iluwatar/soa/controller/GreetingController.java @@ -0,0 +1,21 @@ +package com.iluwatar.soa.controller; + +import com.iluwatar.soa.services.interfaces.PersonalizedGreetingService; +import com.iluwatar.soa.services.registry.ServiceRegistry; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("home") +public class GreetingController { + + @GetMapping("/greeting") + public String getGreeting() { + PersonalizedGreetingService personalizedGreetingService = + (PersonalizedGreetingService) ServiceRegistry.getService("personalizedGreetingService"); + return personalizedGreetingService.generateGreeting(); + } +} + + diff --git a/service-oriented-architecture/src/main/java/com/iluwatar/soa/controller/LoginController.java b/service-oriented-architecture/src/main/java/com/iluwatar/soa/controller/LoginController.java new file mode 100644 index 000000000000..d45e766a1f9a --- /dev/null +++ b/service-oriented-architecture/src/main/java/com/iluwatar/soa/controller/LoginController.java @@ -0,0 +1,15 @@ +/* +package com.iluwatar.soa.controller; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; + +@Controller +public class LoginController { + + @GetMapping("/login") + public String loginPage() { + return "loginPage"; + } +} +*/ diff --git a/service-oriented-architecture/src/main/java/com/iluwatar/soa/model/WeatherCondition.java b/service-oriented-architecture/src/main/java/com/iluwatar/soa/model/WeatherCondition.java new file mode 100644 index 000000000000..24f31bb353a8 --- /dev/null +++ b/service-oriented-architecture/src/main/java/com/iluwatar/soa/model/WeatherCondition.java @@ -0,0 +1,8 @@ +package com.iluwatar.soa.model; + +public enum WeatherCondition { + SUNNY, + RAINY, + CLOUDY, + FOGGY +} diff --git a/service-oriented-architecture/src/main/java/com/iluwatar/soa/security/WebSecurityConfig.java b/service-oriented-architecture/src/main/java/com/iluwatar/soa/security/WebSecurityConfig.java new file mode 100644 index 000000000000..b76b8c776aa7 --- /dev/null +++ b/service-oriented-architecture/src/main/java/com/iluwatar/soa/security/WebSecurityConfig.java @@ -0,0 +1,60 @@ +package com.iluwatar.soa.security; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configurers.LogoutConfigurer; +import org.springframework.security.core.userdetails.User; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; + +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.provisioning.InMemoryUserDetailsManager; +import org.springframework.security.web.SecurityFilterChain; + + +@Configuration +@EnableWebSecurity +public class WebSecurityConfig { + + @Bean + public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { + http + .authorizeHttpRequests(requests -> requests + .requestMatchers("/login").permitAll() + .anyRequest().authenticated() + ) + .formLogin(form -> form + .defaultSuccessUrl("/home/greeting", true) + .permitAll() + ) + .logout(LogoutConfigurer::permitAll); + + return http.build(); + } + + + @Bean + public UserDetailsService userDetailsService() { + UserDetails user = + User.builder() + .username("user") + .password(passwordEncoder().encode("password")) + .roles("USER") + .build(); + UserDetails admin = + User.builder() + .username("admin") + .password(passwordEncoder().encode("password")) + .roles("USER", "ADMIN") + .build(); + return new InMemoryUserDetailsManager(user, admin); + } + + @Bean + public PasswordEncoder passwordEncoder() { + return new BCryptPasswordEncoder(); + } +} diff --git a/service-oriented-architecture/src/main/java/com/iluwatar/soa/services/classes/GreetingServiceImpl.java b/service-oriented-architecture/src/main/java/com/iluwatar/soa/services/classes/GreetingServiceImpl.java new file mode 100644 index 000000000000..23df6469157b --- /dev/null +++ b/service-oriented-architecture/src/main/java/com/iluwatar/soa/services/classes/GreetingServiceImpl.java @@ -0,0 +1,13 @@ +package com.iluwatar.soa.services.classes; + +import com.iluwatar.soa.services.interfaces.GreetingService; +import org.springframework.stereotype.Service; + +@Service +public class GreetingServiceImpl implements GreetingService { + + public String getGenericGreeting() { + return "Hello, how are you today?"; + } + +} \ No newline at end of file diff --git a/service-oriented-architecture/src/main/java/com/iluwatar/soa/services/classes/PersonalizedGreetingServiceImpl.java b/service-oriented-architecture/src/main/java/com/iluwatar/soa/services/classes/PersonalizedGreetingServiceImpl.java new file mode 100644 index 000000000000..7a1e3f57bad6 --- /dev/null +++ b/service-oriented-architecture/src/main/java/com/iluwatar/soa/services/classes/PersonalizedGreetingServiceImpl.java @@ -0,0 +1,38 @@ +package com.iluwatar.soa.services.classes; + +import com.iluwatar.soa.model.WeatherCondition; +import com.iluwatar.soa.services.interfaces.GreetingService; +import com.iluwatar.soa.services.interfaces.PersonalizedGreetingService; +import com.iluwatar.soa.services.interfaces.WeatherService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +@Slf4j +public class PersonalizedGreetingServiceImpl implements PersonalizedGreetingService { + + private final GreetingService greetingService; + private final WeatherService weatherService; + + @Override + public String generateGreeting() { + String weatherGreeting = getWeatherGreeting(); + return weatherGreeting + "! " + greetingService.getGenericGreeting(); + } + + private String getWeatherGreeting() { + WeatherCondition currentWeather = weatherService.getCurrentWeather(); + return switch (currentWeather) { + case SUNNY -> "What a good sunny day!"; + case RAINY -> "What a rainy day!"; + case CLOUDY -> "What a cloudy day!"; + case FOGGY -> "What a foggy day!"; + default -> { + LOGGER.error("Unexpected weather condition: {}", currentWeather); + yield "unexpected weather condition"; + } + }; + } +} diff --git a/service-oriented-architecture/src/main/java/com/iluwatar/soa/services/classes/WeatherServiceImpl.java b/service-oriented-architecture/src/main/java/com/iluwatar/soa/services/classes/WeatherServiceImpl.java new file mode 100644 index 000000000000..26ab7453032e --- /dev/null +++ b/service-oriented-architecture/src/main/java/com/iluwatar/soa/services/classes/WeatherServiceImpl.java @@ -0,0 +1,17 @@ +package com.iluwatar.soa.services.classes; + +import com.iluwatar.soa.model.WeatherCondition; +import java.util.Random; +import com.iluwatar.soa.services.interfaces.WeatherService; +import org.springframework.stereotype.Service; + +@Service +public class WeatherServiceImpl implements WeatherService { + private final Random random = new Random(); + + public WeatherCondition getCurrentWeather() { + WeatherCondition[] conditions = WeatherCondition.values(); + int randomConditionIndex = random.nextInt(conditions.length); + return conditions[randomConditionIndex]; + } +} diff --git a/service-oriented-architecture/src/main/java/com/iluwatar/soa/services/config/ServiceConfiguration.java b/service-oriented-architecture/src/main/java/com/iluwatar/soa/services/config/ServiceConfiguration.java new file mode 100644 index 000000000000..4272161c89e3 --- /dev/null +++ b/service-oriented-architecture/src/main/java/com/iluwatar/soa/services/config/ServiceConfiguration.java @@ -0,0 +1,42 @@ +package com.iluwatar.soa.services.config; + +import com.iluwatar.soa.services.classes.GreetingServiceImpl; +import com.iluwatar.soa.services.classes.PersonalizedGreetingServiceImpl; +import com.iluwatar.soa.services.classes.WeatherServiceImpl; +import com.iluwatar.soa.services.interfaces.GreetingService; +import com.iluwatar.soa.services.interfaces.PersonalizedGreetingService; +import com.iluwatar.soa.services.interfaces.WeatherService; +import com.iluwatar.soa.services.registry.ServiceRegistry; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public final class ServiceConfiguration { + + private ServiceConfiguration() { + throw new IllegalStateException("Utility class"); + } + + public static void configureAndRegisterServices() { + LOGGER.info("Configuring and registering services..."); + + GreetingService greetingService = new GreetingServiceImpl(); + WeatherService weatherService = new WeatherServiceImpl(); + PersonalizedGreetingService personalizedGreetingService = + new PersonalizedGreetingServiceImpl(greetingService, weatherService); + + ServiceRegistry.registerService("greetingService", greetingService); + ServiceRegistry.registerService("weatherService", weatherService); + ServiceRegistry.registerService("personalizedGreetingService", personalizedGreetingService); + + LOGGER.info("Services configured and registered successfully."); + + logServiceRegistry(); + } + + private static void logServiceRegistry() { + LOGGER.info("Current service registry:"); + ServiceRegistry.registry.forEach( + (serviceName, serviceInstance) -> LOGGER.info("- {} : {}", serviceName, + serviceInstance.getClass().getName())); + } +} diff --git a/service-oriented-architecture/src/main/java/com/iluwatar/soa/services/interfaces/GreetingService.java b/service-oriented-architecture/src/main/java/com/iluwatar/soa/services/interfaces/GreetingService.java new file mode 100644 index 000000000000..3013c79f5f5a --- /dev/null +++ b/service-oriented-architecture/src/main/java/com/iluwatar/soa/services/interfaces/GreetingService.java @@ -0,0 +1,7 @@ +package com.iluwatar.soa.services.interfaces; + +public interface GreetingService { + + String getGenericGreeting(); + +} diff --git a/service-oriented-architecture/src/main/java/com/iluwatar/soa/services/interfaces/PersonalizedGreetingService.java b/service-oriented-architecture/src/main/java/com/iluwatar/soa/services/interfaces/PersonalizedGreetingService.java new file mode 100644 index 000000000000..8f8726aa204c --- /dev/null +++ b/service-oriented-architecture/src/main/java/com/iluwatar/soa/services/interfaces/PersonalizedGreetingService.java @@ -0,0 +1,7 @@ +package com.iluwatar.soa.services.interfaces; + +public interface PersonalizedGreetingService { + + String generateGreeting(); + +} diff --git a/service-oriented-architecture/src/main/java/com/iluwatar/soa/services/interfaces/WeatherService.java b/service-oriented-architecture/src/main/java/com/iluwatar/soa/services/interfaces/WeatherService.java new file mode 100644 index 000000000000..effe780fc13d --- /dev/null +++ b/service-oriented-architecture/src/main/java/com/iluwatar/soa/services/interfaces/WeatherService.java @@ -0,0 +1,7 @@ +package com.iluwatar.soa.services.interfaces; + +import com.iluwatar.soa.model.WeatherCondition; + +public interface WeatherService { + WeatherCondition getCurrentWeather(); +} diff --git a/service-oriented-architecture/src/main/java/com/iluwatar/soa/services/registry/ServiceRegistry.java b/service-oriented-architecture/src/main/java/com/iluwatar/soa/services/registry/ServiceRegistry.java new file mode 100644 index 000000000000..84449948cd5b --- /dev/null +++ b/service-oriented-architecture/src/main/java/com/iluwatar/soa/services/registry/ServiceRegistry.java @@ -0,0 +1,17 @@ +package com.iluwatar.soa.services.registry; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +public class ServiceRegistry { + public static final Map registry = new ConcurrentHashMap<>(); + + public static void registerService(String serviceName, T serviceInstance) { + registry.put(serviceName, serviceInstance); + } + + @SuppressWarnings("unchecked") + public static T getService(String serviceName) { + return (T) registry.get(serviceName); + } +} diff --git a/service-oriented-architecture/src/main/resources/application.properties b/service-oriented-architecture/src/main/resources/application.properties new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/service-oriented-architecture/src/main/resources/static/NameGreeting.html b/service-oriented-architecture/src/main/resources/static/NameGreeting.html new file mode 100644 index 000000000000..566549bdf8fa --- /dev/null +++ b/service-oriented-architecture/src/main/resources/static/NameGreeting.html @@ -0,0 +1,10 @@ + + + + + Title + + + + + \ No newline at end of file diff --git a/service-oriented-architecture/src/main/resources/static/WeatherGreeting.html b/service-oriented-architecture/src/main/resources/static/WeatherGreeting.html new file mode 100644 index 000000000000..fb4496d6015e --- /dev/null +++ b/service-oriented-architecture/src/main/resources/static/WeatherGreeting.html @@ -0,0 +1,24 @@ + + + + + + SOA Services + + + +

Welcome to your services!

+

Select a service:

+ + +