Notes

My latest writings


Monday, October 24, 2016

Java/J2ee Must Read - Interview Topics

Core Java:

OOPS

  •     Abstraction
  •     Encapsulation
  •     Polymorphism
  •     Inheritance

Overloading, Overriding

 

Exceptions

  •     Checked & Un-Checked exception
  •     Customizing Exception
  •     Exception chaining and propagation

Enum

  •     General concepts
  •     How to create and use

Threading

  •     Basics
  •     Thread vs Process
  •     Life Cycle
  •     Interrupting Threads
  •     Thread pool concept
  •     Concurrency (Good to have)
  •     Executor service

Collections & Maps

  •     ArrayList, LinkedList with code examples
  •     HashMap, Hashtable, ConcurrentMap detailed implementation knowledge
  •     Hash code, equals concepts
  •     Sorting collection & Maps,
  •     Searching elements in Collection and Maps
  •     Comparator/Comparable utilization

Inner classes

  •     Types of inner classes
  •     Difference with others

Generics

 

Design Patterns

  •     Singleton, factory, builder
  •     Adapter, Proxy, Facade
  •     Strategy, Observer, Chain of responsibility

Data structures

  •     Trees, Stack, Queue, Linked List

More...

  •     Arrays based programs
  •     Serialization vs Externalization
  •     Programs : like Singleton,Mutable class, Prime num, Febinnocii series, Sorting techniques, Hashmap implementation, String based programs,
  •     Object class methods with examples

Note: Features of all the versions Java 5, 6, 7 and 8



Advanced Java:

JDBC:

  •     Steps to write basic JDBC program
  •     Types of JDBC Drivers
  •     Difference b/w Statement, PreparedStatement, CallableStatemnt
  •     Result Sets
  •     Stored Procedures, Batch Processing
  •     Different interfaces used in JDBC program

Servlets:

  •     Lifecyle
  •     Request dispatcher
  •     ServletContext vs ServletConfig
  •     Different Scopes
  •     Session Tracking Mechanisms

JSP:

  •     Implicit objects
  •     Flow of excecution
  •     Session Tracking, Cookies
  •     JSTL
  •     Custom jsp tags
  •     Different types of tags available in JSP like Directives, Actions, etc.

Hibernate:

  •     What is ORM
  •     Hibernate object lifecycle
  •     Single row operations like get() vs load()
  •     Eager loading vs Lazy loading
  •     Annotations
  •     All the interfaces using in Hibernate programs like Session, SessionFactory, Transaction.. etc
  •     Cache like first level and second level cache
  •     Different types of mappings
  •     Hibernate features
  •     Difference b/w SQL, HQL, Criteria API, Native SQL

Spring:

  •     IOC, Spring Core
  •     Dependency Injection (DI) like Setter, Constructor, Interface
  •     Spring Bean Lifecycle
  •     Spring MVC flow of execution
  •     Autowiring
  •     Different Scopes
  •     Annotations
  •     AOP concepts in depth
  •     RESTful Webservices
  •     Transaction Management
  •     Spring integration with different frameworks like Hibernate, JSF, Tiles, Log4j, and etc.
  •     Spring Security


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

Monday, December 3, 2018

Best tips to be a Better Java Developer


If you are a Java developer in early phases of your career, here are some concepts you should read about and learn to be an outstanding Java developer.

All books have been written about these concepts. We will just summarise them here and encourage you to find and read more about them.

1. Thread Safety
All web-applications are multi-threaded applications. If you didn’t know, read about how application containers e.g. Tomcat start a new thread or pick one from a thread pool, to render a new web request. Thread safety is about ensuring access to shared resources is serializable. The most common thread safety mistake? Declaring a private field on a singleton class in your application which is changed by multiple threads.

2. Functional Programming
This came late to Java, specifically in version 1.8. But you should learn and use Streams & Lambda functions in your programs. They make for readable, elegant & concise code, often with improved performance.

3. Thread Local variables
Thread safety was about accessing shared variables safely. Thread local allows you to do just that. Think of them as a HashMap of variables by thread id. However, handle their initialization and clean up with care, especially when using thread pools or you can get into thread safety issues and memory leaks.

4. Mapped Diagnostic Contexts in Logging
Underlying, this works as a thread local variable. But you don’t have to worry about it because most logging frameworks will support it out of the box. The idea is to start and end contexts when logging messages. For instance, at the entry of a request, you can log the API URL and user id, so the logs inside would always carry that context.

