Java Microservices: Core Concepts Explained with Examples

 

1. Constructors

Purpose: Initialize objects when created
Key Features:

  • Same name as class

  • No return type

  • Can be overloaded

java
public class ProductService {
    private ProductRepository repo;
    
    // Constructor: Initializes dependencies
    public ProductService(ProductRepository repo) {
        this.repo = repo;  // Dependency Injection
    }
    
    // Overloaded constructor (default repo)
    public ProductService() {
        this.repo = new DefaultProductRepository();
    }
}

2. Getting Data in Services

Common Methods:

  1. Dependency Injection (DI)

  2. Database Repositories

  3. API Clients

Example Service with Data Access:
java
@Service  // Spring stereotype annotation
public class OrderService {
    
    // 1. Dependency Injection
    @Autowired
    private OrderRepository orderRepo;  // Database access
    
    @Autowired
    private PaymentClient paymentClient;  // External service
    
    // 2. Constructor injection (recommended)
    public OrderService(OrderRepository orderRepo, 
                       PaymentClient paymentClient) {
        this.orderRepo = orderRepo;
        this.paymentClient = paymentClient;
    }

    // 3. Business method using data
    public Order processOrder(OrderRequest request) {
        // Get data from database
        Order order = orderRepo.save(new Order(request));
        
        // Get data from external service
        PaymentStatus status = paymentClient.charge(order);
        
        order.setStatus(status);
        return orderRepo.save(order);
    }
}

**3. Methods & Classes in Java

A) Method Types:
TypeExampleUse Case
Instanceproduct.calculateTax()Object-specific operations
StaticMathUtils.round(price)Utility functions
Abstractabstract void validate()Framework hooks
Default (Interface)Logger.log("msg")Interface backward compatibility
B) Class Types:
TypeExampleUse Case
POJOProduct.javaData containers
ServiceOrderService.javaBusiness logic
RepositoryProductRepository.javaDatabase access
ControllerProductController.javaREST endpoint handler
ConfigurationSecurityConfig.javaSpring bean setup
DTO (Data Transfer Object)ProductResponse.javaAPI response structure

4. Complete Microservice Flow Example

java
// 1. DTO Class (Data Transfer Object)
public record ProductResponse(Long id, String name, double price) {}

// 2. Repository Interface (Data Access)
public interface ProductRepository extends JpaRepository<Product, Long> {
    List<Product> findByPriceLessThan(double maxPrice);  // Spring Data method
}

// 3. Service Class (Business Logic)
@Service
public class ProductService {
    private final ProductRepository repo;

    public ProductService(ProductRepository repo) {
        this.repo = repo;
    }

    // Business method
    public List<ProductResponse> getAffordableProducts(double maxPrice) {
        return repo.findByPriceLessThan(maxPrice)
                  .stream()
                  .map(p -> new ProductResponse(p.getId(), p.getName(), p.getPrice()))
                  .toList();
    }
}

// 4. Controller Class (REST API)
@RestController
@RequestMapping("/products")
public class ProductController {
    private final ProductService service;

    public ProductController(ProductService service) {
        this.service = service;
    }

    @GetMapping("/affordable")
    public ResponseEntity<List<ProductResponse>> getAffordable(
            @RequestParam double maxPrice) {
        return ResponseEntity.ok(service.getAffordableProducts(maxPrice));
    }
}

5. Data Flow in Microservices

  1. Client Request:
    GET /products/affordable?maxPrice=100

  2. Controller:

    • Receives HTTP request

    • Extracts maxPrice parameter

    • Calls service method

  3. Service:

    • Contains business logic

    • Calls repository for data

    • Transforms data to DTO

  4. Repository:

    • Talks to database (e.g., MySQL, PostgreSQL)

    • Executes SQL query:

      sql
      SELECT * FROM products WHERE price < 100
  5. Response Journey:
    Database → Repository → Service → Controller → HTTP Response


Key Takeaways:

  1. Constructors initialize objects and dependencies

  2. Services get data through:

    • Injected dependencies (repositories, API clients)

    • Method parameters

    • Static utility methods

  3. Method Categories:

    • Data Access: repository.findByX()

    • Business Logic: service.processOrder()

    • API Handling: controller.handleRequest()

  4. Class Responsibilities:

    • Controller: Handle HTTP requests/responses

    • Service: Implement business rules

    • Repository: Manage database operations

    • DTO: Define data structure for API communication

Angular Latest Features with Step-by-Step Examples (Angular v17+)

 Angular's latest version introduces groundbreaking features that enhance developer experience, performance, and reactivity. Here's a breakdown of the most significant features with practical examples:

1. New Control Flow Syntax (Developer Preview)

Replaces *ngIf*ngFor, and *ngSwitch with more powerful template directives.

Step-by-Step Example:

html
<!-- Component Template -->
<div>
  @if (user.isLoggedIn) {
    <h2>Welcome, {{ user.name }}!</h2>
  } @else {
    <button (click)="login()">Login</button>
  }

  @for (item of items; track item.id) {
    <app-item-card [item]="item" />
  } @empty {
    <p>No items found</p>
  }

  @switch (status) {
    @case ('loading') {
      <spinner />
    }
    @case ('success') {
      <p>Operation succeeded!</p>
    }
    @default {
      <p>Unknown status</p>
    }
  }
</div>

Key Improvements:

  • Better type checking

  • Reduced bundle size

  • More readable syntax

  • Built-in @empty block for collections


2. Deferrable Views (Lazy Loading)

Load components/dependencies only when needed

Step-by-Step Implementation:

html
<!-- Component Template -->
<button #trigger>Load Analytics</button>

@defer (on interaction(trigger); 
        when shouldLoadAnalytics;
        prefetch on idle) {
  <app-analytics-dashboard />
} @placeholder {
  <p>Analytics will load when you click the button</p>
} @loading (minimum 500ms) {
  <spinner />
} @error {
  <p>Failed to load analytics</p>
}
typescript
// Component Class
shouldLoadAnalytics = false;

loadAnalytics() {
  this.shouldLoadAnalytics = true;
}

Triggers:

  • on viewport (element enters viewport)

  • on idle (browser idle)

  • on interaction (user clicks/hovers)

  • on hover

  • on timer(5s)


3. Signals API (Stable)

Reactive primitive for fine-grained change detection

Step-by-Step Implementation:

typescript
import { signal, computed, effect } from '@angular/core';

// Component Class
export class CartComponent {
  // Writable signal
  items = signal<CartItem[]>([]);

  // Computed signal
  total = computed(() => 
    this.items().reduce((sum, item) => sum + item.price * item.quantity, 0)
  );

  // Effect
  logEffect = effect(() => {
    console.log('Cart changed:', this.items());
  });

  addItem(item: CartItem) {
    // Update signal immutably
    this.items.update(current => [...current, item]);
    
    // Alternative mutable update:
    // this.items.mutate(items => items.push(item));
  }
}

Template Usage:

html
<p>Total: {{ total() | currency }}</p>
<ul>
  @for (item of items(); track item.id) {
    <li>{{ item.name }} - {{ item.quantity }}</li>
  }
</ul>

4. Hybrid Rendering (SSR Improvements)

Unified rendering model for client/server

Step-by-Step Setup:

  1. Create new app with SSR:

bash
ng new my-app --ssr
  1. Enable hydration in app.config.ts:

typescript
export const appConfig: ApplicationConfig = {
  providers: [
    provideClientHydration()
  ]
};
  1. Add ngSkipHydration attribute for client-only elements:

html
<app-live-chart ngSkipHydration />

Key Benefits:

  • 50% faster Time-to-Interactive (TTI)

  • Automatic DOM matching

  • Partial hydration support


5. ESBuild Dev Server (Vite-Powered)

Faster build times and HMR (Hot Module Replacement)

Step-by-Step Migration:

  1. Update angular.json:

json
"architect": {
  "build": {
    "builder": "@angular-devkit/build-angular:browser-esbuild",
    "options": {
      "outputPath": "dist/my-app",
      "index": "src/index.html",
      "main": "src/main.ts",
      // ...
    }
  }
}
  1. Run with new builder:

bash
ng serve

Performance Gains:

  • 87% faster cold builds

  • 80% faster HMR

  • Reduced dev dependencies


6. Standalone Components (Stable)

NgModule-free application architecture

Step-by-Step Implementation:

typescript
// Component
@Component({
  standalone: true,
  imports: [CommonModule, RouterModule, HttpClientModule],
  template: `
    <h1>Standalone Component</h1>
    <router-outlet></router-outlet>
  `
})
export class MainComponent {}

// Bootstrap
bootstrapApplication(MainComponent, {
  providers: [
    provideRouter([
      { path: 'dashboard', loadComponent: () => import('./dashboard.component')}
    ])
  ]
});

Benefits:

  • Reduced boilerplate

  • Lazy loading without modules

  • Simplified dependency management


7. Improved Debugging with Angular DevTools

Enhanced component inspection and dependency tracing

New Features:

  1. Signal value inspection

  2. Dependency graph visualization

  3. Change detection profiling

  4. Directive debug information


8. Template Type Checking Improvements

Stricter type checking in templates

Example:

html
<app-user-profile [user]="selectedUser" />

Now reports errors if:

  • selectedUser doesn't match component input type

  • app-user-profile selector is incorrect

  • Input name is misspelled


Migration Tips:

  1. Update Angular CLI:

bash
npm install -g @angular/cli@latest
  1. Update existing project:

bash
ng update @angular/core @angular/cli
  1. Migrate control flow:

bash
ng generate @angular/core:control-flow

commonly used in modern ASP.NET Core apps more examples using fetch + Blob in JavaScript to download files PDF, Excel

 Let’s explore real-world examples using the fetch + blob pattern, targeting different file types and scenarios. ✅ 1. Download Static PD...

Best for you