Notes

My latest writings


Friday, June 26, 2020

Git Tips - How to know the remote repository URL of your local Branch

If you want only the remote URL, or referential integrity has been broken: 
git config --get remote.origin.url 

If you require full output or referential integrity is intact: 
git remote show origin 
When using git clone (from GitHub, or any source repository for that matter) the default name for the source of the clone is "origin". Using git remote show will display the information about this remote name. The first few lines should show:
C:\Users\jaredpar\VsVim> git remote show origin
* remote origin
Fetch URL: git@github.com:jaredpar/VsVim.git
Push URL: git@github.com:jaredpar/VsVim.git 
HEAD branch: master
Remote branches:

If you want to use the value in the script, you would use the first command listed in this answer.

Sunday, July 7, 2024

Twelve-Factor App methodology applying the Developing a Microservice with Spring Boot


12-Factor App Methodology

The 12-Factor App methodology is a set of best practices for building modern web-based applications. It provides guidelines for creating scalable, maintainable, and portable applications that can be deployed across various environments. Here are the twelve factors with examples:

1. Codebase

One codebase tracked in revision control, many deploys. Example: A single Git repository for your e-commerce application that includes all code for various environments (development, staging, production). Branches can be used for feature development and bug fixes.
git clone https://github.com/username/ecommerce-app.git

2. Dependencies

Explicitly declare and isolate dependencies. Example: Using pom.xml in a Maven-based Java project to declare dependencies.
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <version>2.5.4</version>
</dependency>

3. Config

Store config in the environment. Example: Using environment variables to manage configuration.
# application.properties
spring.datasource.url=${DATABASE_URL}
spring.datasource.username=${DATABASE_USERNAME}
spring.datasource.password=${DATABASE_PASSWORD}
Setting environment variables:
export DATABASE_URL=jdbc:mysql://localhost:3306/mydb
export DATABASE_USERNAME=root
export DATABASE_PASSWORD=secret

4. Backing Services

Treat backing services as attached resources. Example: Configuring a database connection in Spring Boot.
spring.datasource.url=${DATABASE_URL}
This allows you to switch databases easily without changing the code.

5. Build, Release, Run

Strictly separate build and run stages. Example: Using Jenkins to manage build and release pipelines. Build stage: Compile the code, run tests, and package the application.
mvn clean package
Release stage: Combine the build with environment-specific configuration.
java -jar target/myapp.jar --spring.config.location=/path/to/config/
Run stage: Execute the application.
java -jar target/myapp.jar

6. Processes

Execute the app as one or more stateless processes. Example: Running a Spring Boot application as a stateless process.
java -jar target/myapp.jar
State (like session data) is stored in external services like Redis.

7. Port Binding

Export services via port binding. Example: Configuring a Spring Boot application to run on a specific port.
server.port=8080
Accessing the application:
curl http://localhost:8080

8. Concurrency

Scale out via the process model. Example: Running multiple instances of a Spring Boot application using Docker.
docker run -d -p 8080:8080 myapp:latest
docker run -d -p 8081:8080 myapp:latest
Load balancing these instances using Nginx or another load balancer.

9. Disposability

Maximize robustness with fast startup and graceful shutdown. Example: Implementing graceful shutdown in Spring Boot.
@Bean
public ServletWebServerFactory servletContainer() {
    TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory();
    tomcat.addConnectorCustomizers((TomcatConnectorCustomizer) connector -> {
        connector.setProperty("server.shutdown.graceful", "true");
    });
    return tomcat;
}

10. Dev/Prod Parity

Keep development, staging, and production as similar as possible. Example: Using Docker to ensure the same environment in all stages.
docker build -t myapp:latest .
docker run -e DATABASE_URL=jdbc:mysql://localhost:3306/mydb myapp:latest

11. Logs

Treat logs as event streams. Example: Using a logging framework like Logback to write logs to stdout.
<configuration>
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss} - %msg%n</pattern>
        </encoder>
    </appender>
    <root level="info">
        <appender-ref ref="STDOUT" />
    </root>
</configuration>

12. Admin Processes

Run admin/management tasks as one-off processes. Example: Running a database migration using Flyway in a Spring Boot application.
java -cp myapp.jar org.flywaydb.core.Flyway migrate


Developing a Microservice with Spring Boot: Applying the Twelve-Factor Methodology

Developing a microservice using Spring Boot involves several steps, from setting up your development environment to implementing features and ensuring the application adheres to best practices, including the twelve-factor methodology. Here's a step-by-step guide:

Step 1: Set Up Your Development Environment

  1. Install JDK: Ensure you have Java Development Kit (JDK) installed. Spring Boot typically requires JDK 8 or later.
  2. Install an IDE: Use an Integrated Development Environment (IDE) like IntelliJ IDEA, Eclipse, or Visual Studio Code.
  3. Install Maven/Gradle: These build tools help manage project dependencies and build lifecycle. Maven is commonly used with Spring Boot.

Step 2: Create a Spring Boot Application

  1. Initialize the Project:
    • Use Spring Initializr (https://start.spring.io/) to generate a basic Spring Boot project. Select dependencies such as Spring Web, Spring Data JPA, and any database connector (e.g., H2, MySQL).
    • Download the generated project and import it into your IDE.
  2. Structure Your Project: A typical Spring Boot project follows the Maven structure:
    ├── src
    │   ├── main
    │   │   ├── java
    │   │   │   └── com
    │   │   │       └── example
    │   │   │           └── mymicroservice
    │   │   │               ├── MyMicroserviceApplication.java
    │   │   │               ├── controller
    │   │   │               ├── service
    │   │   │               └── repository
    │   │   ├── resources
    │   │       └── application.properties
    │   └── test

Step 3: Develop Your Microservice

  1. Define Models: Create Java classes representing your data model.
    package com.example.mymicroservice.model;
    
    import javax.persistence.Entity;
    import javax.persistence.GeneratedValue;
    import javax.persistence.GenerationType;
    import javax.persistence.Id;
    
    @Entity
    public class Product {
        @Id
        @GeneratedValue(strategy = GenerationType.AUTO)
        private Long id;
        private String name;
        private Double price;
    
        // getters and setters
    }
  2. Create Repositories: Use Spring Data JPA to handle database interactions.
    package com.example.mymicroservice.repository;
    
    import com.example.mymicroservice.model.Product;
    import org.springframework.data.jpa.repository.JpaRepository;
    
    public interface ProductRepository extends JpaRepository<Product, Long> {
    }
  3. Implement Services: Write business logic in service classes.
    package com.example.mymicroservice.service;
    
    import com.example.mymicroservice.model.Product;
    import com.example.mymicroservice.repository.ProductRepository;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    import java.util.List;
    
    @Service
    public class ProductService {
    
        @Autowired
        private ProductRepository productRepository;
    
        public List getAllProducts() {
            return productRepository.findAll();
        }
    
        public Product getProductById(Long id) {
            return productRepository.findById(id).orElse(null);
        }
    
        public Product saveProduct(Product product) {
            return productRepository.save(product);
        }
    
        public void deleteProduct(Long id) {
            productRepository.deleteById(id);
        }
    }
  4. Create Controllers: Define REST endpoints to handle HTTP requests.
    package com.example.mymicroservice.controller;
    
    import com.example.mymicroservice.model.Product;
    import com.example.mymicroservice.service.ProductService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.*;
    
    import java.util.List;
    
    @RestController
    @RequestMapping("/products")
    public class ProductController {
    
        @Autowired
        private ProductService productService;
    
        @GetMapping
        public List getAllProducts() {
            return productService.getAllProducts();
        }
    
        @GetMapping("/{id}")
        public Product getProductById(@PathVariable Long id) {
            return productService.getProductById(id);
        }
    
        @PostMapping
        public Product createProduct(@RequestBody Product product) {
            return productService.saveProduct(product);
        }
    
        @DeleteMapping("/{id}")
        public void deleteProduct(@PathVariable Long id) {
            productService.deleteProduct(id);
        }
    }

Step 4: Apply the Twelve-Factor Methodology

  1. Codebase: One codebase tracked in version control, many deploys. Use a version control system like Git.
  2. Dependencies: Explicitly declare and isolate dependencies. Manage dependencies using Maven or Gradle.
  3. Config: Store config in the environment.
    server.port=8080
    spring.datasource.url=jdbc:mysql://localhost:3306/mydb
    spring.datasource.username=root
    spring.datasource.password=secret
  4. Backing Services: Treat backing services as attached resources. Configure external resources (e.g., databases, message brokers) using environment variables.
  5. Build, Release, Run: Strictly separate build and run stages. Use CI/CD pipelines to automate the build and deployment process.
  6. Processes: Execute the app as one or more stateless processes. Ensure the application is stateless, storing any needed state in a database or external service.
  7. Port Binding: Export services via port binding. Spring Boot applications bind to a port and serve requests.
  8. Concurrency: Scale out via the process model. Scale the application horizontally by running multiple instances.
  9. Disposability: Maximize robustness with fast startup and graceful shutdown. Implement graceful shutdown and ensure the application can handle interruptions.
  10. Dev/Prod Parity: Keep development, staging, and production as similar as possible. Use Docker or similar technologies to ensure consistency across environments.
  11. Logs: Treat logs as event streams. Use a logging framework like Logback and externalize logs to a centralized logging system.
  12. Admin Processes: Run admin/management tasks as one-off processes. Use tools like Spring Boot Actuator for management and monitoring.

Step 5: Testing and Deployment

  1. Write Tests: Implement unit tests, integration tests, and end-to-end tests.
    package com.example.mymicroservice;
    
    import com.example.mymicroservice.model.Product;
    import com.example.mymicroservice.service.ProductService;
    import org.junit.jupiter.api.Test;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    
    import static org.junit.jupiter.api.Assertions.assertNotNull;
    
    @SpringBootTest
    class MyMicroserviceApplicationTests {
    
        @Autowired
        private ProductService productService;
    
        @Test
        void testGetAllProducts() {
            assertNotNull(productService.getAllProducts());
        }
    }
  2. Package and Deploy: Package the application as a JAR or WAR file and deploy it to your server or cloud platform.
    mvn clean package

Step 6: Monitoring and Maintenance

  1. Monitoring: Use tools like Prometheus and Grafana for monitoring application performance.
  2. Logging: Implement centralized logging using tools like ELK Stack (Elasticsearch, Logstash, Kibana).
  3. Security: Regularly update dependencies and use security practices like OAuth2 for authentication and authorization.
By following these steps and adhering to the twelve-factor methodology, you can develop a robust, scalable, and maintainable microservice using Spring Boot.

Friday, July 5, 2024

Building a E-commerce Microservices Architecture with Spring Boot and Spring Cloud


In this article, we will walk through the creation of a scalable microservices architecture for an e-commerce application using Java Spring Boot and Spring Cloud. The architecture includes several services such as Config Server, Eureka Server, API Gateway, Auth Service, Order Service, Inventory Service, and Notification Service with Kafka.

Project Structure

The project is organized into the following structure:
ecommerce-microservices
├── config-server
├── eureka-server
├── api-gateway
├── auth-service
├── order-service
├── inventory-service
├── notification-service
├── docker-compose.yml (optional)
└── README.md
        

Config Server

The Config Server manages external configurations for all microservices.
config-server/pom.xml
<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>
    <groupId>com.example</groupId>
    <artifactId>config-server</artifactId>
    <version>1.0.0</version>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-config-server</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>
        
config-server/src/main/resources/application.yml
server:
  port: 8888

spring:
  cloud:
    config:
      server:
        git:
          uri: https://github.com/your-repo/config-repo
        
config-server/src/main/java/com/example/configserver/ConfigServerApplication.java
package com.example.configserver;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.config.server.EnableConfigServer;

@SpringBootApplication
@EnableConfigServer
public class ConfigServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(ConfigServerApplication.class, args);
    }
}
        