5. Understand Classpath
It seems easy. But can cause problems or be the reason for some weird effects such as – Why does this work on my local but not on production? It may be because of class-path ordering wherein a production application container loaders an older jar from a shared class-path.

6. Class-path & Class Loaders
Class loaders work as a hierarchy. Learn about class-loaders that come with running an application in tomcat. Find if the same class can be loaded twice in memory and how.

7. Hot Loading
Did you know JVM supports hot reloading of Java classes? You change the code and then don’t have to re-compile everything and restart the application. Just the class changed is recompiled and its in-memory byte-code is updated. Find which cases this can happen and configure it in your development environment if you haven’t already.

8. Dependency Injection
You don’t call me. I call you. That’s inversion of control and the principle behind dependency injection, popularised by Spring Framework. You already knew it, but do you know the alternative to dependency injection? Learn and understand why dependency injection is better and leads to more extensible and testable code.

9. Properties
You know about properties files. But what are the principles to decide if something should be a system property, an environment variable or a command line argument? The hint is in runtime i.e. when does the property become available and is provided. Nevertheless, you should know how to accept and use each and override when needed e.g. in a test environment.

10. Fat Jar Deployment
Most application frameworks, spring boot comes to mind, have an embedded container deployment mode. That is a DevOps friendly way to deploy on the cloud, instead of tweaking application container settings. Even if there is an operations team managing deployment for you, learn it as its the way forward.

11. ORM & Persistence
ORM (JPA & Hibernate) give you convenience and power. And often people shoot themselves in their leg with it. Learn to use them responsibly and without performance impact. Transaction boundaries, Lazy vs Eager fetching, different types of caching and how to debug performance. But most importantly, when not to use an ORM and just write a SQL query. Hint – when the amount of data is large or is distributed in too many tables.

12. Fault Tolerance and Isolation
Let’s say one of your application API calls another rest API. If the other rest API becomes slow, will your application go down? It will. Because of the slow API, all threads will be consumed and your application will become unresponsive. So design it to be fault tolerant with proper timeouts. You can make it more robust by using Resilience4j that allows setting up retry & fallback, circuit breakers, rate limiters and more.

13. Deployment and run-time environment
Do you know how your application works in production? Whether its a Paas like Heroku or Iaas like AWS, you should know the memory available, available CPUs, disk latency, network latency within different components to design a performant application.

14. Monitoring
Will you know if some API in your application is slow? What are the key performance indicators you should monitor? You can use an APM provider like New Relic, or build your own health checks and metrics using spring boot actuator.

15. Build Lifecycle and Dependency Management
Can you configure a new java project by hand using Maven or Gradle? Setup development and production environment configuration, create build lifecycles tasks to run checkstyle or find bugs, create build commands to run test-cases and generate coverage and so on.

16. Debugging Setup
Many developers do not know how to set this up.  This is a must when running test-cases, but JVM also allows remote debugging by opening up a port your IDE can connect to. Learn how to set it up and you will be finding bugs 10 times faster than your teammates who don’t have it set up.

17. Know your IDE
Whether its Eclipse or IntelliJ, shame on you if you can’t set up a new or existing project in your IDE. The ideas IDE setup will have static code analyser, run and debug test environment, can connect to debug a running JVM with has libraries source code also downloaded. A good workman knows their tools.

18. Learn to Refactor SensiblyMost code is not perfect. Learn to improve some of it as you go, but not all of it in one go. Unlike the others, this one will take time and experience to master. 
Start today.

©hashedin.com

Friday, March 4, 2016

Java Error Handling Mechanism !!!

Errors: 

When a dynamic linking failure or some other “hard” failure in the virtual machine occurs, the virtual machine throws an Error. Typical Java programs should not catch Errors. In addition, it’s unlikely that typical Java programs will ever throw Errors either.

Exceptions: 

Most programs throw and catch objects that derive from the Exception class. Exceptions indicate that a problem occurred but that the problem is not a serious JVM problem. An Exception class has many subclasses. These descendants indicate various types of exceptions that can occur. For example, NegativeArraySizeException indicates that a program attempted to create an array with a negative size. One exception subclass has special meaning in the Java language: RuntimeException.

