“Navigating Java Developer Interviews: Core Concepts, Spring Insights, Design Patterns, Coding Challenges, Microservices, and AWS Solutions”

Ajay Rathod
Javarevisited
Published in
11 min readAug 17, 2023

These days, the typical Java developer interview commences with a fundamental exploration of Object-Oriented Programming (OOP), Core Java concepts. Gradually, the interview process delves into more advanced areas such as frameworks like Spring, Hibernate, Spring Boot, microservices, and best practices.

Once the interviewer is satisfied with the assessment of the primary skills mentioned above, they proceed to evaluate secondary skills, including proficiency in databases, SQL, and cloud platforms like AWS, GCP, and Azure. Additionally, topics such as Kafka may also come into focus at this stage.

Subsequently, some interviewers extend their examination to encompass deployment knowledge, encompassing Kubernetes, Docker, Jenkins, and Git. The overarching evaluation centers around the foundational competence, which is expected to be above the average threshold. Only upon meeting or surpassing this core level of proficiency does a candidate stand a chance of being selected.

Presented below is a transcript from one of the interviews that follows a trajectory similar to the one outlined above. It is anticipated that this transcript will provide valuable insights. Let’s now embark on this learning journey.

Are you preparing for a job interview as a Java developer?

Find my book: Guide To Clear Java Developer Interview here Gumroad (PDF Format) and Amazon (Kindle eBook).

Guide To Clear Spring-Boot Microservice Interview here Gumroad (PDF Format) and Amazon (Kindle eBook).

Download the sample copy here: Guide To Clear Java Developer Interview[Free Sample Copy]

Guide To Clear Spring-Boot Microservice Interview[Free Sample Copy]

In previous articles, I have written 10 new Spring-Boot Interview Questions, Top-15-spring-boot-interview-questions-and-answers, and 12 Spring-Boot Interview Questions. please check that. Please follow this series to get all the questions.

core Java

How to control threads in the executor framework?

The Executor Framework in Java simplifies concurrent programming by providing a higher-level abstraction for managing thread execution and task scheduling, enhancing resource utilization and developer productivity.

For example, If want to multiple threads to work on a task but you don't want to create them manually every time you need, this framework takes care of that part.

Control threads in the Executor Framework through ThreadPoolExecutor configuration (core/max pool size, keep-alive), reuse for efficiency, prioritize tasks, handle overload, set thread timeouts, synchronize for shared resources, and monitor using metrics for optimal concurrency management.

What are Java Generics, and Java optional methods? use of it?

Java Generics allows you to create classes, interfaces, and methods that operate on different data types while providing type safety and reusability.

Java Optional methods are part of the java.util.Optional class, providing a way to handle potential absence of values, reducing null checks, and enhancing code readability by chaining methods like orElse(), orElseGet(), and map().

Spring

How @autowired works internally?

@Autowired in Spring automatically injects dependencies into a class's fields, constructors, or methods, reducing manual wiring and promoting loose coupling between components.

Here is a detailed article written by @javinapaul

Spring-Boot

How to use multithreading in SpringBoot?

To use multithreading in Spring Boot:

1. Define Task: Implement Runnable or Callable for your task logic.

2. Configure Bean: Create a TaskExecutor bean in a configuration class.

3. Inject and Execute: Inject TaskExecutor into your service/component and use it to execute the task.

Example:

@Component
public class MyTask implements Runnable {
@Override
public void run() {
// Task logic
}
}
@Configuration
public class ThreadConfig {
@Bean
public TaskExecutor taskExecutor() {
return new SimpleAsyncTaskExecutor();
}
}
@Service
public class MyService {
@Autowired
private TaskExecutor taskExecutor;
@Autowired
private MyTask myTask;
public void executeAsyncTask() {
taskExecutor.execute(myTask);
}
}

Call executeAsyncTask() to run the task concurrently.

How to use cache in spring boot?

Caching in Spring Boot can significantly improve the performance of your application by reducing the need to repeatedly fetch data from the database or perform expensive computations. Spring Boot provides integration with various caching providers, and you can easily configure and use caching in your application. Here’s a step-by-step guide on how to use caching in Spring Boot:

1. Add Dependencies:
Open your pom.xml (for Maven) or build.gradle (for Gradle) file and add the necessary dependencies for your chosen caching provider. Spring Boot supports multiple caching providers like Ehcache, Caffeine, Redis, etc. For example, if you want to use Ehcache, add the following dependency:

<! - For Maven →
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>org.ehcache</groupId>
<artifactId>ehcache</artifactId>
</dependency>

Remember to modify the dependencies based on the caching provider you choose.

2. Enable Caching:
In your Spring Boot main class (the class annotated with @SpringBootApplication), add the @EnableCaching annotation. This annotation enables Spring’s caching infrastructure.

import org.springframework.cache.annotation.EnableCaching;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@EnableCaching
public class YourApplication {
public static void main(String[] args) {
SpringApplication.run(YourApplication.class, args);
}
}

3. Configure Cache Manager:
Spring Boot auto-configures a default cache manager based on the caching provider’s availability. However, you can customize the cache manager by creating a CacheManager bean in your configuration. For example, to configure Ehcache:

import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.cache.CacheManager;
import org.springframework.cache.ehcache.EhCacheCacheManager;
import org.springframework.cache.annotation.EnableCaching;
@Configuration
@EnableCaching
public class CacheConfig {
@Bean
public CacheManager cacheManager() {
return new EhCacheCacheManager(ehCacheManager());
}
// Define your Ehcache manager bean here
@Bean
public EhCacheManager ehCacheManager() {
return new EhCacheManager();
}
}

4. Use Caching:
To cache methods, annotate them with caching annotations like @Cacheable, @CachePut, and @CacheEvict.

-@Cacheable: This annotation indicates that the result of the annotated method should be cached. If the method is called again with the same arguments, the cached result will be returned instead of executing the method.

- @CachePut: This annotation updates the cache with the result of the method execution, regardless of whether the data is already cached.

- @CacheEvict: This annotation removes data from the cache. Use it to indicate that the cached data should be evicted after method execution.

Here’s an example of using @Cacheable:

import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
@Service
public class MyService {
@Cacheable("myCache")
public String getCachedData(String key) {
// Method implementation
return someData;
}
}

What is @Aysnc annotation in spring-boot?

The @Async annotation in Spring Boot is used to indicate that a method should be executed asynchronously, meaning it will run in a separate thread from the caller.

This is particularly useful for methods that perform tasks that might take some time to complete, such as I/O operations, network calls, or heavy computations. By marking a method with @Async, you allow Spring to manage the asynchronous execution of that method.

How to configure two databases?

Very good article on this topic:

What are @primary and @ qualifiers?

Certainly, here’s a short answer about @Primary and @Qualifier annotations in Spring:

- @Primary: The @Primary annotation is used to indicate that a bean should be preferred when multiple beans of the same type are candidates for autowiring. It is primarily used to resolve ambiguity when Spring needs to inject a bean of a particular type into a component and there are multiple candidates. The bean marked with @Primary will be given precedence.

- @Qualifier: The @Qualifier annotation is used to specify a unique name or value to identify a particular bean when there are multiple beans of the same type. It is applied along with the @Autowired annotation to indicate which specific bean should be injected when multiple beans of the same type are available.

How JWT is Authenticating HTTP requests?

Here’s a short and simple explanation of how JWT is used for authentication:

1. Token Creation:
When a user logs in or is authenticated, the server generates a JWT containing relevant information (such as user ID, roles, and expiration time) and signs it using a secret key.

2. Token Sending:
The server sends the JWT back to the client (usually in the response body or a cookie). The client stores the token securely, such as in local storage or a cookie.

3. Request Authentication:
When the client wants to make an authenticated HTTP request, it includes the JWT in the request headers, typically using the “Authorization” header with the “Bearer” scheme. The token is usually in the format: `Bearer <token>`.

4. Server Validation:
Upon receiving the request, the server extracts the JWT from the “Authorization” header, verifies its integrity and signature using the secret key, and checks its expiration time. If the token is valid and not expired, the request is considered authenticated.

5. Access Control:
The server can then use the information in the JWT (such as user roles) to determine if the user has the necessary permissions to access the requested resource.

Design pattern

Please note that the following design patterns are commonly discussed in interviews:

  • A thorough exploration of the Builder design pattern
  • In-depth understanding of the Proxy pattern
  • Familiarity with the Facade pattern
  • Insights into the Factory Singleton pattern
  • Knowledge of the Prototype pattern, both shallow and deep variants.

Make sure you know these patterns,

What are the Solid principles?

Very good article written over here,

Coding

program to find the closing parenthesis..balanced “[]})”

import java.util.Stack;

public class BalancedParentheses {
public static boolean isBalanced(String s) {
Stack<Character> stack = new Stack<>();
for (char c : s.toCharArray()) {
if (c == '(' || c == '[' || c == '{') {
stack.push(c);
} else if (c == ')' || c == ']' || c == '}') {
if (stack.isEmpty() || !isMatchingPair(stack.pop(), c)) {
return false;
}
}
}
return stack.isEmpty();
}

public static boolean isMatchingPair(char open, char close) {
return (open == '(' && close == ')') ||
(open == '[' && close == ']') ||
(open == '{' && close == '}');
}

public static void main(String[] args) {
String parenthesesSequence = "[]})";
if (isBalanced(parenthesesSequence)) {
System.out.println("Parentheses are balanced.");
} else {
System.out.println("Parentheses are not balanced.");
}
}
}

program to find the middle number from the linked list?

class ListNode {
int val;
ListNode next;

ListNode(int val) {
this.val = val;
this.next = null;
}
}

public class MiddleOfLinkedList {
public static ListNode findMiddle(ListNode head) {
if (head == null) {
return null;
}

ListNode slow = head;
ListNode fast = head;

while (fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
}

return slow;
}

public static void main(String[] args) {
// Create a sample linked list: 1 -> 2 -> 3 -> 4 -> 5
ListNode head = new ListNode(1);
head.next = new ListNode(2);
head.next.next = new ListNode(3);
head.next.next.next = new ListNode(4);
head.next.next.next.next = new ListNode(5);

ListNode middle = findMiddle(head);
if (middle != null) {
System.out.println("Middle value: " + middle.val);
} else {
System.out.println("List is empty.");
}
}
}

