Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ firebase-service-account.json.b64
.idea/dataSources/dbb0ccd9-06dd-407f-b700-8142fac9bbbd.xml

# IDE
.idea/
.idea
*.iws
*.iml
*.ipr
Expand All @@ -25,7 +25,7 @@ build/
#ignore node modules
node_modules/
#ignore build folder
build/
build

#ignore logs
logs/
Expand Down
2 changes: 1 addition & 1 deletion applicationsConfiguration
1 change: 1 addition & 0 deletions common-utils/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@
</dependency>



</dependencies>


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import reactor.core.publisher.Mono;
import reactor.util.retry.Retry;


import java.time.Duration;
import java.util.UUID;

Expand Down
Binary file not shown.
Binary file modified common-utils/target/common-utils-0.0.1.jar
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/**
* Copyright © 2025
*
* @Author = TJTechy (Tajudeen Busari)
* @Version = 1.0
* This file is part of EcommerceMicroservices module of the Ecommerce Microservices project.
*/

package com.tjtechy.modelNotFoundException;

import java.util.List;
import java.util.UUID;

public class UserNotFoundException extends RuntimeException{

public UserNotFoundException(UUID ID){
super("User not found with id: " + ID);
}

public UserNotFoundException(List<UUID> IDS){
super("Users not found with ids: " + IDS);
}
}
Binary file modified exception/target/exception-0.0.1.jar
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
com\tjtechy\businessException\InsufficientStockQuantityException.class
com\tjtechy\businessException\OrderAlreadyCancelledException.class
com\tjtechy\modelNotFoundException\InventoryNotFoundException.class
com\tjtechy\modelNotFoundException\ProductNotFoundException.class
com\tjtechy\modelNotFoundException\NotificationNotFoundException.class
com\tjtechy\modelNotFoundException\UserNotFoundException.class
com\tjtechy\modelNotFoundException\OrderNotFoundException.class
com\tjtechy\businessException\InsufficientStockQuantityException.class
com\tjtechy\modelNotFoundException\InventoryNotFoundException.class
com\tjtechy\modelNotFoundException\ProductNotFoundException.class
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ C:\Users\tajud\javaProject\EcommerceMicroservices\exception\src\main\java\com\tj
C:\Users\tajud\javaProject\EcommerceMicroservices\exception\src\main\java\com\tjtechy\modelNotFoundException\NotificationNotFoundException.java
C:\Users\tajud\javaProject\EcommerceMicroservices\exception\src\main\java\com\tjtechy\modelNotFoundException\OrderNotFoundException.java
C:\Users\tajud\javaProject\EcommerceMicroservices\exception\src\main\java\com\tjtechy\modelNotFoundException\ProductNotFoundException.java
C:\Users\tajud\javaProject\EcommerceMicroservices\exception\src\main\java\com\tjtechy\modelNotFoundException\UserNotFoundException.java
7 changes: 6 additions & 1 deletion notification-service/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -215,8 +215,13 @@
<artifactId>springdoc-openapi-starter-webmvc-api</artifactId>
<version>2.8.9</version>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>junit-jupiter</artifactId>
<scope>test</scope>
</dependency>

</dependencies>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
Expand Down
13 changes: 6 additions & 7 deletions order-service/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

<!--Spring Boot Starter Web, it is blocking MVC-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
Expand All @@ -66,12 +67,6 @@
<!-- <dependency>-->
<!-- <groupId>io.micrometer</groupId>-->
<!-- <artifactId>micrometer-registry-prometheus</artifactId>-->
<!-- </dependency>-->
<!-- &lt;!&ndash; OpenTelemetry exporter for Prometheus &ndash;&gt;-->
<!-- <dependency>-->
<!-- <groupId>io.opentelemetry.instrumentation</groupId>-->
<!-- <artifactId>opentelemetry-instrumentation-api</artifactId>-->
<!-- <version>2.20.1</version>-->
<!-- </dependency>-->

<dependency>
Expand Down Expand Up @@ -136,6 +131,10 @@
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>

<!-- Jackson module to support Hibernate types and lazy loading
It prevents infinite recursion or unexpected JSON.E.G.,When you have
when you have another entity inside another entity related by for
example @OneToMany-->
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-hibernate6</artifactId>
Expand Down Expand Up @@ -201,7 +200,7 @@
<!-- <scope>test</scope>-->
<!-- </dependency>-->

