Home - ashish-ghub/docs GitHub Wiki

Interview preparation

https://github.com/wuyichen24

Java:

Trouble shooting thread dumps

java 8

https://www.interviewbit.com/java-8-interview-questions/

spring-security https://www.interviewbit.com/spring-security-interview-questions/

Owasp: https://owasp.org/www-project-top-ten/ https://cheatsheetseries.owasp.org/cheatsheets/Docker_Security_Cheat_Sheet.html

Spring: https://www.interviewbit.com/spring-interview-questions/

SQL https://www.interviewbit.com/sql-interview-questions/

Linux https://www.interviewbit.com/linux-interview-questions/


Java 10 mins

  • What is dynamic polymorphism?

  • What changes needs be done in department class to use it as key in Hashmap<Department, List

    1. Why are both equals() and hashCode() necessary?
    2. If equals() is overridden but hashCode() is not
    3. Let's say the Department class has a mutable attribute, for example, employeeCount. If the employeeCount changes after a Department object is used as a key in the HashMap, what potential issues could arise, and how would you mitigate them?
    4. What is immutable class? example, use cases, write an immutable class for a Employee has String name, int id, Date doj, Float salary, hobbies List
  • You need to design an API where you need to send all countries in response what data structure you will chose?

  • What if we want India as first country and rest as alphabetical order in UI Please share solution

  • Explain how to create and use parallel streams in Java. What are the potential benefits and drawbacks of using parallel streams? When would you consider using them?

  • What is concurrent modification exception in java? Why does it happen?

  • What is concurrent hash map? how it works?

  • What is the difference between thread and process? inter thread communication and inter-process communication

  • When should I use a CompletionService over an ExecutorService?