Why Use Config Server?

Config Server provides a centralized place to manage external properties for applications across all environments. It uses a Git repository to store configuration files, making it easy to version and manage configurations.

How to Deploy and Run Config Server

To deploy the Config Server, ensure you have a Git repository with configuration files. Then, run the application using:
mvn spring-boot:run
This will start the Config Server on port 8888.

Eureka Server

The Eureka Server is a service registry for locating services.
eureka-server/pom.xml
<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>
    <groupId>com.example</groupId>
    <artifactId>eureka-server</artifactId>
    <version>1.0.0</version>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>
        
eureka-server/src/main/resources/application.yml
server:
  port: 8761

eureka:
  client:
    register-with-eureka: false
    fetch-registry: false
  instance:
    hostname: localhost
        
eureka-server/src/main/java/com/example/eurekaserver/EurekaServerApplication.java
package com.example.eurekaserver;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(EurekaServerApplication.class, args);
    }
}
        

Why Use Eureka Server?

Eureka Server acts as a discovery server for registering and locating microservices. This helps in load balancing and makes it easier to scale services dynamically.

How to Deploy and Run Eureka Server

To deploy the Eureka Server, run the application using:
mvn spring-boot:run
This will start the Eureka Server on port 8761.

API Gateway

The API Gateway routes requests to appropriate services.
api-gateway/pom.xml
<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>
    <groupId>com.example</groupId>
    <artifactId>api-gateway</artifactId>
    <version>1.0.0</version>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.security.oauth.boot</groupId>
            <artifactId>spring-security-oauth2-autoconfigure</artifactId>
            <version>2.2.5.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>
        