Microservice

How to communicate to microservice what are the ways to do it?

Microservices communicate with each other using various communication mechanisms. Here’s a short answer on how microservices can communicate:

1. HTTP/REST APIs: Microservices expose and consume RESTful APIs over HTTP. They can make HTTP requests (GET, POST, PUT, DELETE) to each other’s endpoints.

2. Messaging/Event Bus: Microservices communicate asynchronously through a messaging system or event bus (e.g., Apache Kafka, RabbitMQ). They publish and subscribe to events, enabling decoupled communication.

3. gRPC: gRPC is a high-performance RPC (Remote Procedure Call) framework that allows microservices to communicate using strongly typed contracts.

4. Service Discovery: Microservices register with a service discovery tool (e.g., Eureka, Consul) and discover each other’s locations dynamically.

5. API Gateway: An API gateway serves as a central entry point for clients and routes requests to appropriate microservices, often handling authentication, load balancing, and caching.

6. Database/Shared Data Store: Microservices may communicate indirectly through a shared database or data store, although this may introduce coupling.

7. Circuit Breakers/Resilience Patterns: Services use circuit breakers and fallback mechanisms to handle failures and degraded performance gracefully.

8. Synchronous vs. Asynchronous: Choose synchronous communication for real-time interactions and asynchronous for decoupling and scalability.

9.REST vs. Messaging: REST APIs are suitable for request-response interactions, while messaging is better for broadcasting events and complex workflows.

10. Security and Authentication: Implement proper security mechanisms (e.g., OAuth, JWT) to ensure secure communication between microservices.

What is Netflix OSS library?

Netflix OSS (Open Source Software) library is a collection of open-source software tools and frameworks developed by Netflix to address various challenges in building and running large-scale, distributed systems. These tools provide solutions for tasks like service discovery, fault tolerance, load balancing, and more, enhancing the resilience and efficiency of applications in cloud environments.

This library from the basis of Spring Cloud and other component, Netflix have open sourced the code.

What is Fault tolerance and resilience?

Fault Tolerance: Imagine a web application hosted on multiple servers. If one server fails due to a hardware issue, the load balancer automatically redirects traffic to the remaining servers, ensuring uninterrupted service for users.

Resilience: Consider a cloud-based file storage service. If a data center experiences a power outage, the system quickly switches to a backup data center, ensuring users can still access their files without significant interruption. Additionally, the service may replicate data across multiple locations to prevent data loss and improve overall system resilience.

What is the Kafka messaging system, What is the pub-sub model?

Kafka Messaging System:
Apache Kafka is a distributed streaming platform that allows you to publish, store, and consume streams of records (messages) in a fault-tolerant, scalable, and highly available manner. It’s commonly used for real-time data streaming, event sourcing, and log aggregation.

Pub-Sub Model:
The Publish-Subscribe (pub-sub) model is a messaging paradigm where publishers send messages to a central broker (exchange), and subscribers receive the messages they are interested in from that broker. It decouples senders (publishers) from receivers (subscribers), allowing multiple subscribers to receive the same message simultaneously. Kafka follows the pub-sub model, where producers (publishers) send messages to Kafka topics, and consumers (subscribers) subscribe to those topics to receive and process the messages.

AWS

How to deal with the lambda function cold start problem?

Using Provisioned Concurrency (AWS keeps warm the lambda function)

How we are dealing with the resource id change that happens when we delete the stack inside AWS?

To manage resource ID changes when deleting a stack:

  1. Use logical names for resources.
    2. Employ tags and metadata.
    3. Dynamically reference resources.
    4. Backup critical data and configurations.
    5. Adopt Infrastructure as Code (IaC) practices.
    6. Leverage stack lifecycle management tools.
    7. Automate with orchestration tools.
    8. Document and track changes meticulously.
    9. Test stack processes in non-production environments.

A CloudFormation template, written in YAML format, is employed to establish the infrastructure within the AWS environment. This template orchestrates the creation of a comprehensive technology stack for your project, encompassing components such as database setups, network security groups, API gateways, and roles.

Free PDF’s from @javinpaul from @javarevisited

Grokking the Java Interview [Free Sample Copy]

Grokking the Spring Boot Interview [Free Sample Copy]

Thanks for reading

  • 👏 Please clap for the story and subscribe 👉(you can give upto 50 likes)
  • 📰 Read more content on my Medium (30+ stories on Java Developer interview)

Find my books below :

  • Guide To Clear Java Developer Interview here Gumroad (PDF Format) and Amazon (Kindle eBook).
  • Guide To Clear Spring-Boot Microservice Interview here Gumroad (PDF Format) and Amazon (Kindle eBook).
  • 🔔 Follow me: LinkedIn | Twitter | Substack | Facebook | Youtube

--

--

Ajay Rathod
Javarevisited

Java Programmer | AWS Certified | Writer | Find My Books on Java Interview here - https://rathodajay10.gumroad.com | YouTube - https://www.youtube.com/@ajtheory