Sunday, 24 August 2025

Mock Interview Preparation - Microservices in Spring Boot

I: Can you explain how you implemented microservices in your last project?

C: Sure. In my last project, I worked on a Digital Locker / Document Vault System where we followed a microservices architecture. 
We had separate services like User Service, Document Service, and Notification Service. 
- Each service had its own database to ensure loose coupling. 
- Services communicated using REST APIs for synchronous calls and Kafka for asynchronous, event-driven scenarios. 
- We used Spring Boot + Spring Cloud for building microservices, Eureka for service discovery, and Spring Cloud Gateway as the API Gateway. 
- Security was handled via OAuth2 with JWT tokens. 
- For deployment, we containerised each service with Docker and deployed them on Kubernetes (OpenShift). 
- To handle resilience, we used Resilience4j (circuit breakers, retries, fallbacks). 
This architecture gave us scalability, independent deployments, and fault isolation. 


๐Ÿ” Follow-ups

I: Why did you choose microservices instead of a monolith? 
C: In a monolith, even a small change requires redeploying the whole application. Scaling was also harder since everything scaled together. With microservices, we gained independent deployments, better scalability, fault isolation, and tech flexibility. 

I: Why Kafka when REST APIs were already there? 
C: REST works fine for synchronous calls, but for event-driven features like sending notifications after a document upload, Kafka allows asynchronous communication. If the notification Service was down, messages stayed in Kafka and were processed later. 

I: How did you manage databases across services? 
C: Each service had its own database. This ensured loose coupling and autonomy. For example, User Service used PostgreSQL and Document Service used MongoDB. If we used a single DB, services would get tightly coupled. 

I: How did you secure inter-service communication? 
C: We used OAuth2 with JWT tokens. Auth Service generated JWTs after login. Each request carried the JWT, and microservices validated it. This ensured stateless, centralised authentication. 

I: What challenges did you face? 
C: 
- Distributed logging → solved with ELK stack. 
- Service failures → handled with Resilience4j circuit breakers & retries. 
- Database consistency → used the saga pattern for long transactions. 
- Network latency from multiple calls → optimised with caching + async messaging. 

I: Why Eureka and API Gateway? 

C: 
- Eureka (Service Discovery): avoided hardcoding URLs, services registered dynamically. 
- API Gateway: acted as a single entry point, managed routing, authentication, and rate limiting. 

I: How did you deploy and manage microservices? 
C: Each service had its own Jenkins pipeline. We used Docker for containerization and deployed on Kubernetes (OpenShift). This gave us scalability, rolling updates, and independent deployments. 


Angular Interview Questions

What is a Memory Leak?

A memory leak happens when your app keeps holding onto memory that it no longer needs.
In Angular, this usually means you’ve created references (like event listeners, subscriptions, DOM objects) that are never cleaned up — so the Garbage Collector cannot free them.
Over time, the app’s memory usage keeps growing → leading to slow performance or even crashes.

Common Causes of Memory Leaks in Angular:

1. Unsubscribed Observables / Subscriptions

If you don’t unsubscribe in ngOnDestroy, the subscription stays alive.

2. Event Listeners not removed

If not removed, the component will still respond to resize even after destruction.

3. Timers not cleared

If you don’t clearInterval, it keeps running.

How to Prevent Memory Leaks

1. Unsubscribe properly

2. Use async pipe

Instead of subscribing manually:
3. Remove event listeners & clear timers