api-gateway/src/main/resources/application.yml
server:
  port: 8080

spring:
  application:
    name: api-gateway

eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/
  instance:
    prefer-ip-address: true

spring:
  security:
    oauth2:
      resourceserver:
        jwt:
          jwk-set-uri: http://localhost:9000/oauth2/default/.well-known/jwks.json
        
api-gateway/src/main/java/com/example/apigateway/ApiGatewayApplication.java
package com.example.apigateway;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;

@SpringBootApplication
@EnableEurekaClient
@EnableResourceServer
public class ApiGatewayApplication {
    public static void main(String[] args) {
        SpringApplication.run(ApiGatewayApplication.class, args);
    }
}
        
api-gateway/src/main/java/com/example/apigateway/config/SecurityConfig.java
package com.example.apigateway.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;

@Configuration
@EnableResourceServer
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
            .antMatchers("/h2-console/**").permitAll()
            .anyRequest().authenticated()
            .and()
            .csrf().disable()
            .headers().frameOptions().disable();
    }
}
        

Why Use API Gateway?

The API Gateway handles requests by routing them to the appropriate microservice. It provides a single entry point for the client and helps in securing and managing requests efficiently.

How to Deploy and Run API Gateway

To deploy the API Gateway, run the application using:
mvn spring-boot:run
This will start the API Gateway on port 8080.

Auth Service

The Auth Service handles authentication and authorization using OAuth2.
auth-service/pom.xml
<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>
    <groupId>com.example</groupId>
    <artifactId>auth-service</artifactId>
    <version>1.0.0</version>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-oauth2</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>
        
auth-service/src/main/resources/application.yml
server:
  port: 9000

spring:
  application:
    name: auth-service

eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/
  instance:
    prefer-ip-address: true

spring:
  datasource:
    url: jdbc:h2:mem:testdb
    driverClassName: org.h2.Driver
    username: sa
    password: password

spring:
  h2:
    console:
      enabled: true

spring:
  jpa:
    hibernate:
      ddl-auto: update
    database-platform: org.hibernate.dialect.H2Dialect
        
auth-service/src/main/java/com/example/authservice/AuthServiceApplication.java
package com.example.authservice;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;

@SpringBootApplication
@EnableEurekaClient
@EnableAuthorizationServer
public class AuthServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(AuthServiceApplication.class, args);
    }
}
        
auth-service/src/main/java/com/example/authservice/config/AuthorizationServerConfig.java
package com.example.authservice.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;

@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {

    @Autowired
    private AuthenticationManager authenticationManager;

    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        security.tokenKeyAccess("permitAll()")
                .checkTokenAccess("isAuthenticated()");
    }

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory()
                .withClient("client-id")
                .secret("{noop}client-secret")
                .authorizedGrantTypes("password", "authorization_code", "refresh_token")
                .scopes("read", "write")
                .accessTokenValiditySeconds(3600)
                .refreshTokenValiditySeconds(36000);
    }

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.authenticationManager(authenticationManager);
    }
}
        
auth-service/src/main/java/com/example/authservice/config/WebSecurityConfig.java
package com.example.authservice.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Bean
    @Override
    protected AuthenticationManager authenticationManager() throws Exception {
        return super.authenticationManager();
    }

    @Bean
    @Override
    protected UserDetailsService userDetailsService() {
        InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
        manager.createUser(User.withDefaultPasswordEncoder()
                .username("user")
                .password("password")
                .roles("USER")
                .build());
        return manager;
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
            .anyRequest()
            .authenticated()
            .and()
            .formLogin()
            .permitAll();
    }
}
        

Why Use Auth Service?

The Auth Service handles user authentication and authorization using OAuth2. It provides secure access to resources by issuing JWT tokens.

How to Deploy and Run Auth Service

To deploy the Auth Service, run the application using:
mvn spring-boot:run
This will start the Auth Service on port 9000.

Order Service

The Order Service manages orders within the e-commerce application.
order-service/pom.xml
<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>
    <groupId>com.example</groupId>
    <artifactId>order-service</artifactId>
    <version>1.0.0</version>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.kafka</groupId>
            <artifactId>spring-kafka</artifactId>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>
        
