Java Interview Questions & Answers Guide
Java Interview Questions & Answers Guide
Spring Bean Scopes define the lifecycle and visibility of beans across the application. The 'singleton' scope creates a single instance for the entire application context, suitable for shared resources. In contrast, 'prototype' results in a new instance on each request, necessary for independent processes requiring fresh data. 'Request' scope restricts the same instance to an HTTP request lifecycle, beneficial in web applications where per-request state needs management, while 'session' scope limits bean lifecycle to an HTTP session, useful for storing user session data .
The Saga pattern offers advantages in distributed systems by breaking down transactions into a sequence of local transactions with compensatory actions, which allows for greater resilience and non-blocking operations, making it suitable for microservices. However, it requires careful design of compensatory logic and monitoring for eventual consistency. In contrast, 2PC ensures atomicity but is synchronous and involves a single coordinator, which can become a performance bottleneck due to global locking and blocking issues, making it less scalable and prone to single points of failure .
Backward compatibility in microservices can be maintained through strategic API versioning, allowing multiple simultaneous API versions without disrupting clients. Contract testing ensures service contracts align with client expectations, minimizing integration issues. Gradual database migrations ensure schema changes do not break existing functionality by supporting coexistence of old and new schema versions. These strategies enable continuous delivery and deployment in rapidly changing environments, ensuring stability and consistent service behavior for users .
Asynchronous messaging in microservices can be implemented using messaging systems like Kafka or RabbitMQ, which allows services to communicate via events instead of direct calls. This approach decouples services, enhancing scalability since producers and consumers can be scaled independently. It increases fault tolerance as message queues persist data even if services are temporarily unavailable, enabling seamless recovery. It also improves system responsiveness as services can process messages at their own pace, leading to overall system resilience and better load management .
Diagnosing latency in microservices requires evaluating database query performance, as slow queries can significantly affect response times. Monitoring garbage collection and thread pool health can identify resource starvation. Network latency should also be checked, particularly in service dependencies. Analyzing logs and traces for bottleneck identification is crucial, as is testing downstream dependencies for their performance under load. Tools like distributed tracing can help visualize latency paths across services, aiding in pinpointing lag sources .
The Circuit Breaker pattern protects microservices by monitoring service calls for failures. When failures exceed a threshold, the circuit 'opens', preventing further open connections to allow the system to recover. Calls in this state receive immediate failures, reducing strain on the failing service. The circuit eventually enters a 'half-open' state to test if the service has recovered by allowing a limited number of requests. If these requests succeed, the circuit 'closes', permitting normal traffic. This strategy prevents cascading failures and enhances system resilience by isolating faulty components .
The N+1 problem occurs in JPA when lazy loading triggers multiple database queries during data retrieval, often leading to performance bottlenecks. For example, fetching a list of parent entities may unknowingly trigger additional queries for their related entities. This can be mitigated by using JOIN FETCH clauses to eagerly load related entities in a single query, applying EntityGraphs to specify fetch strategies, or employing batch fetching which implicitly loads related entities in bulk to reduce database round-trips and improve performance .
gRPC is preferable over REST in scenarios where lower latency and higher performance are crucial, due to its use of HTTP/2, which enables multiplexing and faster data transmission. It supports bi-directional streaming for efficient data flow in real-time applications and leverages Protocol Buffers for compact and efficient message serialization, reducing network load. Additionally, gRPC provides built-in code generation for strongly-typed interfaces, enhancing developer productivity and minimizing errors in microservice communication .
Dependency Injection in Spring decouples object creation from its behavior by providing dependencies externally, either via constructor or annotations like @Autowired. This promotes a cleaner separation of concerns, allowing developers to focus on behavior rather than configuration, leading to modular code. It enhances testing by enabling object mocking without affecting object behavior, facilitating isolated unit testing. By injecting dependencies at runtime, it also supports flexible application configuration through externalized settings .
Idempotency in RESTful APIs ensures that repeated identical requests have the same effect as a single request, avoiding unintended state changes. Techniques to enforce this include using idempotent HTTP methods like PUT and DELETE, utilizing idempotency keys which are unique tokens that track and replicate the outcomes of requests, and implementing UPSERT operations that update existing resources or insert new ones if absent. Idempotency is critical to guarantee reliability and consistency, especially in scenarios with network retries or distributed systems .