A memory leak in Angular means resources are not released properly (like Observables, event listeners, timers, or DOM references). The fix is to unsubscribe, clean up, and use Angular features (async pipe, takeUntil, ngOnDestroy`) properly.


How to copy a reference from one variable to another?


What is server-side rendering in Angular?

Server-Side Rendering (SSR) in Angular is the process of rendering Angular applications on the server instead of the browser. With SSR, the Angular app is executed on the server, generating HTML which is sent to the browser. The browser displays a fully rendered page instantly, and then Angular takes over to make it interactive.

Benefits of SSR

• Faster First Contentful Paint (FCP)
• Better SEO (search engines can crawl HTML easily)
• Improved performance on slow networks or devices
• Better user experience

If I am making a Spring Boot REST API + Angular project, how will SSR work instead of Node.js?

Normally, Angular Universal requires a Node.js (Express) server to perform SSR. In a Spring Boot + Angular project:

Option 1: Use Node.js alongside Spring Boot:
   • Spring Boot serves REST APIs (/api/**).
   • Angular Universal runs on Node.js to handle SSR.
   • A reverse proxy (like Nginx) directs frontend routes to Node.js and API routes to Spring Boot.

Option 2: Use Pre-rendering (without Node.js):
   • Angular Universal or Scully can pre-generate static HTML at build time.
   • These static pages can be served directly from Spring Boot.
   • Suitable for static pages but not for dynamic user-specific content.


State Management in Angular

๐Ÿ”นIntroduction

State Management in Angular refers to how application data (state) is stored, updated, and shared across components and services.
It ensures consistency, scalability, and predictability, especially as applications grow in complexity.


๐Ÿ”น Types of State

  1. Local State – Data inside a single component (e.g., form input, toggle button).
    ✅ Managed using component variables.

  2. Shared State – Data shared across multiple components (e.g., logged-in user info, theme preference).
    ✅ Managed using Services + RxJS (BehaviorSubject, ReplaySubject).

  3. Global/Application State – Data needed across the entire app (e.g., authentication, shopping cart, notifications).
    ✅ Managed using state management libraries like NgRx, NGXS, or Akita.


๐Ÿ”น Common Approaches in Angular

1️⃣ Service with RxJS

  • Use BehaviorSubject or ReplaySubject in a service to hold and emit state.

  • Components subscribe to get updates.

Example – AuthService managing user state:

@Injectable({ providedIn: 'root' }) export class AuthService { private userSubject = new BehaviorSubject<User | null>(null); user$ = this.userSubject.asObservable(); setUser(user: User) { this.userSubject.next(user); } }
  • Any component can subscribe:

this.authService.user$.subscribe(user => console.log(user));

2️⃣ NgRx (Redux Pattern for Angular)

  • Predictable state container using:

    • Actions → What happened (e.g., Login, Logout).

    • Reducers → How the state changes.

    • Store → Single source of truth for the entire app.

  • Best for large & complex applications.

  • Comes with DevTools (time-travel debugging, action logging).


๐Ÿ”น Why State Management is Important?

✔ Prevents data inconsistency across components.
✔ Makes apps scalable and maintainable.
✔ Simplifies debugging and testing.
✔ Provides a centralized single source of truth.


๐Ÿ”น Interview-Ready Answer

State management in Angular is about handling and sharing application data consistently.
For small apps, I usually rely on services with RxJS subjects.
For larger applications, I use NgRx, which follows the Redux pattern and provides a single source of truth, predictable state transitions, and better debugging with DevTools.
This ensures data consistency, scalability, and maintainability of the application.







Monday, 30 January 2023

How to configure Liquibase in Project

 

What is Liquibase?

Liquibase is an open-source database schema change management solution that enables you to manage revisions of your database changes easily. Liquibase makes it easy for anyone involved in the application release process to:

  • Eliminate errors and delays when releasing databases.
  • Deploy and roll back changes for specific versions without knowing what has already been deployed.
  • Deploy database and application changes together so they always stay in sync.


Download Liquibase: Liquibase for Windows

For Non-spring Boot project, we need to make use of batch(.bat) file.

1. update.bat file

liquibase --driver=oracle.jdbc.driver.OracleDriver --url=jdbc:oracle:thin:@localhost:1521:orcl --changeLogFile=liquibase-changelogs.xml --username=system --password=root12345 update

Here --changeLogFile=liquibase-changelogs.xml

liquibase-changelogs.xml consists of all the changesets that we want to apply to our database.

For best practice, we don't add the changesets in a single file. 

Instead, we will have a separate file for each changeset with the proper id and author name.




Here we have included the <includeAll> tag to mention the path where we are having all the changesets files. It can be any location within the project. 

Suppose I have 3 SQL files with 3 changesets.








Explanation: 
Line 1: --liquibase formatted sql
            To make liquibase understand this is the SQL file that we have to use as a changeset.

Line 3: --changeset Aamir:1
            The required changeset that we have to execute with author name as Aamir and id as 1.

Line 4-7: The standard SQL statement to create a table

Line 8: --rollback drop table person
            This is the custom rollback that we have to create.
            After --liquibase, we have to give the SQL statement that act as rollback.


After writing all the changeset we can execute the "update.bat" file from the command line/Terminal.




This will execute all the changeset SQL file inside the given folder.

So it will create a table "person" along with 2 other tables:
i) databasechangelog
ii) databaseChangeLogLock









2. rollback.bat file

Now after executing all the changesets file, you want to rollback the last change. Then we need to create a separate "rollback.bat" file.

liquibase --driver=oracle.jdbc.driver.OracleDriver --url=jdbc:oracle:thin:@localhost:1521:orcl --changeLogFile=liquibase-changelogs.xml --username=system --password=root12345 rollbackCount 1

Here, we are using "rollbackCount 1". This means it will rollback the last executed changeset.

It can be rollbackCount 3, which will rollback the last three changesets.

Like this, we can rollback as per our need.



3. rollbackTag

We can also assign a tag to our changesets and then can rollback based on that

liquibase --driver=oracle.jdbc.driver.OracleDriver --url=jdbc:oracle:thin:@localhost:1521:orcl --changeLogFile=liquibase-changelogs.xml --username=system --password=root12345 tag prev_version

Here we are giving "tag pre_version", so after all the changeset are executed, then at the last changesets, the tag column in the databaseChangeLog will get updated with "prev_version".

So next time, after you have executed more changeset and if you have any issues, you can rollback to prev_version.



4. rollbackTime

Similarly, we can also rollback based on the Time the changesets were executed.

In this databaseChangeLog, we have one column related to Time of execution. 

5. update-sql 

The update-sql command is a helper command that allows you to inspect the SQL Liquibase will run while using the update command.

Uses

The update-sql command is used when you want to inspect the raw SQL before running the update command, so you can correct any issues that may arise before running the command. Liquibase uses the raw SQL to apply database changes you have added to the changelog file.


When we run "update-sql" command, it will create a new file(path and name we can give) with the SQL that is going to be executed.


















Wednesday, 22 June 2022

Multiple Database Configuration in Spring Boot

 Databases: 

  • MySQL Database
  • Oracle

In this demo, we would only use two datasources: MySQL and Oracle. 

Before you start: Create a database in MySQL called "mydb".

How it works:

It would be similar to your normal application but with a few changes

  1. The application.properties file would now contain multiple setting each for a different datasource.
  2. You need configuration classes, one for each of the data sources. One of the configuration classes must be set as Primary using the @Primary annotation.
  3. The configuration classes would contain mandatory methods:
    • DataSource method
    • LocalContainerEntityManagerFactoryBean method
    • PlatformTransactionManager method
  4.  We need a model/Entity class and a repository interface.

Step1: Create a SpringBoot project using SpringInitializer and add required dependencies like web, devtools etc.

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <scope>runtime</scope>
</dependency>
<dependency>
    <groupId>oracle</groupId>
    <artifactId>ojdbc6</artifactId>
    <version>11.2.0</version>
    <scope>system</scope>
    <systemPath>C:/oraclexe/app/oracle/product/11.2.0/server/jdbc/lib/ojdbc6.jar</systemPath>
</dependency>

Step 2: Create Entity class as Employee.java and Student.java under Entity package.
Make sure to include All args- constructors as well as no-args constructors as well as getters and setter methods. You can also include toString method as well.

Step 3: Create the Controller class to call the APIs from the mentioned endpoints.
You can create a separate controller class or a combined controlled class. Here I have created a separate Controller class as EmployeeController.java and StudentController.java.

Step 4: Create a Repository interface each for the different Entity class that we have created. We need to create StudentRepository.java and EmployeeRepository.java that will ultimately extends JPARepository.

Step 5: Create a service layer to act as a mediator between Controller and Repository layer to fetch data from the database. 

Step 6: In the application.properties files, we have to give different datasource properties as shown below:


You can see the setting for the two datasources. Take note that the datasources are differentiated based on the prefixes. Just be sure to provide valid name.

Step 7: Now the most important part. We have to create the Database configuration file to connect with the required database.
EmployeeConfiguration.java and StudentConfiguration.java.



i) DataSource method

Take note that in this listing the function is annotated with the @Primary annotation.

ii) LocalContainerEntityManagerFactory


iii) PlatformT
ransactionManager

Step 8: Similarly we have to do for StudentConfiguration.java file. Just don't forget to remove the @Primary annotation from there as we can't have two primary datasource.

The complete contents of both the file is available at the github location.

Step 9: Run the application and call the API based on the Employee or Student data and you will see the data insertion/retrieval will happen from both the databases.


Friday, 25 February 2022

Spring Boot Swagger2

 Spring Boot Swagger2

Swagger2 is an open source project used to generate the REST API documents for RESTful web services. It provides a user interface to access our RESTful web services via the web browser.

To enable the Swagger2 in Spring Boot application, you need to add the following dependencies in our build configurations file.


<dependency>
   <groupId>io.springfox</groupId>
   <artifactId>springfox-swagger2</artifactId>
   <version>2.7.0</version>
</dependency>
<dependency>
   <groupId>io.springfox</groupId>
   <artifactId>springfox-swagger-ui</artifactId>
   <version>2.7.0</version>
</dependency>

To enable the Swagger 2 we use the annotation @EnableSwagger2 in our SpringBoot Applivation class.


A Docket bean is defined and using its select() method we get an instance of ApiSelectorBuilder. ApiSelectorBuilder we configure the endpoints exposed by Swagger.


After the Docket bean is defined, its select() method returns an instance of ApiSelectorBuilder, which provides a way to control the endpoints exposed by Swagger.


Using the RequestHandlerSelectors and PathSelectors we configure the predicates for selection of RequestHandlers.




These are the only changes required. Now go to http://localhost:8080/swagger-ui.html.
We will see the documentation for the exposed API as follows-




Source Code: Spring Boot Swagger

Reference:  https://www.javainuse.com/spring/boot_swagger_annotations
















Thursday, 24 February 2022

Spring Boot Security + JWT Welcome Example

In this tutorial, we will be developing a Spring Boot application that makes use of JWT authentication for securing an exposed REST API. In this example, we will be making use of hard-coded user values for user authentication.

Any user will be able to consume this API only if it has a valid JSON Web Token (JWT).






Develop a Spring Boot application that exposes a simple REST GET API with mapping /welcome.

Configure Spring Security for JWT. Expose REST POST API with mapping /token using which User will get a valid JSON Web Token. And then, allow the user access to the API /welcome only if it has a valid token.




The Maven project will look as follows:



Spring Security and JWT Configuration

We will be configuring Spring Security and JWT for performing 2 operations-

  • Generating JWT — Expose a POST API with mapping /token. On passing correct username and password it will generate a JSON Web Token(JWT)
  • Validating JWT — If user tries to access GET API with mapping /welcome. It will allow access only if request has a valid JSON Web Token(JWT).


The sequence flow for these operations will be as follows-

Generating JWT




Validating JWT




Add the Spring Security and JWT dependencies

The secret key is combined with the header and the payload to create a unique hash. We are only able to verify this hash if you have the secret key.

jwt.secret=java


JwtUtil

The JwtUtil is responsible for performing JWT operations like creation and validation.It makes use of the io.jsonwebtoken.Jwts for achieving this.

JWTUserDetailsService

JWTUserDetailsService implements the Spring Security UserDetailsService interface. It overrides the loadUserByUsername for fetching user details from the database using the username. The Spring Security Authentication Manager calls this method for getting the user details from the database when authenticating the user details provided by the user. Here we are getting the user details from a hardcoded User List. Also the password for a user is stored in encrypted format using BCrypt. 


JwtAuthenticationController

Expose a POST API /authenticate using the JwtAuthenticationController. The POST API gets username and password in the body- Using Spring Authentication Manager we authenticate the username and password.If the credentials are valid, a JWT token is created using the JWTTokenUtil and provided to the client.

JwtRequest

This class is required for storing the username and password we recieve from the client.

JwtResponse

This is class is required for creating a response containing the JWT to be returned to the user.

JwtRequestFilter

The JwtRequestFilter extends the Spring Web Filter OncePerRequestFilter class. For any incoming request this Filter class gets executed. It checks if the request has a valid JWT token. If it has a valid JWT Token then it sets the Authentication in the context, to specify that the current user is authenticated.

JwtAuthenticationEntryPoint

This class will extend Spring’s AuthenticationEntryPoint class and override its method commence. It rejects every unauthenticated request and send error code 401

WebSecurityConfig

This class extends the WebSecurityConfigurerAdapter is a convenience class that allows customization to both WebSecurity and HttpSecurity.


Start the Spring Boot Application

  • Generate a JSON Web Token -
  • Create a POST request with url localhost:9191/token. Body should have valid username and password. In our case username is "amir" and password is "amir123".






  • Validate the JSON Web Token
  • - Try accessing the url localhost:9191/welcome using the above generated token in the header as follows

Source Code: Spring-boot-Jwt

Reference: https://medium.com/swlh/spring-boot-security-jwt-hello-world-example-b479e457664c