You should use a CompletionService over an ExecutorService when you need to efficiently process results as they become available, regardless of the order in which tasks were submitted. Here are specific scenarios and use cases where CompletionService is preferable:

  • What is the issue in current code how you can improve it ( Integer -> Atomic and AtomicInteger quantity = itemQuantities.computeIfAbsent(item, k -> new AtomicInteger(0));
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class ItemQuantityTracker {

    private final Map<String, Integer> itemQuantities = new ConcurrentHashMap<>();

    /**
     * Updates the total quantity for a given item.
     */
    public void updateItemQuantity(String item, int quantityToAdd) {
        // Current implementation for updating quantity:
        Integer currentQuantity = itemQuantities.get(item);

        if (currentQuantity == null) { 
            itemQuantities.put(item, quantityToAdd);
        } else {
            itemQuantities.put(item, currentQuantity + quantityToAdd);
        }
    }

    public Map<String, Integer> getItemQuantities() {
        return itemQuantities;
    }

    public static void main(String[] args) throws InterruptedException {
        ItemQuantityTracker tracker = new ItemQuantityTracker();
        ExecutorService executor = Executors.newFixedThreadPool(5);

        // Simulate multiple concurrent orders
        for (int i = 0; i < 100; i++) { 
            executor.submit(() -> {
                tracker.updateItemQuantity("Laptop", 1);
                tracker.updateItemQuantity("Mouse", 2);
                if (Math.random() < 0.2) { // Simulate less frequent items
                    tracker.updateItemQuantity("Keyboard", 1);
                }
            });
        }

        executor.shutdown();
        executor.awaitTermination(5, TimeUnit.SECONDS); 
    }
}
  • What is the issue in current code how you can improve it (AtomicInteger -> totalAggregatedPrice)
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

public class StockAggregator {

    // This is the shared total price from all sources
    private int totalAggregatedPrice = 0; 

    public void aggregatePrice(int price) {
        totalAggregatedPrice += price; 
        System.out.println("Aggregated price: " + totalAggregatedPrice + " by " + Thread.currentThread().getName());
    }

    public int getTotalAggregatedPrice() {
        return totalAggregatedPrice;
    }

    public static void main(String[] args) throws InterruptedException {
        StockAggregator aggregator = new StockAggregator();
        ExecutorService executor = Executors.newFixedThreadPool(5); 

        for (int i = 0; i < 100; i++) {
            final int priceToAdd = i + 1; // Prices from 1 to 100
            executor.submit(() -> aggregator.aggregatePrice(priceToAdd)); 
        }

        executor.shutdown();
        executor.awaitTermination(1, TimeUnit.MINUTES); 

        System.out.println("\nFinal Total Aggregated Price: " + aggregator.getTotalAggregatedPrice()); 
    }
}
  • What is the issue in current code how you can improve it

Code Snippet 1:

public static String getDepartmentName(Employee employee) {
    if (employee != null) {
        Department department = employee.getDepartment();
        if (department != null) {
            String name = department.getName();
            if (name != null) {
                return name;
            }
        }
    }
    return "Unknown Department";
}

   public static String getDepartmentName(Employee employee) {
    return Optional.ofNullable(employee) // Wrap the employee in an Optional
                   .map(Employee::getDepartment) // Get the department if the employee exists
                   .map(Department::getName) // Get the name if the department exists
                   .orElse("Unknown Department"); // Default value if any of the above is null
}

Spring Boot and Micro service (10 mins)

Coding problem (15 mins)

Design problem (15 mins)


Answer

  • Sorting problem
The core of the Comparator interface is the compare (T o1, T o2) method. 
This method takes two objects of type T as arguments and returns an integer value that indicates their relative order:

Negative integer: If o1 should come before o2.
Zero: If o1 is considered equal to o2 for the purpose of ordering.
Positive integer: If o1 should come after o2.


  Comparator<String> customOrderComparator = (country1, country2) -> {
            if (country1.equals("India")) {
                return -1; // India comes before anything else
            }
            if (country2.equals("India")) {
                return 1;  // Anything else comes after India
            }
            // For all other countries, sort alphabetically (case-insensitive)
            return country1.compareToIgnoreCase(country2);
        };

        // Sort the list using the custom Comparator
        countryList.sort(customOrderComparator);
  • concurrent modification exception

The ConcurrentModificationException is thrown by an object's iterator if it detects that the underlying collection has been structurally modified while the iteration is in progress, except through the iterator's own remove() or add() methods (in the case of ListIterator).

"Structural Modification" means:

Adding or removing elements from the collection. In the case of Map, also changing the key-value mappings. Essentially, any modification that affects the size or internal structure of the collection. Why does it happen?

The primary reason for this exception is to ensure the fail-fast behavior of iterators. When an iterator is created for a collection, it often keeps track of the collection's structure (e.g., through a modification counter). If another thread (or even the same thread in some cases) modifies the collection structurally during iteration, the iterator's internal state becomes inconsistent with the actual state of the collection.

Common Scenarios where you might encounter ConcurrentModificationException:

Iterating and Modifying in Multiple Threads: Iterating and Modifying in a Single Thread (Incorrectly):

How to Avoid ConcurrentModificationException?

  1. Use Thread-Safe Collections: If multiple threads need to access and modify a collection concurrently, use thread-safe collection classes from the java.util.concurrent package. Examples include:

ConcurrentHashMap ConcurrentLinkedQueue CopyOnWriteArrayList CopyOnWriteArraySet These collections are designed to handle concurrent modifications safely without throwing ConcurrentModificationException. However, be aware that they might have different performance characteristics and consistency guarantees compared to their non-thread-safe counterparts.

  1. Use the Iterator's remove() Method: When iterating over a collection using a standard Iterator, use the iterator's remove() method to safely remove the current element. This method informs the iterator about the modification, preventing the exception. For ListIterator, you can also use its add() and set() methods safely.

  2. Create a Copy for Iteration: If you need to modify the collection while iterating, one approach is to create a copy of the collection and iterate over the copy. Modifications are made to the original collection. However, this can be inefficient for large collections.

Spring Boot Interview Questions for Experienced Candidates

1. Autoconfiguration

  • Question: Spring Boot's autoconfiguration drastically reduces boilerplate. Explain in detail how autoconfiguration works under the hood. What are the key annotations and mechanisms involved, and what are the potential drawbacks or challenges associated with relying heavily on autoconfiguration in complex applications?

  • Answer: Autoconfiguration in Spring Boot relies heavily on the @EnableAutoConfiguration annotation (often implicitly included via @SpringBootApplication). This annotation triggers a search for spring.factories files in the classpath, specifically under the META-INF directory. These files list classes annotated with @Configuration that Spring Boot should consider.

    The AutoConfigurationImportSelector is the core component that processes these entries. It uses various conditional annotations (e.g., @ConditionalOnClass, @ConditionalOnProperty, @ConditionalOnBean) to determine whether a particular autoconfiguration class should be applied based on the presence of specific classes, properties in the environment, or existing beans in the application context.

    Mechanisms Involved:

    • @Configuration: Marks a class as a source of bean definitions.
    • @Bean: Defines a bean within a @Configuration class.
    • @EnableAutoConfiguration: Enables Spring Boot's autoconfiguration mechanism.
    • @SpringBootApplication: A convenience annotation combining @Configuration, @EnableAutoConfiguration, and @ComponentScan.
    • Conditional Annotations: Control the application of autoconfiguration based on specific conditions.
    • spring.factories: Configuration metadata file listing auto-configuration classes.

    Potential Drawbacks/Challenges:

    • "Magic" and Reduced Explicit Control: Can make it harder to understand the exact beans being created and their configurations, potentially hindering debugging or customization.
    • Dependency Conflicts: Introducing new dependencies might unexpectedly trigger unwanted autoconfiguration.
    • Performance Overhead: While generally minimal, the process of evaluating all potential autoconfiguration can have a slight impact on startup time in very large applications.
    • Opacity in Complex Scenarios: Understanding why a particular autoconfiguration did or did not apply can be challenging without careful inspection of conditions and dependencies.

2. Cloud Native Support

  • Question: Spring Boot provides significant support for building cloud-native applications. Discuss the key features and integrations that facilitate this. Elaborate on how you would leverage Spring Cloud (or similar technologies) in a Spring Boot application to address common cloud-native concerns like configuration management, service discovery, and circuit breaking.

  • Answer: Spring Boot's cloud-native support is enhanced through integrations with various Spring Cloud projects and core features. Key aspects include:

    • Externalized Configuration: Support for loading configuration from various sources like environment variables, command-line arguments, and external configuration servers (e.g., Spring Cloud Config, HashiCorp Consul). This aligns with the Twelve-Factor App methodology.
    • Service Discovery: Integration with service discovery tools like Spring Cloud Netflix Eureka, Consul, or Kubernetes DNS, allowing services to dynamically discover and communicate with each other.
    • Circuit Breakers: Libraries like Spring Cloud CircuitBreaker (backed by Resilience4j or Spring Retry) enable the implementation of circuit breaker patterns to enhance the resilience of microservices by preventing cascading failures.
    • Load Balancing: Spring Cloud LoadBalancer provides client-side load balancing capabilities for making calls to other services registered in a service registry.
    • Distributed Tracing: Integration with distributed tracing systems like Spring Cloud Sleuth (supporting Zipkin, OpenTelemetry) to track requests across multiple services, aiding in debugging and performance analysis.
    • Health Checks: Actuator endpoints provide built-in health indicators that can be used by orchestration platforms like Kubernetes to monitor the health of application instances.
    • Metrics: Actuator also exposes application metrics (e.g., JVM metrics, HTTP request metrics) that can be collected and monitored by systems like Prometheus.

    Leveraging Spring Cloud:

    • Configuration Management (Spring Cloud Config): Centralizing application configuration in a remote repository and providing a mechanism for services to retrieve their configuration dynamically.
    • Service Discovery (Eureka/Consul): Registering service instances with a central registry, allowing other services to discover their locations without hardcoding.
    • Circuit Breaking (Resilience4j): Wrapping external service calls with circuit breakers to prevent failures from propagating and providing fallback mechanisms.
    • Load Balancing (Spring Cloud LoadBalancer): Using @LoadBalanced WebClient or RestTemplate to automatically distribute requests across available service instances.

3. Testing

  • Question: Spring Boot provides excellent testing support. Describe the different types of tests you would write for a typical Spring Boot application (e.g., unit, integration, end-to-end). For integration tests, specifically discuss the advantages and disadvantages of using @SpringBootTest versus more focused slice tests (e.g., @WebMvcTest, @DataJpaTest). When would you choose one over the other?

  • Answer: A comprehensive testing strategy for a Spring Boot application typically involves:

    • Unit Tests: Focused on testing individual components (classes, methods) in isolation, without involving the Spring context or external dependencies (often using JUnit, Mockito). They are fast and help pinpoint issues at a granular level.
    • Integration Tests: Test the interaction between different parts of the application or with external systems (e.g., databases, APIs) within a (potentially partial) Spring context.
    • End-to-End (E2E) Tests: Simulate real user scenarios, often testing the entire application stack (UI, backend, database) as a black box (using tools like Selenium, Cypress, RestAssured).

    @SpringBootTest vs. Slice Tests:

    • @SpringBootTest:

      • Advantages: Loads the full Spring application context, providing a realistic environment for testing interactions between all beans. Useful for testing complex integrations and ensuring the overall application context is configured correctly.
      • Disadvantages: Can be slower to run due to the full context loading. Might test more than necessary for a specific scenario, leading to less focused tests.
    • Slice Tests (e.g., @WebMvcTest, @DataJpaTest, @WebFluxTest, @RestClientTest):

      • Advantages: Load a more focused slice of the Spring context relevant to the specific component being tested. This makes tests faster and more isolated, focusing on the behavior of a particular layer (e.g., web controllers, JPA repositories).
      • Disadvantages: Might require more setup for mocking or stubbing dependencies that are not part of the loaded slice. Less effective for testing cross-layer interactions or overall context configuration.

    When to Choose:

    • Use unit tests for isolated logic testing.
    • Use slice tests for focused integration testing of specific layers (e.g., testing REST controllers with @WebMvcTest and mocked services, testing JPA repositories with @DataJpaTest and an in-memory database). This is often the preferred approach for most integration testing needs due to speed and focus.
    • Use @SpringBootTest for more comprehensive integration tests that require the full Spring context to be loaded, especially for testing complex interactions between multiple components or when verifying the overall application context configuration.
    • Use end-to-end tests to validate the application from a user perspective, ensuring all layers work together correctly.

4. Advanced Customization

  • Question: Beyond basic properties configuration, what are some advanced techniques you've used to customize Spring Boot applications? Describe scenarios where you might need to implement custom ApplicationContextInitializers, ApplicationListeners, or CommandLineRunner/ApplicationRunner. Provide examples of how these components can be used to influence the application startup or runtime behavior.

  • Answer: Advanced customization in Spring Boot often involves leveraging its lifecycle hooks and extension points:

    • ApplicationContextInitializers: These interfaces allow you to perform actions before the ApplicationContext is fully refreshed. They are useful for programmatically configuring the ConfigurableApplicationContext, such as setting active profiles based on environment variables or system properties, or registering custom property sources. They are typically registered declaratively via the context.initializer.classes environment property or programmatically.

    • ApplicationListeners: These components listen to various application events published during the Spring Boot startup and shutdown lifecycle (e.g., ApplicationStartedEvent, ApplicationReadyEvent, ContextClosedEvent). They can be used to perform tasks after the application has started (e.g., initializing caches, scheduling jobs), or during shutdown (e.g., releasing resources). Listeners can be registered as beans or via spring.factories.

    • CommandLineRunner and ApplicationRunner: These interfaces provide a way to execute code after the Spring ApplicationContext has been fully initialized and the application is ready to start.

      • CommandLineRunner receives raw command-line arguments as a String array.
      • ApplicationRunner receives the parsed command-line arguments as an ApplicationArguments object, providing more structured access to options and non-option arguments.

    Scenarios and Examples:

    • ApplicationContextInitializers:

      • Dynamically setting active profiles based on a specific environment variable (e.g., setting cloud profile if CLOUD_ENVIRONMENT=true).
      • Registering a custom PropertySource to load configuration from a non-standard location or format.
    • ApplicationListeners:

      • Logging the application startup time after ApplicationReadyEvent.
      • Registering a custom shutdown hook to gracefully release external resources when ContextClosedEvent is published.
      • Initializing a distributed lock manager after the application has started.
    • CommandLineRunner/ApplicationRunner:

      • Performing database migrations or schema initialization on startup.
      • Loading initial data into the application.
      • Implementing a custom command-line interface for administrative tasks.
      • Starting background processing tasks immediately after the application starts.

5. Transaction Management

  • Question: Explain Spring's approach to transaction management. Discuss the differences between programmatic and declarative transaction management. In the context of a distributed system with multiple microservices and potentially different data sources, what are the challenges of maintaining data consistency, and what patterns or strategies (beyond traditional ACID transactions) might you consider?

  • Answer: Spring provides an abstraction layer over various transaction management APIs (e.g., JDBC, JPA, JTA), offering a consistent way to manage transactions regardless of the underlying data access technology. It supports both:

    • Programmatic Transaction Management: Involves explicitly controlling transaction boundaries within the code using a TransactionTemplate or directly using the PlatformTransactionManager. This offers fine-grained control but can lead to boilerplate code.

    • Declarative Transaction Management: Relies on metadata (typically annotations like @Transactional) to define transaction boundaries. Spring's AOP framework intercepts method calls annotated with @Transactional and automatically manages the transaction lifecycle (starting, committing, rolling back). This is the more common and recommended approach for most applications due to its simplicity and readability.

    Transaction Attributes: The @Transactional annotation allows specifying various transaction attributes, such as propagation behavior (e.g., REQUIRED, REQUIRES_NEW), isolation level, timeout, read-only status, and rollback rules.

    Challenges in Distributed Systems: Maintaining data consistency across multiple microservices and heterogeneous data sources is a significant challenge due to network latency, potential failures, and the lack of distributed ACID transactions in many scenarios.

    Patterns and Strategies Beyond ACID:

    • Saga Pattern: A sequence of local transactions in each service, where each local transaction updates its database and publishes an event to trigger the next transaction in another service. Compensating transactions are defined to undo the effects of previous transactions in case of failure.
    • Two-Phase Commit (2PC): A distributed transaction protocol that aims for atomicity across multiple resource managers. However, it can introduce performance bottlenecks and is not always supported by NoSQL databases.
    • Eventual Consistency: Accepting that data might be temporarily inconsistent across services but will eventually reach a consistent state. This often involves asynchronous communication and idempotent operations.
    • Outbox Pattern: Persisting outgoing events in the local database transaction of the service that produces the event. A separate process then reliably publishes these events to a message broker, ensuring that events are not lost if the service fails after committing the local transaction.
    • Change Data Capture (CDC): Monitoring database changes and publishing events based on those changes, allowing other services to react to data updates.

    The choice of strategy depends on the specific consistency requirements, performance considerations, and the nature of the business operations involved. Often, a combination of these patterns might be used in a complex distributed system.

Scalable Java Applications & Cloud-Native Technologies

Design:

  • Question: "Describe a complex, scalable Java application you've designed and developed. What were the key scalability challenges, and how did you address them? (Probe for specific examples of horizontal scaling, microservices, etc.)"
  • Potential Answer: The candidate should describe a project involving a significant user base or data volume. They should articulate the specific scalability bottlenecks encountered (e.g., database read/write limits, single points of failure, increasing request latency). Their answer should highlight the strategies employed, such as:
    • Horizontal Scaling: Adding more instances of the application.
    • Microservices Architecture: Breaking down the application into independent, deployable services.
    • Load Balancing: Distributing traffic across multiple instances.
    • Caching Strategies: Implementing various caching layers (e.g., in-memory, distributed) to reduce database load.
    • Asynchronous Processing: Using message queues to decouple components and handle long-running tasks.
    • Database Sharding/Partitioning: Distributing data across multiple database instances.
    • Read Replicas: Offloading read traffic to secondary database instances.

Coding/Implementation:

  • "Give an example of a time you had to optimize a Java application for performance. What tools and techniques did you use to identify bottlenecks and improve efficiency?"

  • Potential Answer: For a specific scenario where performance was an issue. They should mention the tools they used for profiling (e.g., Java Flight Recorder, VisualVM, YourKit), the identified bottlenecks (e.g., slow database queries, inefficient algorithms, excessive garbage collection), and the techniques they applied for optimization (e.g., query optimization, algorithm improvements, caching, connection pooling, thread pool tuning).

  • "How do you ensure code quality, maintainability, and testability in a large-scale Java project?" *Potential Answer:

    • Code Reviews: Emphasizing the importance of peer review.
    • Coding Standards and Style Guides: Following consistent coding conventions.
    • Static Code Analysis: Using tools like SonarQube, Checkstyle, PMD to identify potential issues.
    • Unit Testing: Writing comprehensive unit tests (using frameworks like JUnit, TestNG).
    • Integration Testing: Testing the interaction between different components.
    • Continuous Integration/Continuous Delivery (CI/CD): Automating the build, test, and deployment process.
    • Modularity and Loose Coupling: Designing components that are independent and interact through well-defined interfaces.
    • Proper Documentation: Writing clear and concise documentation.

Distributed Systems, Event-Driven Architectures

Design:

  • "Explain the key concepts of a distributed system. What are the common challenges (e.g., latency, consistency, fault tolerance), and how do you address them in your designs?"

  • Potential Answer: The candidate should explain concepts like nodes, communication, and coordination. They should discuss challenges such as:

    • Latency: Network delays affecting communication. Addressed by caching, optimizing communication paths, asynchronous communication.
    • Consistency: Ensuring data is the same across multiple nodes. Discuss different consistency models (e.g., strong, eventual) and techniques like distributed transactions, two-phase commit (2PC), or eventual consistency patterns (e.g., Saga).
    • Fault Tolerance: Designing the system to continue operating despite failures. Addressed by redundancy, replication, circuit breakers, retries.
    • Network Partitioning: Failures in network connectivity. Addressed by designing for resilience and using strategies like "split-brain" resolvers.
  • "Describe your experience with event-driven architectures. What are the advantages and disadvantages of this approach, and in what scenarios is it most suitable?"

  • Potential Answer: The candidate should explain the core concepts of EDA (producers, consumers, events, message brokers). They should discuss advantages like decoupling, scalability, resilience, and real-time processing. Disadvantages might include eventual consistency, increased complexity, and challenges in debugging. Suitable scenarios include systems with asynchronous tasks, real-time data processing, and loosely coupled services.

  • "Discuss your experience with messaging frameworks like Kafka, RabbitMQ, or similar. How have you used them to build asynchronous and decoupled systems? Explain your understanding of topics like message ordering, delivery guarantees, and handling message failures. (https://aws.amazon.com/compare/the-difference-between-rabbitmq-and-kafka)"

  • Potential Answer: The candidate should discuss their practical experience with the chosen framework. They should explain how it facilitates asynchronous communication and decouples services. Their understanding should cover:

    • Message Ordering: How messages are processed in the order they were sent (and the guarantees provided by the framework).
    • Delivery Guarantees: At-most-once, at-least-once, and exactly-once delivery semantics and how they are achieved.
    • Handling Message Failures: Dead-letter queues (DLQs), retry mechanisms, and error handling strategies.

Problem Solving:

  • "How would you design a system to handle a large volume of real-time events (e.g., millions per second)? Consider factors like scalability, throughput, and latency."

  • Potential Answer: The candidate should propose a design incorporating:

    • Message Queues (e.g., Kafka): For high-throughput ingestion and buffering of events.
    • Stream Processing Engines (e.g., Apache Flink, Apache Spark Streaming, Kafka Streams): For real-time processing and transformation of events.
    • Horizontal Scaling: Scaling both the message brokers and the stream processing applications.
    • Partitioning: Dividing event streams into multiple partitions for parallel processing.
    • Optimized Data Structures and Algorithms: For efficient processing.
    • Low-Latency Communication: Minimizing network hops and using efficient serialization formats.
  • "Describe a time you had to troubleshoot a distributed system issue. What was the problem, how did you diagnose it, and what was the solution?"

  • Potential Answer: The candidate should describe a specific incident, outlining the symptoms, the tools and techniques used for diagnosis (e.g., log aggregation, distributed tracing, monitoring dashboards), the root cause of the problem, and the steps taken to resolve it. This demonstrates their analytical and problem-solving skills in a distributed environment.

Concurrent Programming

Concepts:

  • "Explain the difference between a process and a thread. What are the advantages and disadvantages of using threads in Java?"

  • "Describe your understanding of Java's concurrency primitives (e.g., synchronized, volatile, ReentrantLock, AtomicInteger, CountDownLatch, CyclicBarrier, ExecutorService). Provide examples of when you would use each."

  • Potential Answer: The candidate should explain the purpose and usage of each primitive:

    • synchronized: For basic mutual exclusion on methods or blocks.
    • volatile: For ensuring visibility of variable changes across threads.
    • ReentrantLock: A more flexible locking mechanism with features like fairness and timeouts.
    • AtomicInteger: For thread-safe operations on integer values without explicit locking.
    • CountDownLatch: To synchronize one or more threads waiting for a set of operations to complete.
    • CyclicBarrier: To synchronize a fixed number of threads at a specific point, allowing them to proceed together.
    • ExecutorService: For managing and executing threads using thread pools.
  • "What are the common challenges in concurrent programming (e.g., race conditions, deadlocks, livelocks), and how do you prevent them?"

  • Potential Answer: The candidate should define each challenge:

    • Race Conditions: When the outcome of a program depends on the unpredictable order of execution of multiple threads accessing shared resources. Prevented by proper synchronization.
    • Deadlocks: When two or more threads are blocked indefinitely, each waiting for a resource held by another. Prevented by avoiding circular dependencies in resource acquisition, using timeouts, or employing deadlock detection and recovery mechanisms.
    • Livelocks: When threads repeatedly react to each other's state, preventing them from making progress even though they are not blocked. Prevented by introducing randomness or backoff strategies.

Application:

  • "Describe a time you used multithreading or parallel processing to improve the performance of a Java application. What were the specific challenges, and how did you overcome them?"

  • Potential Answer: The candidate should describe a scenario where they parallelized a task (e.g., processing a large dataset, handling multiple client requests). They should mention the challenges encountered (e.g., managing shared state, ensuring thread safety, optimizing the number of threads) and the techniques they used to address them (e.g., using thread-safe data structures, proper synchronization, tuning thread pool parameters).

  • "How do you design a thread-safe data structure in Java? (Probe for knowledge of concurrent collections, atomic variables, and synchronization techniques.)"

  • Potential Answer: The candidate should discuss approaches like:

    • Using Java's concurrent collections (e.g., ConcurrentHashMap, CopyOnWriteArrayList).
    • Employing atomic variables (AtomicInteger, AtomicReference) for simple atomic operations.
    • Using explicit locking mechanisms (synchronized, ReentrantLock) to control access to mutable state.
    • Ensuring proper visibility of shared variables using volatile.
    • Designing immutable objects.
  • "How do you profile and debug multithreaded applications in Java?"

  • Potential Answer: The candidate should mention tools like thread dump analyzers (e.g., jstack, VisualVM), profilers (e.g., Java Flight Recorder, YourKit), and debugging techniques specific to multithreading (e.g., setting breakpoints in different threads, examining thread states, looking for deadlocks).

Relational & NoSQL Databases & Database Performance

  • "How do you approach database performance optimization for a high-traffic Java application? Discuss techniques like indexing, query optimization, caching, and connection pooling."

Design:

  • "How do you choose the right database (SQL vs NoSQL) for a given application requirement?"

  • "How do you design a database schema for a microservices architecture, considering data consistency and eventual consistency?"

  • Potential Answer: The candidate should discuss strategies like database per service, shared-nothing architecture, and handling data consistency challenges using techniques like eventual consistency patterns (e.g., outbox pattern, event sourcing).

Containerization & Orchestration

Experience:

  • "Describe your experience with Docker. How have you used it to containerize Java applications, and what benefits did you observe (e.g., portability, consistency)?"

  • "Explain your understanding of Kubernetes. How have you used it to orchestrate containerized Java applications, and what are your experiences with concepts like pods, deployments, services, and scaling?"

  • "How do you manage the lifecycle of a containerized application, from development to deployment and monitoring?"

Problem Solving:

  • "How do you handle rolling updates and rollbacks in a Kubernetes environment for a high-traffic Java application?"

  • "How do you monitor the health and performance of your applications running in Kubernetes?"

VI. Problem-Solving & Analytical Skills

Technical:

  • "Present a hypothetical scenario involving a performance bottleneck in a Java application. Ask the candidate to walk you through their troubleshooting process, including how they would identify the root cause and propose solutions." (This can be tailored to a specific technology or area, e.g., database performance, memory leaks, concurrency issues.)

  • "Give the candidate a small coding problem (related to data structures or algorithms) and ask them to solve it on a whiteboard or shared editor. Observe their problem-solving approach, coding style, and ability to communicate their solution."

    Scenario 1: Efficiently Processing Multiple Tasks with Results

    Problem Statement

    You are tasked with processing a batch of independent tasks in parallel. Each task involves making an external API call that returns some data after a delay. Your goal is to:

    1. Submit all tasks for execution.
    2. Retrieve results as they complete (in the order of task completion, not submission).
    3. Ensure the solution is thread-safe and efficient.

    Write a Java program using ExecutorCompletionService to solve this problem.

Behavioral:

  • "Describe a time you faced a significant technical challenge in a project. How did you approach the problem, what steps did you take to analyze and resolve it, and what was the outcome?"

  • "Tell me about a time you had to work under pressure to resolve a critical production issue. How did you handle the situation, and what did you learn from it?"


Key Scenarios for Using CompletionService

  1. Results in Completion Order:

    • If you want to handle the results as soon as tasks complete, rather than waiting for all tasks to finish, CompletionService is ideal.
    • For example:
      • Processing web scraping tasks where you consume each result as soon as a page is scraped.
      • Handling database queries that return at different times.
  2. Dynamic Result Processing:

    • If the time required to process results varies between tasks, you can consume results dynamically with CompletionService, keeping your program responsive.
    • Example: Aggregating responses from multiple APIs that have variable response times.
  3. Optimizing Throughput:

    • With CompletionService, you can start consuming and processing results immediately without waiting for all tasks to complete.
    • This helps in reducing the memory footprint by processing and discarding results incrementally.
  4. Polling for Results:

    • Use CompletionService if you need to poll for results but do not want to block the calling thread unnecessarily.
    • The poll() method allows you to check for completed tasks without blocking.
  5. Simpler Result Management:

    • When using ExecutorService, you would need to track all submitted Future objects and iterate through them to check if they are done.
    • CompletionService automatically handles this by maintaining an internal queue of completed tasks.

When to Stick with ExecutorService

  1. Task Submission and Waiting for All Results:

    • If your workflow requires submitting tasks and waiting for all of them to complete before proceeding, then ExecutorService (along with invokeAll) might be simpler.
  2. Sequential Result Processing:

    • If results need to be processed in the exact order of task submission, ExecutorService is a better fit because CompletionService processes tasks based on completion order.
  3. Custom Complex Logic:

    • If you need more control over task execution, result collection, or specific synchronization requirements, ExecutorService gives you more flexibility.

Practical Examples

Using CompletionService:

Process tasks in the order they complete:

import java.util.concurrent.*;

public class CompletionServiceExample {
    public static void main(String[] args) throws InterruptedException, ExecutionException {
        ExecutorService executor = Executors.newFixedThreadPool(3);
        CompletionService<String> completionService = new ExecutorCompletionService<>(executor);

        // Submit tasks
        for (int i = 1; i <= 5; i++) {
            final int taskId = i;
            completionService.submit(() -> {
                Thread.sleep(taskId * 1000); // Simulate variable task duration
                return "Result from Task " + taskId;
            });
        }

        // Consume results as they complete
        for (int i = 1; i <= 5; i++) {
            Future<String> result = completionService.take(); // Blocks until a task completes
            System.out.println(result.get());
        }

        executor.shutdown();
    }
}

Using ExecutorService:

Wait for all tasks to complete and process results in submission order:

import java.util.concurrent.*;

public class ExecutorServiceExample {
    public static void main(String[] args) throws InterruptedException, ExecutionException {
        ExecutorService executor = Executors.newFixedThreadPool(3);
        List<Future<String>> futures = new ArrayList<>();

        // Submit tasks
        for (int i = 1; i <= 5; i++) {
            final int taskId = i;
            futures.add(executor.submit(() -> {
                Thread.sleep(taskId * 1000); // Simulate variable task duration
                return "Result from Task " + taskId;
            }));
        }

        // Consume results in submission order
        for (Future<String> future : futures) {
            System.out.println(future.get()); // Blocks until the task is done
        }

        executor.shutdown();
    }
}

Key Differences

Feature CompletionService ExecutorService
Result Order Based on task completion (dynamic). Based on task submission (static).
Result Access Non-blocking poll() or blocking take() for completed. Must iterate over Future objects and use isDone() or get().
Ease of Incremental Processing Simple, results are queued as tasks finish. Requires manual polling or synchronization for incremental results.
Flexibility Best for dynamic, unordered result processing. Best for static or sequential result handling.

Final Recommendation

  • Use CompletionService when completion order is more important than submission order, and you want to process results as they are available.
  • Stick with ExecutorService when you need submission order or want to block until all tasks finish for simpler workflows.

Q. how to implement retry basic retry mechanism
int maxRetries = 3; int retryCount = 0;

`while (retryCount < maxRetries) {`
`try {`
	`// Your operation here`
	`break; // Exit loop on success`
`} catch (Exception e) {`
	`// Handle exception (log, wait)`
	`retryCount++;`
`}`
`}`

`if (retryCount == maxRetries) {`
`// Handle all retries failed scenario`
`}   ` 

Q. what is the issue with simple retry and what are better way ?

There are a couple of issues with a simple retry mechanism that just repeats an operation a fixed number of times:

Increased Load: If multiple clients retry simultaneously after a failure, it can overload the system even further. This can worsen the original problem and make recovery more difficult. Inefficiency: Retries might happen too frequently, wasting resources if the underlying issue isn't resolved quickly.

              Simple Retry	             Exponential Backoff with Jitter

Load on System Can overload Lower load due to distributed retries Efficiency Inefficient retries possible More efficient retries Configuration Limited Flexible configuration (attempts, delay) Exception Handling All exceptions retried Specific exceptions retried

Here are better ways to implement retries with backoff:

Exponential Backoff: This strategy increases the wait time between retries exponentially. This gives the service more time to recover with each attempt and avoids overwhelming it with retries.

**Random Jitter: ** In addition to exponential backoff, introducing a random amount of wait time (jitter) can further prevent retry collisions. This ensures clients don't all retry at the exact same moment after the backoff period.

Configurable Retry Attempts: The ability to define the maximum number of retries allows you to control how persistent the retry behavior is.

Specific Exception Handling: Not all exceptions warrant retries. Ideally, you should only retry for transient exceptions that might resolve themselves on a subsequent attempt.


**Security : **

What is a vulnerability? how many types of them you have addressed ?

What is micro service architecture ?

What are the various security feature provided by spring ?

What is Directory traversal/ path-traversal sequences ? How to prevent a directory traversal attack? https://portswigger.net/web-security/file-path-traversal

What is oauth2 ? what is different grant type in oauth2 ?

What is CSRF? how would you design a solution to apply it across microservices?

What is XSS ? how do you fix them ?

What is brute force attack ? How would you protect it for authentication ? How would you design this feature ? ( good password policy with password size at least 8 or more chars, IP blocking, ( when ip is common like citrix or load balancer ip), MFA)

How would you design a solution where you need to enable you customer's employee can login with same username and password from our application login page ?

How would you design a solution where you need to enable, authentication from customer's portal and based on users role defined at customer end we need to map roles in our product for authorization ?

What is Oidc ?

How would you develop a system or procedure to eliminate vulnerabilities across products in a systematic way may initially targeting only critical then in next sprint major and so on ?

What is issue with this below code ?

  1. XSS

    <script> var x = '<%= token %>'; var d = document.createElement('div'); d.innerHTML = x; document.body.appendChild(d); </script>
  2. Open redirection issue

    protected void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException
    {
      String query = request.getQueryString();
      if (query.contains("fwd"))
       {
          String fwd = request.getParameter("fwd");
          try
          {
            request.getRequestDispatcher(fwd).forward(request, response);
          }
          catch (ServletException e)
          {
            e.printStackTrace();
          }
       }
    }
    

**Trouble shooting **

  • Deadlock identification, mitigations
  • Application slow analysis
  • Memory leaks identification
  • what you do to remote debug a docker running container

performance issue troubleshooting

-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/opt/com/data/heapdump/heapdump-reporter-pm-23-9ptwc.dump -XX:InitialHeapSize=14000000000 -XX:MaxHeapSize=14000000000 -XX:+PrintCommandLineFlags -XX:+PrintGC -XX:+PrintGCApplicationConcurrentTime -XX:+PrintGCApplicationStoppedTime -XX:+PrintGCDateStamps -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintHeapAtGC -XX:+PrintSafepointStatistics -XX:+PrintTenuringDistribution -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseParallelGC


https://medium.com/@pulapaphani/why-overriding-equals-and-hashcode-in-java-b5f869f985d2

Employee implements Comparable {

private String name; 
private int salary; 

// Used to sort movies by year (desc order)
public int compareTo(Employee m) 
{ 
    return this.salary- m.salary; 
} 

}

solid-design-principle

https://stackify.com/solid-design-open-closed-principle/

  1. Single Responsibility Principle
  2. Open/Closed Principle
  3. Liskov Substitution Principle
  4. Interface Segregation Principle
  5. Dependency Inversion

https://github.com/xoraus/CrackingTheSQLInterview

XML :

https://www.tutorialspoint.com/java_xml/java_xml_parsers.htm

Linux :

Symbolic link ln -s src folderpath linkname

Listing java process: ps -auxww grep java | grep <>

checking free memory : free -g

check size of directory du -sh path

Heapdums:

jmap -dump:format=b,file= Example: jmap -dump:format=b,file=/opt/tmp/heapdump.bin 37320

jcmd

  1. jcmd GC.heap_dump
  2. where
  3. pid: is the Java Process Id, whose heap dump should be captured
  4. file-path: is the file path where heap dump will be written in to.
  5. Example:
  6. 1 jcmd 37320 GC.heap_dump /opt/tmp/heapdump.bin

What is a vulnerability? A vulnerability is a hole or a weakness in the application, which can be a design flaw or an implementation bug, that allows an attacker to cause harm to the stakeholders of an application. Stakeholders include the application owner, application users, and other entities that rely on the application.

Please do not post any actual vulnerabilities in products, services, or web applications. Those disclosure reports should be posted to bugtraq or full-disclosure mailing lists.

Examples of vulnerabilities Lack of input validation on user input Lack of sufficient logging mechanism Fail-open error handling Not closing the database connection properly

https://owasp.org/www-project-top-ten/

  1. ACID Properties in DBMS transaction

Atomicity Atomicity requires that each transaction be "all or nothing": if one part of the transaction fails, then the entire transaction fails, and the database state is left unchanged. An atomic system must guarantee atomicity in each and every situation, including power failures, errors and crashes. To the outside world, a committed transaction appears (by its effects on the database) to be indivisible ("atomic"), and an aborted transaction does not happen.

Consistency The consistency property ensures that any transaction will bring the database from one valid state to another. Any data written to the database must be valid according to all defined rules, including constraints, cascades, triggers, and any combination thereof. This does not guarantee correctness of the transaction in all ways the application programmer might have wanted (that is the responsibility of application-level code), but merely that any programming errors cannot result in the violation of any defined rules.

Isolation The isolation property ensures that the concurrent execution of transactions results in a system state that would be obtained if transactions were executed sequentially, i.e., one after the other. Providing isolation is the main goal of concurrency control. Depending on the concurrency control method (i.e., if it uses strict - as opposed to relaxed - serializability), the effects of an incomplete transaction might not even be visible to another transaction.

Durability The durability property ensures that once a transaction has been committed, it will remain so, even in the event of power loss, crashes, or errors. In a relational database, for instance, once a group of SQL statements execute, the results need to be stored permanently (even if the database crashes immediately thereafter). To defend against power loss, transactions (or their effects) must be recorded in a non-volatile memory.

  1. Which operator is used to search for a specified text pattern in a column?

The LIKE operator is used in a WHERE clause to search for a specified pattern in a column. There are two wildcards used in conjunction with the LIKE operator: % - The percent sign represents zero, one, or multiple characters _ - The underscore represents a single character

Examples:

WHERE CustomerName LIKE 'a%' -- Finds any values that starts with "a" WHERE CustomerName LIKE '%a' -- Finds any values that ends with "a" WHERE CustomerName LIKE '%or%' -- Finds any values that have "or" in any position WHERE CustomerName LIKE 'r%' -- Finds any values that have "r" in the second position WHERE CustomerName LIKE 'a%_%' -- Finds any values that starts with "a" and are at least 3 characters in length WHERE ContactName LIKE 'a%o' -- Finds any values that starts with "a" and ends with "o"

  1. How to write a query to show the details of a student from Students table whose FirstName starts with 'K'?

SELECT * FROM Students WHERE FirstName LIKE 'K%'.

Explanation from previous question applies.

  1. performance tuning of oracle

  2. What is a trigger? Triggers in SQL is kind of stored procedures used to create a response to a specific action performed on the table. You can invoke triggers explicitly on the table in the database. Triggers are, in fact, written to be executed in response to any of the following events: A database manipulation (DML) statement (DELETE , INSERT , or UPDATE ) A database definition (DDL) statement (CREATE , ALTER , or DROP ). A database operation (SERVERERROR , LOGON , LOGOFF , STARTUP , or SHUTDOWN). Action and Event are two main components of SQL triggers when certain actions are performed the event occurs in response to that action.


import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger; // Import AtomicInteger

public class ItemQuantityTrackerAtomicValues {

    // Map stores AtomicInteger as values for atomic updates
    private final Map<String, AtomicInteger> itemQuantities = new ConcurrentHashMap<>();

    public void updateItemQuantity(String item, int quantityToAdd) {

        // Atomically gets the AtomicInteger for the key, or creates a new one with 0 if absent.
        // This part uses ConcurrentHashMap's atomic computeIfAbsent.

        AtomicInteger quantity = itemQuantities.computeIfAbsent(item, k -> new AtomicInteger(0));

        // This operation is thread-safe on the AtomicInteger itself.
        quantity.addAndGet(quantityToAdd);
    }

    public Map<String, Integer> getItemQuantities() {
        // When retrieving for display, convert AtomicInteger to int for cleaner output.
        // This iteration itself might not be strictly consistent across all values if map is
        // simultaneously modified, but individual values will be correctly captured.
        Map<String, Integer> finalQuantities = new ConcurrentHashMap<>(); // Or HashMap if consistency isn't needed
        itemQuantities.forEach((item, atomicQuantity) -> finalQuantities.put(item, atomicQuantity.get()));
        return finalQuantities;
    }

    public static void main(String[] args) throws InterruptedException {
        ItemQuantityTrackerAtomicValues tracker = new ItemQuantityTrackerAtomicValues();
        ExecutorService executor = Executors.newFixedThreadPool(5);

        for (int i = 0; i < 1000; i++) { // Increased iterations for clearer results
            executor.submit(() -> {
                tracker.updateItemQuantity("Laptop", 1);
                tracker.updateItemQuantity("Mouse", 2);
                if (Math.random() < 0.2) {
                    tracker.updateItemQuantity("Keyboard", 1);
                }
            });
        }

        executor.shutdown();
        executor.awaitTermination(5, TimeUnit.SECONDS);

        // Expected counts:
        // Laptop: 1000
        // Mouse: 2000
        // Keyboard: approx 200
    }
}
⚠️ **GitHub.com Fallback** ⚠️