All the exceptions except RuntimeException are compiler checked exceptions. If a method is capable of throwing a checked exception it must declare it in its method header or handle it in a try/catch block. Failure to do so raises a compiler error. So checked exceptions can, at compile time, greatly reduce the occurrence of unhandled exceptions surfacing at runtime in a given application at the expense of requiring large throws declarations and encouraging use of poorly constructed try/catch blocks. Checked exceptions are present in other languages like C++, C#, and Python.


Runtime Exceptions (unchecked exception):

A RuntimeException class represents exceptions that occur within the Java virtual machine (during runtime). An example of a runtime exception is NullPointerException. The cost of checking for the runtime exception often outweighs the benefit of catching it. Attempting to catch or specify all of them all the time would make your code unreadable and unmaintainable. The compiler allows runtime exceptions to go uncaught and unspecified. If you like, you can catch these exceptions just like other exceptions. However, you do not have to declare it in your “throws" clause or catch it in your catch clause. In addition, you can create your own RuntimeException subclasses and this approach is probably preferred at times because checked exceptions can complicate method signatures and can be difficult to follow.

What are the exception handling best practices: 

Q. Why is it not advisable to catch type “Exception”?

Exception handling in Java is polymorphic in nature. For example if you catch type Exception in your code then it can catch or throw its descendent types like IOException as well. So if you catch the type Exception before the type IOException then the type Exception block will catch the entire exceptions and type IOException block is never reached. In order to catch the type IOException and handle it differently to type Exception, IOException should be caught first (remember that you can’t have a bigger basket above a smaller basket).


The diagram above is an example for illustration only. In practice it is not recommended to catch type
“Exception”. We should only catch specific subtypes of the Exception class. Having a bigger basket (i.e. Exception) will hide or cause problems. Since the RunTimeException is a subtype of Exception, catching the type Exception will catch all the run time exceptions (like NullPointerException, ArrayIndexOutOfBoundsException) aswell.

Example: The FileNotFoundException is extended (i.e. inherited) from the IOException. So (subclasses have to be caught first) FileNotFoundException (small basket) should be caught before IOException (big basket).

Q. Why should you throw an exception early?

The exception stack trace helps you pinpoint where an exception occurred by showing you the exact sequence of method calls that lead to the exception. By throwing your exception early, the exception becomes more accurate and more specific. Avoid suppressing or ignoring exceptions. Also avoid using exceptions just to get a flow control.

Instead of:
// assume this line throws an exception because filename == null.
InputStream in = new FileInputStream(fileName);

Use the following code because you get a more accurate stack trace:

if(filename == null) {
throw new IllegalArgumentException(“file name is null”);
}
InputStream in = new FileInputStream(fileName);

Q. Why should you catch a checked exception late in a catch {} block?

You should not try to catch the exception before your program can handle it in an appropriate manner. The natural tendency when a compiler complains about a checked exception is to catch it so that the compiler stops reporting errors. It is a bad practice to sweep the exceptions under the carpet by catching it and not doing anything with it.

The best practice is to catch the exception at the appropriate layer (e.g. an exception thrown at an integration layer can be caught at a presentation layer in a catch {} block), where your program can either meaningfully recover from the exception and continue to execute or log the exception only once in detail, so that user can identify the cause of the exception. 

Q. When should you use a checked exception and when should you use an unchecked exception?

Due to heavy use of checked exceptions and minimal use of unchecked exceptions, there has been a hot debate in the Java community regarding true value of checked exceptions. Use checked exceptions when the client code can take some useful recovery action based on information in exception. Use unchecked exception when client code cannot do anything. For example Convert your SQLException into another checked exception if the client code can recover from it. Convert your SQLException into an unchecked (i.e. RuntimeException) exception, if the client code can not recover from it. (Note: Hibernate 3 & Spring uses RuntimeExceptions prevalently).

Important: throw an exception early and catch an exception late but do not sweep an exception under the carpet by catching it and not doing anything with it. This will hide problems and it will be hard to debug and fix. 

A note on key words for error handling:

throw / throws – used to pass an exception to the method that called it.
try – block of code will be tried but may cause an exception.
catch – declares the block of code, which handles the exception.
finally – block of code, which is always executed (except System.exit(0) call) no matter what program flow, occurs when dealing with an exception.
assert – Evaluates a conditional expression to verify the programmer’s assumption.

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