<!-- Optional: For using JSON serialization in Redis
<!-- Optional: For using JSON serialization in Redis,
You don't need this if we are not serializing in redis
-->
<dependency>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,6 @@ void createOrderSuccess() throws Exception {

//Then: Verify Interactions
verify(orderService).processOrderReactively(any(Order.class));

}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,6 @@ class OrderServiceImplTest {
@Mock
private OrderEventProducer orderEventProducer;





private static final Logger logger = LoggerFactory.getLogger(OrderServiceImplTest.class);


Expand Down
19 changes: 1 addition & 18 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
<module>inventory-service</module>
<module>notification-service</module>
<module>user-service</module>
<module>security</module>
</modules>

<properties>
Expand Down Expand Up @@ -66,24 +67,6 @@
<artifactId>micrometer-observation</artifactId>
</dependency>

<!-- OpenTelemetry exporter for Prometheus.
NOTE: I MAY NEED TO REMOVE THIS
DEPENDENCY BECAUSE I WILL ADD SOME DEPENDENCIES FOR JAEGER FOR TRACING
-->
<!-- <dependency>-->
<!-- <groupId>io.opentelemetry.instrumentation</groupId>-->
<!-- <artifactId>opentelemetry-instrumentation-api</artifactId>-->
<!-- <version>2.20.1</version>-->
<!-- </dependency>-->

<!-- The dependency: Automatically enables context propagation (traceId/spanId passing between services)-->
<!-- <dependency>-->
<!-- <groupId>io.opentelemetry.instrumentation</groupId>-->
<!-- <artifactId>opentelemetry-spring-boot-starter</artifactId>-->
<!-- <version>2.20.1</version>-->
<!-- </dependency>-->


</dependencies>

<dependencyManagement>
Expand Down
2 changes: 2 additions & 0 deletions postgres-init/init-multiple-dbs.sql
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@ CREATE DATABASE "ECommerce-Order-Service";
CREATE DATABASE "ECommerce-Product-Service";
CREATE DATABASE "ECommerce-Inventory-Service";
CREATE DATABASE "ECommerce-Notification-Service";
CREATE DATABASE "ECommerce-User-Service";

-- Grant all privileges on the databases to the postgres user
GRANT ALL PRIVILEGES ON DATABASE "ECommerce-Order-Service" TO postgres;
GRANT ALL PRIVILEGES ON DATABASE "ECommerce-Product-Service" TO postgres;
GRANT ALL PRIVILEGES ON DATABASE "ECommerce-Inventory-Service" TO postgres;
GRANT ALL PRIVILEGES ON DATABASE "ECommerce-Notification-Service" TO postgres;
GRANT ALL PRIVILEGES ON DATABASE "ECommerce-User-Service" TO postgres;

-- print a message to indicate that the databases have been created
-- sql dialect is not configured statement can be ignored or just click use PostgreSQL
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ void testAddProductSuccess() throws Exception {
new BigDecimal("100.0"),
100,
"Category 1",
100, //available stock, should now be same as product quantity
100, //available stock should now be the same as product quantity
LocalDate.now().plusDays(30),//expiry date
LocalDate.of(2024, 10, 10),//manufactured date
LocalDate.of(2026, 9, 5)));//updated date
Expand Down Expand Up @@ -235,7 +235,7 @@ void testAddProductSuccessWithInventory() throws Exception {
new BigDecimal("100.0"),
100,
"Category 1",
100, //available stock, should now be same as product quantity
100, //available stock should now be the same as product quantity
LocalDate.now().plusDays(30),
LocalDate.of(2024, 10, 10),//manufactured date
LocalDate.of(2026, 9, 5)));//updated date
Expand Down Expand Up @@ -279,7 +279,7 @@ void testAddProductSuccessWithExternalizedService() throws Exception {
new BigDecimal("100.0"),
100,
"Category 1",
100, //available stock, should now be same as product quantity
100, //available stock should now be the same as product quantity
LocalDate.now().plusDays(30),//expiry date
LocalDate.of(2024, 10, 10),//manufactured date
LocalDate.of(2026, 9, 5)));//updated date
Expand Down
2 changes: 0 additions & 2 deletions product-service/src/test/resources/application-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,8 @@ spring:
username: postgres
password: postgres
hikari:

max-lifetime: 300000
connection-timeout: 15000

validation-timeout: 3000

jpa:
Expand Down
36 changes: 36 additions & 0 deletions security/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.4.2</version>
<relativePath/>
</parent>

<groupId>com.tjtechy</groupId>
<artifactId>security</artifactId>
<version>0.0.1</version>
<packaging>jar</packaging> <!-- ✅ package as jar-->
<name>security</name>
<description>Security Module for ECommerce Microservices</description>

<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
</properties>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
</dependency>
</dependencies>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/**
* Copyright © 2025
*
* @Author = TJTechy (Tajudeen Busari)
* @Version = 1.0
* This file is part of EcommerceMicroservices module of the Ecommerce Microservices project.
*/

package com.tjtechy.security.config;

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.reactive.EnableWebFluxSecurity;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

import org.springframework.security.web.server.SecurityWebFilterChain;

@Configuration
@EnableWebFluxSecurity
public class SecurityConfiguration {
/**
* Password encoder bean using BCrypt
* @return PasswordEncoder
* note: BCrypt is a strong hashing algorithm that is widely used for securely storing passwords.
* This bean is needed when using the PasswordEncoder interface in the application.
*/
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}

/**
* Security filter chain configuration
* Once there is a spring security dependency, by default, all endpoints are secured.
* So make a state change like a POST, PUT, DELETE request to any endpoint will require CSRF token.
* For simplicity, we are disabling CSRF here.
* @param http
* @return
* @throws Exception
*/
@Bean
public SecurityWebFilterChain securityFilterChain(ServerHttpSecurity http) throws Exception {
return http
.csrf(ServerHttpSecurity.CsrfSpec::disable)
.authorizeExchange(exchanges -> exchanges
.pathMatchers("/api/v1/user/register").permitAll()
.anyExchange()
.permitAll()
)
.build();
}
}
8 changes: 8 additions & 0 deletions system/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,14 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-actuator</artifactId>
</dependency>
</dependencies>


Expand Down
Binary file modified system/target/system-0.0.1.jar
Binary file not shown.
3 changes: 3 additions & 0 deletions user-service/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,6 @@ build/

### VS Code ###
.vscode/

##ignore log files
*.log
44 changes: 44 additions & 0 deletions user-service/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
The user-service module is responsible for managing user-related operations within the application.
It provides functionalities such as user registration, authentication, profile management, and password recovery.
It is based on Reactive webflux framework to handle asynchronous data streams efficiently, so the
dependencies are designed accordingly and are different from traditional Spring MVC based modules (like inventory-service etc.).
When the application starts, it does not automatically create DB TABLE because it does not use the spring.jpa.hibernate.ddl-auto property.
You need to create the necessary tables manually in the database before running the application or use a database migration tool like Flyway
or Liquibase to manage your database schema.
----------------------------------------------------------------------------------------------
OPTION1: Manually create the necessary tables in the database before running the application.
OPTION2: Use a database migration tool like Flyway or Liquibase to manage your database schema
add migration scripts in, for example:
**src/main/resources/db/migration folder**.
V1__create_users_table.sql
Flyway runs on startup (blocking JDBC) and ensures that table exits, works with reactive R2DBC.
SAMPLE CONTENT:
--------------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS users (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
username VARCHAR(50) NOT NULL UNIQUE,
email VARCHAR(100) NOT NULL,
password VARCHAR(255) NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT now(),
updated_at TIMESTAMP NOT NULL DEFAULT now()
);

-- Optional: trigger to update 'updated_at' on row update
CREATE OR REPLACE FUNCTION update_updated_at_column()
RETURNS TRIGGER AS $$
BEGIN
NEW.updated_at = now();
RETURN NEW;
END;
$$ language 'plpgsql';

CREATE TRIGGER update_users_updated_at
BEFORE UPDATE ON users
FOR EACH ROW
EXECUTE FUNCTION update_updated_at_column();
-----------------------------------------------------------------------------------------------------------------



it is advisable not to make directly changes in the .sql scripts else it may lead to inconsistencies in the database schema management.
In this case, you will have to delete the database and re-create it again to ensure that the migration scripts are applied correctly from scratch.
Loading