Blog

Interview Experience At Sapaient

Question: Can you talk about your technical experience in brief? What skills and technologies you have worked on? How much experience do you have on those things?

Answer: Neelabh provided details about his 6.5 years of experience working with Java, Spring Boot, microservices, AWS cloud, and data structures & algorithms. He mentioned working at companies like Amazon, HaloFile, Sapient, and Xpora.

Question: Can you talk about the project that you have worked on microservices architecture, right? So, what was the microservices design pattern that you were using there?


Answer: I explained that in the budgeting system project at Amazon, they implemented the SAGA design pattern and circuit breaker pattern for handling distributed transactions across multiple microservices.

Question: What is the circuit breaker pattern?

Answer: I explained the circuit breaker pattern, which is used to prevent cascading failures when a service is not responsive. It operates in three states (open, closed, and half-open) and returns a fallback response when a service is unresponsive.

Question: What are orchestrations and choreography patterns in microservices?

Answer: Orchestrations and choreography are two different patterns used to manage and coordinate the communication and data flow between multiple microservices in a distributed system.

  1. Orchestration Pattern:

    In the orchestration pattern, there is a central orchestrator service that is responsible for coordinating the execution of tasks across multiple microservices.

    The orchestrator acts as a control mechanism, making decisions on which microservices to call, in what order, and with what data. It manages the overall flow of the business process and handles any failures or compensating actions.

    The orchestrator service typically maintains the state of the entire process and coordinates the communication between microservices.

    It acts as a single entry point for the client, receives requests, and then calls the appropriate microservices in the correct sequence, aggregating the responses and returning the final result to the client.

  2. Choreography Pattern:

    In the choreography pattern, there is no central orchestrator. Instead, each microservice is aware of the overall business process and communicates directly with other microservices when needed.

    The microservices collaborate and coordinate with each other using a predetermined protocol or messaging system, such as message queues or event streaming platforms.

    In this pattern, microservices publish events or messages when certain actions occur, and other microservices subscribe to these events or messages and take appropriate actions in response.

    The communication and data flow between microservices are decoupled, and each microservice is responsible for making decisions based on the events it receives and the business logic it encapsulates.

    The choreography pattern promotes autonomy and decentralization, as each microservice has its decision-making logic and can evolve independently.

    However, this pattern can become more complex as the number of microservices increases, and maintaining consistency and managing failures can be more challenging.

Key Differences:

  • Orchestration has a central orchestrator that controls the flow, while choreography is decentralized with no central coordinator.
  • Orchestration is easier to manage and maintain, while choreography is more complex but promotes autonomy and decentralization.
  • Orchestration can handle long-running transactions and complex rollback scenarios more easily, while choreography is better suited for simpler, event-driven interactions.
  • Orchestration can be a single point of failure, while choreography is more resilient due to its decentralized nature.

The choice between orchestration and choreography depends on the complexity of the business process, the level of decoupling required, the need for central control or autonomy, and the existing infrastructure and tools available in the organization.

Question: What is an aggregator?

Answer: In the context of microservices architecture, an aggregator is a separate service or component that acts as a single entry point for clients to access data or functionality from multiple microservices.

It aggregates and combines the responses from various microservices into a unified response for the client.

The main responsibilities of an aggregator in a microservices architecture include:

  1. Data Aggregation: The aggregator retrieves data from multiple microservices by making separate calls to each of them. It then combines or merges the data into a single response and returns it to the client. This is useful when a client needs data from multiple microservices to fulfil a single request.
  2. Functional Aggregation: In addition to data aggregation, an aggregator can also orchestrate and coordinate the execution of multiple microservices to perform a specific business operation or process. It acts as a façade, exposing a single entry point for clients while internally managing the interactions with multiple microservices.
  3. Insulation Layer: The aggregator acts as an insulation layer between the client and the underlying microservices. It hides the complexity of the distributed system from the client, providing a simpler and more consistent interface.
  4. Cross-Cutting Concerns: Aggregators can handle cross-cutting concerns such as caching, circuit breakers, load balancing, and protocol translation, offloading these responsibilities from individual microservices.
  5. Fault Tolerance: Aggregators can implement fault tolerance mechanisms, such as fallbacks and retries, to handle failures or timeouts from individual microservices, ensuring the overall system’s resilience.

By using an aggregator, clients don’t need to know the details of the microservices they’re interacting with or make multiple calls to different microservices. The aggregator encapsulates this complexity, providing a single entry point for clients to access the required data or functionality.

However, it’s important to note that introducing an aggregator can also add complexity and potential performance overhead. It can become a bottleneck or a single point of failure if not designed and implemented properly. Therefore, it’s crucial to strike a balance between the benefits of an aggregator and the potential drawbacks, considering factors such as system complexity, performance requirements, and the need for decoupling and insulation between clients and microservices.

Question: How are you handling the security part in your microservices? What all components were you using?

Answer: Javed mentioned using the Spring Boot Starter Security dependency and handling security at the API gateway level, but he could not provide specific details on the configurations.

References: https://dzone.com/articles/microservices-security-in-a-nutshell

Question: How do you configure the data source and all when we are using JPA?