order-service/src/main/resources/application.yml
server:
  port: 9001

spring:
  application:
    name: order-service

eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/
  instance:
    prefer-ip-address: true

spring:
  datasource:
    url: jdbc:h2:mem:testdb
    driverClassName: org.h2.Driver
    username: sa
    password: password

spring:
  h2:
    console:
      enabled: true

spring:
  jpa:
    hibernate:
      ddl-auto: update
    database-platform: org.hibernate.dialect.H2Dialect

spring:
  kafka:
    bootstrap-servers: localhost:9092
    consumer:
      group-id: order-group
        
order-service/src/main/java/com/example/orderservice/OrderServiceApplication.java
package com.example.orderservice;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;

@SpringBootApplication
@EnableEurekaClient
public class OrderServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(OrderServiceApplication.class, args);
    }
}
        
order-service/src/main/java/com/example/orderservice/model/Order.java
package com.example.orderservice.model;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

@Entity
public class Order {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String product;
    private int quantity;
    private double price;

    // Getters and setters
}
        
order-service/src/main/java/com/example/orderservice/repository/OrderRepository.java
package com.example.orderservice.repository;

import com.example.orderservice.model.Order;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface OrderRepository extends JpaRepository<Order, Long> {
}
        
order-service/src/main/java/com/example/orderservice/controller/OrderController.java
package com.example.orderservice.controller;

import com.example.orderservice.model.Order;
import com.example.orderservice.repository.OrderRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/orders")
public class OrderController {

    @Autowired
    private OrderRepository orderRepository;

    @Autowired
    private KafkaTemplate<String, String> kafkaTemplate;

    private static final String TOPIC = "order-topic";

    @PostMapping
    public Order createOrder(@RequestBody Order order) {
        Order savedOrder = orderRepository.save(order);
        kafkaTemplate.send(TOPIC, "Order created: " + savedOrder.getId());
        return savedOrder;
    }

    @GetMapping("/{id}")
    public Order getOrder(@PathVariable Long id) {
        return orderRepository.findById(id).orElse(null);
    }
}
        

Why Use Order Service?

The Order Service manages all operations related to orders. It uses Kafka to send notifications whenever an order is created.

How to Deploy and Run Order Service

To deploy the Order Service, run the application using:
mvn spring-boot:run
This will start the Order Service on port 9001.

Inventory Service

The Inventory Service manages product inventory within the e-commerce application.
inventory-service/pom.xml
<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>
    <groupId>com.example</groupId>
    <artifactId>inventory-service</artifactId>
    <version>1.0.0</version>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.kafka</groupId>
            <artifactId>spring-kafka</artifactId>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>
        
inventory-service/src/main/resources/application.yml
server:
  port: 9002

spring:
  application:
    name: inventory-service

eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/
  instance:
    prefer-ip-address: true

spring:
  datasource:
    url: jdbc:h2:mem:testdb
    driverClassName: org.h2.Driver
    username: sa
    password: password

spring:
  h2:
    console:
      enabled: true

spring:
  jpa:
    hibernate:
      ddl-auto: update
    database-platform: org.hibernate.dialect.H2Dialect

spring:
  kafka:
    bootstrap-servers: localhost:9092
    consumer:
      group-id: inventory-group
        
inventory-service/src/main/java/com/example/inventoryservice/InventoryServiceApplication.java
package com.example.inventoryservice;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;

@SpringBootApplication
@EnableEurekaClient
public class InventoryServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(InventoryServiceApplication.class, args);
    }
}
        
inventory-service/src/main/java/com/example/inventoryservice/model/Inventory.java
package com.example.inventoryservice.model;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

@Entity
public class Inventory {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String product;
    private int quantity;

    // Getters and setters
}
        
inventory-service/src/main/java/com/example/inventoryservice/repository/InventoryRepository.java
package com.example.inventoryservice.repository;

import com.example.inventoryservice.model.Inventory;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface InventoryRepository extends JpaRepository<Inventory, Long> {
}
        
inventory-service/src/main/java/com/example/inventoryservice/controller/InventoryController.java
package com.example.inventoryservice.controller;

import com.example.inventoryservice.model.Inventory;
import com.example.inventoryservice.repository.InventoryRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/inventory")
public class InventoryController {

    @Autowired
    private InventoryRepository inventoryRepository;

    @Autowired
    private KafkaTemplate<String, String> kafkaTemplate;