Answer: When using JPA (Java Persistence API) in a Java application, you need to configure the data source and other related settings to establish a connection with the database. Here’s a typical approach to configure the data source and JPA in a Spring Boot application:

  1. Database Connection Properties:
  • In the application.properties or application.yml file, specify the database connection details, such as the URL, username, and password.
  • For example, for a PostgreSQL database:
YAML
spring.datasource.url=jdbc:postgresql://localhost:5432/myDatabase
spring.datasource.username=myUsername
spring.datasource.password=myPassword
  1. Database Driver:
  • Add the database driver dependency to your project’s pom.xml file.
  • For example, for PostgreSQL:
XML
<dependency>
    <groupId>org.postgresql</groupId>
    <artifactId>postgresql</artifactId>
</dependency>
    1. JPA Configuration:
    • In the application.properties or application.yml file, specify the JPA properties, such as the dialect, and show SQL and DDL auto mode.
    • For example:
    YAML
    spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
    spring.jpa.show-sql=true
    spring.jpa.hibernate.ddl-auto=update
      1. Entity Classes:
      • Create entity classes that represent the database tables using JPA annotations like @Entity, @Table, @Id, @Column, etc.
      • For example:
      Java
      @Entity
      @Table(name = "users")
      public class User {
          @Id
          @GeneratedValue(strategy = GenerationType.IDENTITY)
          private Long id;
      
          @Column(nullable = false)
          private String name;
      
          // Getters and setters
      }
        1. Repository Interfaces:
        • Create repository interfaces that extend JpaRepository or CrudRepository to define database operations.
        • For example:
        Java
        public interface UserRepository extends JpaRepository<User, Long> {
            // Additional custom queries if needed
        }
          1. Enable JPA:
          • In your main Spring Boot application class, annotate it with @EnableJpaRepositories to enable JPA repository support.
          • For example:
          Java
          @SpringBootApplication
          @EnableJpaRepositories
          public class MyApplication {
              public static void main(String[] args) {
                  SpringApplication.run(MyApplication.class, args);
              }
          }

          By following these steps, Spring Boot will automatically configure the data source and JPA based on the provided properties and annotations. You can then inject and use the repository interfaces in your application’s services or controllers to perform database operations.

          Note: If you’re using a different database management system (e.g., MySQL, Oracle), you’ll need to update the database connection properties, driver dependency, and dialect accordingly.

          Question: What all happens when you start your Spring Boot application, right? What does it do in the background?


          Answer: When you start a Spring Boot application, several things happen in the background to initialize and configure the application. Here’s a high-level overview of the startup process:

          1. Application Launch: The journey of a Spring Boot application begins with the public static void main(String[] args) method, where SpringApplication.run(App.class, args); is invoked.

            This is typically the entry point of the application.
          2. Spring Boot Application Initialization: The SpringApplication class is responsible for bootstrapping the Spring application context. It performs various initialization tasks, such as:
          • Setting up the environment (e.g., loading properties from various sources)
          • Configuring the application context (e.g., registering listeners, setting the active profiles)
          • Applying external configuration (e.g., from application.properties or application.yml)
          1. Application Context Creation: A new instance of the ApplicationContext (Spring’s IoC container) is created. This context is responsible for managing the lifecycle of beans and their dependencies.
          2. Annotation Discovery and Bean Registration: Spring Boot scans the project’s classpath for classes annotated with @Component, @Service, @Repository, @Controller, etc., and registers them as beans in the application context.
          3. Auto-Configuration and Bean Definitions: Spring Boot’s auto-configuration feature automatically configures and registers beans based on the dependencies present in the classpath. For example, if you have the spring-boot-starter-web dependency, it will automatically configure and register the necessary components for building a web application (e.g., DispatcherServlet, ViewResolver, etc.).
          4. Bean Post-Processing and Initialization: Spring Boot initializes the registered beans and applies any bean post-processing defined by the user or third-party libraries.
          5. Running Application Lifecycle Events: Spring Boot executes a series of lifecycle events, such as ApplicationStartingEvent, ApplicationEnvironmentPreparedEvent, ApplicationPreparedEvent, ApplicationStartedEvent, and ApplicationReadyEvent. You can register listeners for these events and perform custom actions or configurations.
          6. Executing CommandLineRunner and ApplicationRunner: If you have defined any CommandLineRunner or ApplicationRunner beans, their run() methods will be executed after the application context has been loaded. These can be used for initialization tasks or any other tasks that need to run when the application starts.
          7. Web Server Initialization (if applicable): If the application is a web application, Spring Boot starts the embedded server (like Tomcat, Jetty, or Undertow) and deploys the application. The server is configured and started to handle incoming HTTP requests.
          8. Application Ready: The application is now fully initialized and ready to serve requests.
          9. Printing Banner and Startup Information: After the application has started successfully, Spring Boot prints the banner (if enabled) and provides startup information, including the configured properties, active profiles, and other details.
          10. Registering Shutdown Hooks: Spring Boot registers shutdown hooks with the JVM to gracefully shut down the application when it receives a termination signal (e.g., Ctrl+C in the terminal or a kill command).

            Throughout the startup process, Spring Boot logs various messages to the console, providing insights into the initialization steps and any issues or warnings that may arise. You can also customize the startup behavior by providing your own configuration classes, listeners, or overriding default settings.
            Ref: https://medium.com/javarevisited/top-15-spring-boot-interview-questions-and-answers-for-java-developers-series-24-q-a-on-actuators-7253402c671#:~:text=When%20a%20Spring%20Boot%20application,and%20starts%20the%20application%20context.

          Question: How is a concurrent HashMap different from a normal HashMap in internal implementation?
          Answer:

          Ref

          1. https://itsromiljain.medium.com/curious-case-of-concurrenthashmap-90249632d335
          2. https://medium.com/double-pointer/guide-to-concurrenthashmap-in-java-9ba810b5182d
          3. https://medium.com/@surinder0322/what-is-concurrenthashmap-in-java-a1bd6d37bde4
          4. https://vicksheet.medium.com/unlocking-the-power-of-concurrenthashmap-a-thread-safe-guide-7697d2fdf75d
          5. https://medium.com/@basecs101/comparing-hashmap-and-concurrenthashmap-in-java-latest-98fc845ec70c
          6. https://anmolsehgal.medium.com/concurrenthashmap-internal-working-in-java-b2a1a48c7289
          7. https://anmolsehgal.medium.com/hashtable-vs-hashmap-vs-concurrenthashmap-4aa0ff1eecc4
          8. https://any-one-can-code.medium.com/hashtable-hashmap-concurrenthashmap-concurrency-read-write-performance-f7e59baca499
          9. https://medium.com/@vikas.taank_40391/java-concurrent-hashmap-improvements-over-the-years-8d8b7be6ce37
          10. https://www.youtube.com/watch?v=IPTa8EyiJGQ
          11. https://itsromiljain.medium.com/curious-case-of-concurrenthashmap-90249632d335

          Question: Have you heard about fail-fast and fail-safe? How can you make a fail-fast iterator fail-safe?
          Answer: Javed explained the concepts of fail-fast and fail-safe iterators and mentioned that modifying the iterator using its own methods could make a fail-fast iterator fail-safe.

          https://anmolsehgal.medium.com/fail-fast-and-fail-safe-iterations-in-java-collections-11ce8ca4180e

          following difference is not correct for

          Remove OpearationArrayList iterator supports removal of element during iteration.CopyOnWriteArrayList.remove() method throws exception if elements are tried to be removed during iteration.

          https://www.tutorialspoint.com/Difference-between-ArrayList-and-CopyOnWriteArrayList-in-Java#:~:text=ArrayList%20is%20not%20thread%20safe,CopyOnWriteArrayList%20is%20thread%20safe.&text=ArrayList%20iterator%20is%20fail%2Dfast,never%20throw%20ConcurrentModificationException%20during%20iteration.

          • Question: Why do we need locks, and how can you use these locking mechanisms in Java?
            Answer: Javed explained the need for locks in critical sections to avoid inconsistencies when multiple threads access shared resources. He mentioned using the ReentrantLock mechanism in Java.
          • Question: What if you do not overwrite the HashCode method? What is the impact of it?
            Answer: Javed explained that if the HashCode method is not overridden, it could break the contract between equals() and hashCode(), leading to unexpected behavior when using HashMap or HashSet.
          • Question: Can you write down a SQL query to find all employees whose salary is greater than their manager’s salary?
            Answer: Javed was unable to provide the correct SQL query to solve this problem.
          • Question: What all things on AWS you have used?
            Answer: Javed mentioned using CloudWatch, S3 buckets, API Gateway, Lambda functions, and EC2 instances on AWS.
          • Question: How do you connect RabbitMQ with your Spring Boot application? What configurations do you need?
            Answer: Javed could not remember the specific configurations required to connect RabbitMQ with a Spring Boot application.
          • Question: Can you give an example of any pattern that you have actually implemented in your experience, like with an example?
            Answer: Javed briefly explained the Builder design pattern, which is used when the creation of an object is complex and involves multiple attributes.
          • Question: Any experience in GraphQL?
            Answer: Javed mentioned that he has not worked with GraphQL APIs.
          • Question: What methodology are you following in your project? How frequently do you release changes?
            Answer: Javed mentioned that they follow the Agile methodology, specifically the Scrum model, and the release frequency varies between weekly and bi-weekly for different teams.

          Please note that this summary covers the main questions and answers, but there may be some additional details or follow-up questions that are not included.

          Avatar

          Neelabh

          About Author

          As Neelabh Singh, I am a Senior Software Engineer with 6.6 years of experience, specializing in Java technologies, Microservices, AWS, Algorithms, and Data Structures. I am also a technology blogger and an active participant in several online coding communities.

          You may also like

          Blog Design Pattern

          Understanding the Builder Design Pattern in Java | Creational Design Patterns | CodeTechSummit

          Overview The Builder design pattern is a creational pattern used to construct a complex object step by step. It separates
          Blog Tech Toolkit

          Base64 Decode

          Base64 encoding is a technique used to encode binary data into ASCII characters, making it easier to transmit data over