    private static final String TOPIC = "inventory-topic";

    @PostMapping
    public Inventory addInventory(@RequestBody Inventory inventory) {
        Inventory savedInventory = inventoryRepository.save(inventory);
        kafkaTemplate.send(TOPIC, "Inventory added: " + savedInventory.getId());
        return savedInventory;
    }

    @GetMapping("/{id}")
    public Inventory getInventory(@PathVariable Long id) {
        return inventoryRepository.findById(id).orElse(null);
    }
}
        

Why Use Inventory Service?

The Inventory Service manages all operations related to inventory. It uses Kafka to send notifications whenever inventory is updated.

How to Deploy and Run Inventory Service

To deploy the Inventory Service, run the application using:
mvn spring-boot:run
This will start the Inventory Service on port 9002.

Communication Between Services

Microservices communicate using REST APIs and Apache Kafka for asynchronous messaging. Services are registered with Eureka and communicate via Eureka Server.

Testing

Unit and integration tests are implemented using Spring Boot Test.
Example test class:
order-service/src/test/java/com/example/orderservice/OrderServiceApplicationTests.java
package com.example.orderservice;

import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class OrderServiceApplicationTests {

    @Test
    void contextLoads() {
    }

}
        

Directory Structure

Here's the complete directory structure for the project:
ecommerce-microservices/
├── api-gateway/
│   ├── src/main/java/com/example/apigateway/ApiGatewayApplication.java
│   ├── src/main/resources/application.yml
│   └── pom.xml
├── auth-service/
│   ├── src/main/java/com/example/authservice/AuthController.java
│   ├── src/main/java/com/example/authservice/AuthServiceApplication.java
│   ├── src/main/java/com/example/authservice/SecurityConfig.java
│   ├── src/main/java/com/example/authservice/User.java
│   ├── src/main/java/com/example/authservice/UserRepository.java
│   ├── src/main/resources/application.yml
│   └── pom.xml
├── config-server/
│   ├── src/main/java/com/example/configserver/ConfigServerApplication.java
│   ├── src/main/resources/application.yml
│   └── pom.xml
├── eureka-server/
│   ├── src/main/java/com/example/eurekaserver/EurekaServerApplication.java
│   ├── src/main/resources/application.yml
│   └── pom.xml
├── inventory-service/
│   ├── src/main/java/com/example/inventoryservice/InventoryController.java
│   ├── src/main/java/com/example/inventoryservice/Inventory.java
│   ├── src/main/java/com/example/inventoryservice/InventoryRepository.java
│   ├── src/main/java/com/example/inventoryservice/InventoryServiceApplication.java
│   ├── src/main/resources/application.yml
│   └── pom.xml
├── notification-service/
│   ├── src/main/java/com/example/notificationservice/KafkaConsumerConfig.java
│   ├── src/main/java/com/example/notificationservice/KafkaListenerService.java
│   ├── src/main/java/com/example/notificationservice/NotificationServiceApplication.java
│   ├── src/main/resources/application.yml
│   └── pom.xml
├── order-service/
│   ├── src/main/java/com/example/orderservice/OrderController.java
│   ├── src/main/java/com/example/orderservice/Order.java
│   ├── src/main/java/com/example/orderservice/OrderRepository.java
│   ├── src/main/java/com/example/orderservice/OrderServiceApplication.java
│   ├── src/main/resources/application.yml
│   └── pom.xml
├── docker-compose.yml (optional)
└── README.md

Works

What can I do


Branding

Social media Branding is far and away the best technique a company has to boost engagement with its customer base. Even a minimum of involvement, such as making one post a day.

Web Design

Web design is the process of creating websites. It encompasses several different aspects, including webpage layout, content production, and graphic design.

Development

Web Development refers to building, creating, and an maintaining websites. It includes aspects such as web design, web publishing, web programming and database management.

Graphic Design

Graphic design is the process of visual communication and problem-solving through the use of typography, photography, and illustration. The field is considered a subset of visual communication and communication design.

Photography

Photography is the art, application and practice of creating durable images by recording light or other electromagnetic radiation, either electronically by means of an image sensor, or chemically by means of a light-sensitive material such as photographic film.

User Experience

User experience (UX) design is the process design teams use to create products that provide meaningful and relevant experiences to users. This involves the design of the entire process of acquiring and integrating the product, including aspects of branding, design.

Contact

Get in touch with me


Adress/Street

Bangalore, India