0% found this document useful (0 votes)
1 views222 pages

Java 1

The document discusses memory management in Java, detailing the two main types of memory: Stack and Heap, along with their characteristics and garbage collection mechanisms. It explains the different types of references, the structure of the heap memory, and the various garbage collection algorithms available in Java. Additionally, it covers object-oriented programming principles, class loaders, and the importance of encapsulation, inheritance, and polymorphism.
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
1 views222 pages

Java 1

The document discusses memory management in Java, detailing the two main types of memory: Stack and Heap, along with their characteristics and garbage collection mechanisms. It explains the different types of references, the structure of the heap memory, and the various garbage collection algorithms available in Java. Additionally, it covers object-oriented programming principles, class loaders, and the importance of encapsulation, inheritance, and polymorphism.
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

Memory Management in Java

07 April 2025 21:11

2 types of memory:
1. STACK -> stores temporary variables
Store temporary variables and separate memory block for methods.
Store primitive data types.
Store Reference of the heap objects.
Types of reference:
- Strong reference : ClassName obj=new ClassName();
When GC, is invoked it is not deleted.
- Weak reference : ClassName<Person> obj=new ClassName<Person>(new Person());
When GC is invoked, it may be deleted.
Example

- Soft reference : Type of Weak Reference, Softly referenced objects are collected only when the JVM runs out of
memory. Widely used for caching mechanisms in applications.

- Phantom Reference: Type of weak reference. They are used to do post-mortem cleanup or finalization after an
object is garbage collected.
They are not accessible directly. You need to use a ReferenceQueue to receive notifications when the object is
garbage collected. Rarely used, mainly for final cleanup or tracking garbage collection.

Core Java Page 1


garbage collected. Rarely used, mainly for final cleanup or tracking garbage collection.

Each thread has its own Stack memory.


Variables within a SCOPE is only visible and as soon as any variable goes out of the SCOPE, it gets deleted from the
stack (LIFO)
When stack memory goes full, its throws "[Link]"
2. HEAP -> more memory and only one copy
Stores Objects.
There is no order of allocating the memory.
Garbage Collector is used to delete the unreferenced objects from the heap.
- Mark and sweep algorithm.
- Types of GC: Single GC, Parallel GC, CMS(Concurrent Mark Sweep), G1
Heap memory is shared with all the threads.
Heap also contains the String pool.
When heap memory goes full, its throws "[Link]"
Heap memory is further divided into
- Young Generation (minor GC happens here)
Eden, Survivor
- Old/Tenured Generation (major GC happens here)
- Permanent Generation
To run the GC, [Link]() -> no guarantee whether it will be called or not that totally depends on JVM.
Heap is divided into
- Young Generation
- Old Generation
Non-Heap -> Metaspace
Before java 7 -> PremGen but now it is no more used
Java (JVM) Memory Model

Core Java Page 2


Java (JVM) Memory Model

JVM memory is divided into separate parts. At board level, JVM Heap memory is physically divided into 2 parts - Young
Generation and Old Generation.
Memory Management in Java - Young Generation
The young generation is the place where all new objects are created. When this is filled then garbage collection is
performed. This garbage collection is called Minor GC.
Young generation is divided into three parts - Eden Memory and two Survivor Memory spaces.
-> Most of the newly created objects are located in the Eden memory space.
-> When Eden space is filled with objects, Minor GC is performed and all the survivor objects are moved to one of the
survivor spaces.
-> Minor GC also checks the survivor objects and move them to the other survivor space. So at a time, one of the survivor
space is always empty.
Garbage Collection uses Mark and Sweep Algorithm:
- Mark : Marks the objects which needs to be deleted.
- Sweep : Moves the survived objects to the survival space and agce of survived objects is marked as 1.
This process is called minor GC.
When again new object is created and when GC is called again, then the same process is continued but this time new
objects are moved Eden to s1 and s1 moves to s2 but the age of previous objects will be increased by 1 and new objects
will be 1.

-> Objects that are survived after many cycles of GC, are moved to the Old generation memory space. Usually, it's done by
setting a threshold for the age of the young generation objects before they become eligible to promote to Old generation.
When the threshold is met, then the objects are moved to old generation and this is time taking process. This process is
called Major GC.
Memory Management in Java - Old Generation
Old Generation memory contains the objects that are long-lived and survived after many rounds of Minor GC. Usually,
garbage collection is performed in Old Generation memory when it’s full. Old Generation Garbage Collection is called Major
GC and usually takes a longer time.
Stop the World Event
All the Garbage Collections are “Stop the World” events because all application threads are stopped until the operation
completes. Since Young generation keeps short-lived objects, Minor GC is very fast and the application doesn’t get affected
by this. However, Major GC takes a long time because it checks all the live objects. Major GC should be minimized because

Core Java Page 3


by this. However, Major GC takes a long time because it checks all the live objects. Major GC should be minimized because
it will make your application unresponsive for the garbage collection duration. So if you have a responsive application and
there are a lot of Major Garbage Collection happening, you will notice timeout errors. The duration taken by garbage
collector depends on the strategy used for garbage collection. That’s why it’s necessary to monitor and tune the garbage
collector to avoid timeouts in the highly responsive applications.
Java Memory Model - Permanent Generation / Meta Space.
Permanent Generation or “Perm Gen” contains the application metadata required by the JVM to describe the classes and
methods used in the application. Note that Perm Gen is not part of Java Heap memory. Perm Gen is populated by JVM at
runtime based on the classes used by the application. Perm Gen also contains Java SE library classes and methods. Perm
Gen objects are garbage collected in a full garbage collection.
It stores class variables, class metadata, constants. When JVM is loaded then its metadata is stored in metadata.
Differences between the Prem Gen and Meta Space :
Prem Gen was part of heap and is not expandable if it is filled then it will throw OutOfMemoryError.
Meta Space is out of Heap memory and it is expandable as you require.
Java Memory Model - Method Area
Method Area is part of space in the Perm Gen and used to store class structure (runtime constants and static variables) and
code for methods and constructors.
Java Memory Model - Memory Pool
Memory Pools are created by JVM memory managers to create a pool of immutable objects if the implementation supports
it. String Pool is a good example of this kind of memory pool. Memory Pool can belong to Heap or Perm Gen, depending on
the JVM memory manager implementation.
Java Memory Model - Runtime Constant Pool
Runtime constant pool is per-class runtime representation of constant pool in a class. It contains class runtime constants
and static methods. Runtime constant pool is part of the method area.
Java Memory Model - Java Stack Memory
Java Stack memory is used for execution of a thread. They contain method specific values that are short-lived and
references to other objects in the heap that is getting referred from the method.

Memory Management in Java - Java Heap Memory Switches


Java provides a lot of memory switches that we can use to set the memory sizes and their ratios. Some of the commonly
used memory switches are:

Core Java Page 4


Core Java Page 5
Garbage Collection
07 April 2025 21:57

Algorithm of GC:
1. Mark and Sweep Algorithm
2. Mark and Sweep with Compaction
In Compaction, it compact the different memory together in sequential manner so that it would
be easy to added the memory when required

Java Garbage Collection


Java Garbage Collection is the process to identify and remove the unused objects from the memory and
free space to be allocated to objects created in future processing. One of the best features of Java
programming language is the automatic garbage collection, unlike other programming languages such as
C where memory allocation and deallocation is a manual process. Garbage Collector is the program
running in the background that looks into all the objects in the memory and find out objects that are not
referenced by any part of the program. All these unreferenced objects are deleted and space is
reclaimed for allocation to other objects. One of the basic ways of garbage collection involves three
steps:
Marking: This is the first step where garbage collector identifies which objects are in use and which ones
are not in use.
Normal Deletion: Garbage Collector removes the unused objects and reclaim the free space to be
allocated to other objects.
Deletion with Compacting: For better performance, after deleting unused objects, all the survived
objects can be moved to be together. This will increase the performance of allocation of memory to
newer objects.
There are two problems with a simple mark and delete approach.
First one is that it’s not efficient because most of the newly created objects will become unused
Secondly objects that are in-use for multiple garbage collection cycle are most likely to be in-use for
future cycles too.
The above shortcomings with the simple approach is the reason that Java Garbage Collection is
Generational and we have Young Generation and Old Generation spaces in the heap memory.
Memory Management in Java - Java Garbage Collection Types
1. Serial Garbage Collector
Single-threaded.
Marks, sweeps, and compacts objects sequentially.
Best for: Small applications with single-threaded environments, standalone application.
2. Parallel Garbage Collector (default java 8)
Uses multiple threads to perform marking, sweeping, and compacting.
Best for: Applications with medium to large heaps where throughput is prioritized.
3. CMS Garbage Collector (Concurrent Mark and Sweep)
Performs marking concurrently with the application threads to reduce pause times.
Best for: Low-latency applications (e.g., real-time systems).
4. G1 Garbage Collector (Garbage-First GC) -> default since java 9
Divides the heap into multiple regions and performs incremental garbage collection.
Focuses on collecting regions with the most garbage first.
Best for: Applications with large heaps and predictable pause times.

Core Java Page 6


Best for: Applications with large heaps and predictable pause times.
5. Z Garbage Collector (ZGC) (Java 11+)
Performs garbage collection with very low pause times using concurrent operations.
Handles heaps as large as terabytes.
Best for: Applications requiring ultra-low latency.
6. Shenandoah Garbage Collector (Java 12+)
Employs concurrent compaction to reduce fragmentation and minimize pause times.
Best for: Applications requiring balanced throughput and latency.
Serial GC (-XX:+UseSerialGC): Serial GC uses the simple mark-sweep-compact approach for young and
old generations garbage collection i.e Minor and Major GC.
Parallel GC (-XX:+UseParallelGC): Parallel GC is same as Serial GC except that is spawns N threads for
young generation garbage collection where N is the number of CPU cores in the system. We can control
the number of threads using -XX:ParallelGCThreads=n JVM option. Parallel Garbage Collector is also
called throughput collector because it uses multiple CPUs to speed up the GC performance. Parallel GC
uses a single thread for Old Generation garbage collection.
Parallel Old GC (-XX:+UseParallelOldGC): This is same as Parallel GC except that it uses multiple threads
for both Young Generation and Old Generation garbage collection.
Concurrent Mark Sweep (CMS) Collector (-XX:+UseConcMarkSweepGC): CMS Collector is also referred
as concurrent low pause collector. It does the garbage collection for the Old generation. CMS collector
tries to minimize the pauses due to garbage collection by doing most of the garbage collection work
concurrently with the application threads. CMS collector on the young generation uses the same
algorithm as that of the parallel collector. This garbage collector is suitable for responsive applications
where we can’t afford longer pause times. We can limit the number of threads in CMS collector using -
XX:ParallelCMSThreads=n JVM option.
G1 Garbage Collector (-XX:+UseG1GC): The Garbage First or G1 garbage collector is available from Java
7 and its long term goal is to replace the CMS collector. The G1 collector is a parallel, concurrent, and
incrementally compacting low-pause garbage collector. Garbage First Collector doesn’t work like other
collectors and there is no concept of Young and Old generation space. It divides the heap space into
multiple equal-sized heap regions. When a garbage collection is invoked, it first collects the region with
lesser live data, hence “Garbage First”.
Abstract Algorithm (Phases):
Initialization: Prepare the GC process and root set identification.
Mark Phase: Traverse from root to find all reachable objects.
Sweep Phase: Remove unreachable (garbage) objects.
Compact Phase: Rearrange surviving objects to reduce fragmentation (if supported).
Repeat: Perform GC periodically or when memory is full (depends on triggering policy).

Core Java Page 7


OOPS Fundamentals
10 April 2025 10:33

OOPS means Object-Oriented Programming


Object means real-world entity (Properties and Behavior)

Object and Classes:


Objects has 2 things:
- Properties or state
- Behavior or Function
Class is a blueprint of an object or skeleton
Class provides the template or blueprint from which object can be created.
From one class, we can create multiple Objects
Getters and Setters are called as Data methods since they directly work on data variables.
4 pillars of OOPS:
1. Data Abstraction:
It hides the internal implementation and shows only essential functionality to the user.
It can be achieved through interface and abstract classes.
Advantages : Increase security and confidentiality.
2. Data Encapsulation:
Encapsulation bundles the data and the code working on that data in a single unit. Also known as
Data-hiding.
Steps to achieve encapsulation.
- Data hiding can be done using private static.
- Declare Variable of a Class as a private.
- Provide a Public Getters and Setters to modify and view the value of the variables.
Advantages : Loosely coupled code, Better access control and security.
3. Inheritance:
Capability of a class to inherit properties from their Parent class. It can inherit both functions and
variables, so we do not have to write them again in child classes.
Can be achieved using extends keyword or through interface.
Types of inheritance:
- Single Inheritance
- Multilevel Inheritance
- Hierarchical Inheritance
- Multiple Inheritance - through interface we can resolve the diamond problem.
Advantages : Code reusability, We can achieve polymorphism using inheritance.
4. Polymorphism:
Poly means many and Morphism means form. A same method, behaves differently in different
situation.
Types of polymorphism:
- Compile Time/ Static Polymorphism / Method Overloading
- Run Time / Dynamic Polymorphism / Method Overriding
Access-modifiers:

Core Java Page 8


Access-modifiers:
- Private
- Public
- Protected
- Default ( package-protected)
Objects Relationships :
- Is-a Relationship:
Achieved through inheritance
Inheritance form an is-a relation between its parent child classes.
Example: DOG is a Animal
- Has-a Relationship:
Whenever, an Object is used in Other classes, it's called HAS-A relationship
Relationship could be 1:1, 1:m,m:m
Example: School has students
- Associative relationship between 2 different Objects:
Aggregation : Both Objects. Can survive individually, means ending of one object will not end
other object. Weak relationship
Composition: Ending of one object will end another object.
Strong relationship

Core Java Page 9


Class Loader
20 May 2025 11:00

The Java ClassLoader is an integral part of the Java Runtime Environment (JRE) that dynamically loads Java classes into
the Java Virtual Machine (JVM). The Java run time system does not need to know about files and file systems because of
classloaders. Java classes aren’t loaded into memory all at once, but when required by an application. At this point, the
Java ClassLoader is called by the JRE, and these ClassLoaders load classes into memory dynamically.
ClassLoaders play a crucial role in Java's ability to dynamically load classes into memory as needed, enabling flexibility
and efficiency in Java applications.
Types of ClassLoaders in Java
1. Bootstrap ClassLoader (Primordial ClassLoader):
The Bootstrap ClassLoader is a machine code responsible for initiating the JVM's operations.
In Java versions up to 8, it loaded core Java files from [Link]. However, starting from Java 9, it loads core Java files from
the Java Runtime Image (JRT).
Bootstrap ClassLoader operates independently without any parent ClassLoaders.
2. Platform Class Loader (Extension ClassLoader):
In Java versions before Java 9, there was an Extension ClassLoader, but from Java 9 onwards, it's referred to as the
Platform Class Loader.
It loads platform-specific extensions from the JDK's module system.
Platform Class Loader loads files from the Java runtime image or from any other module specified by the system
property [Link] or --module-path.
3. System ClassLoader (Application ClassLoader):
Also known as the Application ClassLoader, it loads classes from the application's classpath.
It is a child of the Platform Class Loader.
Classes are loaded from directories specified by the environment variable CLASSPATH, the -classpath or -cp command-
line option.
Principles of Functionality of a Java ClassLoader

Java ClassLoaders operate based on specific principles:


1. Delegation Model:
ClassLoaders follow a delegation hierarchy algorithm.
When the JVM encounters a class, it checks if it's already loaded. If not, it delegates the loading process through a chain
of ClassLoaders.
The delegation hierarchy starts from the Application ClassLoader, then moves to the Platform Class Loader, and finally
to the Bootstrap ClassLoader.
Each ClassLoader in the hierarchy searches for the class in its defined locations and delegates the search if necessary.
2. Visibility Principle:
Classes loaded by parent ClassLoaders are visible to child ClassLoaders, but not vice versa.
This ensures encapsulation and prevents conflicts between classes loaded by different ClassLoaders.
3. Uniqueness Property:
ClassLoaders ensure that classes are loaded only once to maintain uniqueness.
If a parent ClassLoader cannot find a class, only then the current instance attempts to load it.
Methods of [Link]

Several methods in [Link] facilitate the loading of classes:


loadClass(String name, boolean resolve): Loads classes referenced by the JVM, resolving them if necessary.
defineClass(): Defines a byte array as an instance of a class. Throws ClassFormatError if the class is invalid.
findClass(String name): Finds a specified class without loading it.
findLoadedClass(String name): Verifies if the class is already loaded.
[Link](String name, boolean initialize, ClassLoader loader): Loads and initializes a class, allowing the
specification of a ClassLoader. If the ClassLoader parameter is null, the Bootstrap ClassLoader is used by default.
Example:
// Code executed before class loading
Class<?> clazz = [Link]().loadClass("[Link]");

Core Java Page 10


Class<?> clazz = [Link]().loadClass("[Link]");

Java ClassLoader Functionality Principles


There are three principles of functionality, they are:
Delegation Model: The Java Virtual Machine and the Java ClassLoader use an algorithm called the Delegation Hierarchy
Algorithm to Load the classes into the Java file. The ClassLoader works based on a set of operations given by the
delegation model.
Visibility Principle: The Visibility Principle states that a class loaded by a parent ClassLoader is visible to the child
ClassLoaders but a class loaded by a child ClassLoader is not visible to the parent ClassLoaders.
Uniqueness Property: The Uniqueness Property ensures that the classes are unique and there is no repetition of classes.
This also ensures that the classes loaded by parent classloaders are not loaded by the child classloaders.
Example: The following code is executed before a class is loaded:
protected synchronized Class<?> loadClass(String name, boolean resolve)
throws ClassNotFoundException
{
Class c = findLoadedClass(name);
try {
if (c == NULL) {
if (parent != NULL) {
c = [Link](name, false);
}
else {
c = findBootstrapClass0(name);
}
}
catch (ClassNotFoundException e)
{
[Link](e);
}
}
}
Note: If a class has already been loaded, it returns it. Otherwise, it delegates the search for the new class to the parent
class loader. If the parent class loader doesn't find the class, loadClass() calls the method findClass() to find and load the
class. The findClass() method searches for the class in the current ClassLoader if the class wasn't found by the parent
ClassLoader.

Core Java Page 11


Commonly Overridden in Custom ClassLoaders
• findClass(String name)
• findResource(String name)
• loadClass(String name) (advanced use only – this breaks delegation if not handled carefully)

Core Java Page 12


Important
20 May 2025 11:50

Overloading
Same name - different paramerters
Static can be overloaded
Final can be overloaded
Overriding:
Same name - same parameters - return type same/coveriant(sub-class)
Final cannot be overridden
Static cannot be overridden but it can be hidden using static
Because : static methods belong to the class, not the instance.
So method resolution happens at compile time, based on the reference type, not the object
Parent - Child
Checked - Unchecked
Checked - Checked

Exception - Checked
Exception - Unchecked

Core Java Page 13


HashMap
20 May 2025 13:05

A HashMap<K, V> stores key-value pairs. It allows null keys and values, and provides O(1) average time for get() and put(),
assuming good hash distribution.
Core Components Inside HashMap
Internally, a HashMap uses:
An array of buckets (Node<K, V>[] table)
Each bucket is a linked list (or tree when collision threshold is high)
Each Node stores:
static class Node<K, V> implements [Link]<K, V> {
final int hash;
final K key;
V value;
Node<K, V> next;
}
How put(key, value) Works
[Link]("apple", 100);
Hash Calculation
Computes a hash code from the key:
int hash = hash("apple");
Index Determination
Converts the hash into an index for the array:
int index = (n - 1) & hash; // n = array length
Collision Handling
If the bucket at that index is empty → insert the new node.
If not → collision! → traverse the list:
If key already exists → update value
If not → add the node at the end (or in Java 8+, may treeify)
If size exceeds loadFactor * capacity, the HashMap resizes itself (usually doubling the capacity), and rehashes all keys.
How get(key) Works
[Link]("apple");
Calculate the hash → locate the bucket index
Traverse the linked list (or tree) at that index
Use equals() to find the correct key → return value
hash → index → check each node's key with equals() → get value
Treeification (Java 8+)
If one bucket has more than 8 nodes and capacity ≥ 64:
Java converts the linked list to a red-black tree.
Improves performance from O(n) to O(log n) in that bucket.
What Happens on Hash Collisions?
If two keys have the same hash and land in the same bucket:
They're stored in a linked list (or tree if many)
Java uses equals() to distinguish the keys
HashMap<String, Integer> map = new HashMap<>();
[Link]("A", 1);
[Link]("B", 2); // suppose A and B hash to same bucket
Bucket looks like: "A" → "B" linked
null key is always stored in bucket 0
Operation Time Complexity (Avg) Notes
put() O(1) Becomes O(log n) if treeified
get() O(1) Uses hash + equals()
remove() O(1) Similar to get
🔑

Core Java Page 14


🔑 equals() and hashCode() in HashMap

Core Java Page 15


Git commands
22 May 2025 21:54

Installing & Configuring Git


git --version # Check Git version
git config --global [Link] "Your Name"
git config --global [Link] "you@[Link]"
git config --global [Link] "code --wait" # Set VS Code as editor
git config --global [Link] true # Windows (true), macOS/Linux (input)
git config --global -e # Edit global config
Repository Setup
mkdir project # Create new directory
cd project
git init # Initialize Git repo
Git Workflow (Working Directory → Staging → Repository)
Add & Commit
git add file1 file2 # Add specific files
git add . # Add all files
git commit -m "Message" # Commit with message
git commit # Open editor for detailed message
git commit -am "Msg" # Add + Commit in one go
Remove Files
git rm [Link] # Remove and stage deletion
git rm --cached [Link] # Unstage deletion
Rename/Move Files
mv [Link] [Link] # Move
git mv [Link] [Link] # Move with Git tracking
Ignoring Files
touch .gitignore # Create ignore file
echo logs/ > .gitignore # Add directory to ignore
code .gitignore # Edit in VS Code
Check Status & Differences
git status # Check file status
git status -s # Short status
git diff # Changes in working directory
git diff --staged # Changes in staging area
Diff Tools
git config --global [Link] vscode
git config --global [Link] "code --wait --diff $LOCAL $REMOTE"
git difftool
git difftool --staged
View History
git log # Full commit log
git log --oneline # Summary
git log --oneline --reverse # Old to new
git show <commit_id> # Show specific commit
git show HEAD~1:<path> # View file in previous commit
git ls-tree HEAD~1 # List commit files
Unstaging & Reverting

Core Java Page 16


Unstaging & Reverting
git restore --staged [Link] # Unstage file
git restore [Link] # Discard changes
git clean -f # Delete untracked files
git checkout -- [Link] # Revert file to last commit
Reset Commits
git reset --soft HEAD~1 # Undo last commit (keep staged)
git reset --mixed HEAD~1 # Undo last commit (unstage)
git reset --hard HEAD~1 # Undo and discard changes
Stashing Work
git stash # Save uncommitted changes
git stash list
git stash apply # Apply last stash
Rewriting History
git commit --amend -m "New Msg"
git rebase -i HEAD~n # Interactive rebase (n = number of commits)
# Change "pick" to "squash", "reword", etc.
Blame
git blame filename # Who changed each line
Merge & Cherry-Pick
git merge feature # Fast-forward merge
git cherry-pick <commit> # Apply commit from another branch
git merge --abort # Abort merge
git rebase --abort # Abort rebase
Remote Repositories
git remote add origin <url> # Add remote
git push origin main # Push to remote
git pull origin main # Pull from remote
git fetch # Get changes without merging
🔥 Git Flow Models
1. Git Flow (nvie)
• main, develop, feature/*, release/*, hotfix/*
git flow feature start login
git flow feature finish login
2. Trunk-Based Development
• All devs commit to main, short-lived branches encouraged.
3. GitHub Flow
• Only main and feature branches.
• Push → PR → Review → Merge.

Core Java Page 17


Git
08 January 2025 21:14

Git is Version Control System, records changes made to our code overtime in a special database called repository.
Without VCS, we need to maintain the copy of all the changes made by each developers, which makes system work slow
and merge all the changes which leads to many conflicts.
With VCS, we can
-> Track History
-> Work Together
VCS forms into 2 categories
1. Centralized - all the team members connect to a central server to get the latest copy of the code and to share the
code changes to all.
Examples -> Subversion, MS team Foundation server
Disadvantages -> Single point failure and cannot save data.
2. Distributed - every team members has the copy of the project and history of their machine so we can save the data
locally in our systems. If server is offline, we can directly synchronize our code with others.
Examples -> Git, mercurial
Why Git?
- Free
- Open Source
- Super fast
- Scalable
- Cheap Branching/Merging
Using Git,
- The command line - terminal and it is faster
- Code editors & IDEs - Source control panel in VS code - GitLens extension
- GUI - Git website - popular tools GitKraken Git GUI and SourceTree
GitKraken - works across different platforms and easy to integrate with other products like GitKraken Boards for
issue tracking and GitKraken Timelines for project management it is free for open source and for commercial it is
payable.
SourceTree - free open source available for windows and mac.
Why command line?
- GUI tools have limitations
- GUI tools may not be available
Installing Git
- Terminal to check version -> git --version -> 2.27.0
Installed application called GitBash = Born Again Shell -> Command prompt window which emulates unix and linux
environment.
- Configuring Git
Settings -> name, email, default editor, line ending
Configuration Settings in 3 levels,
1. System levels -> Applied to all users
2. Global levels -> Applied to all the repositories of the current user
3. Local levels -> applied to current repo
git config --global [Link] "XYX" -> name
git config --global [Link] xtc@[Link] -> email
default editor for mac is vim
download and install VScode and configure the path and then in terminal type code
git config --global [Link] "code --wait" wait flag to tell terminal to wait until we close the new vscode instance
All the global configuration are stored in text file which can be edited using default editor
git config --global -e -> opens our default editor to edit the global settings (default file name -> gitconfig)
In windows, end of line is marked with \r->Carriage Return and \n->Line Feed

JM-0 Page 1
In windows, end of line is marked with \r->Carriage Return and \n->Line Feed
In mac, end of line is marked with \n
We need to configure the end of line to avoid data issues, to prevent this we need to use [Link] property which is
carriage return line feed.
git config --global [Link] true/input(true for windows and input for mac)
Git help commands
git config --help (space for next page and q to exit)
git config -h -> summary for each commands and its options
Git Commands
To create directory -> mkdir dir
To open directory -> cd dir
To create empty repository/ initialize-> git init
By default subdirectories are hidden because of that we cannot see .git in list
To list all files and directories -> ls
To list all files and directories even hidden -> ls -a (a=All) we can .git subfolder then
To open .git, windows-> explorer, mac -> finder
To open .git file from terminal -> open .git
It contains branches, hooks, info, objects and references. If anyone deletes this folder then can lose the project history
To make terminal pretty (optional), windows -> posh-git, mac -> Zsh with Git plugin
To remove directory with sub repository -> rm -rf .git
Git Workflow:

Staging area / index -> review the changes and then commit and pushes the code to repository where it is stored
permanently.
git add f1 f2 f3 -> to add files from local to staging area
git commit -m "message" -> to send file from staging area to repository
After pushing the code to repository we still have files in staging area which says our working file
If we want to delete the file from the working directory then we need to delete the file from directory and then use git
add file to remove file from staging area and repository and then git commit.
Each commit contains ID, message, data/time, author, complete snapshot
Git reduces the storage by compressing the content and doesn't store duplicate content
Staging Files:
To add data into files -> echo hello > [Link] (> means to add data)
To track and the status of working directory and staging area -> git status
To add all files to staging area -> git add .
Green color for main branch with ? Indicates we have files which are not being tracked
Yellow color for main branch without ? But some other mark indicates that there are files in staging area and are ready
to be committed
echo world >> [Link] (>> means to append the data)
Committing changes:
git commit -m "message"
To add some additional info for the commit file (description)
git commit -> opens default editor (short description -> max 80 length and then line break and then long description)
Committing best Practices:
- Commit size shouldn't be too small and too big
- We don’t make a commit for every update
- Commit often with relevant changes(5 recommended)

JM-0 Page 2
- Commit often with relevant changes(5 recommended)
- Wording conversion (past tense -> fixed the bug rather then fix the bug)
Skipping the staging area:
git commit -a -m "message"
git commit -am "message" (a=All, m=message)
Removing Files : Should be removed from staging area and repository.
rm [Link] -> deletes file from working directory
But staging area contains the file , to check git ls-files
git add [Link]
git commit -m "msg"
Single command for this -> git rm [Link] *.txt -> removes file from staging area and working directory
Renaming and Moving Files:
mv [Link] [Link] -> unix command
git add [Link] [Link]
Single command -> git mv [Link] [Link] -> working and staging area
Ignoring Files:
Developers can have their own log files, it is not shared and synchronize with other team members
mkdir logs -> echo hello > logs/[Link] -> creates a log file into logs directory
To ignore files -> .gitignore file - This file has no name and it has only the extension and it should be created in the root
of the project
echo logs/ > .gitignore -> echo to create, write and display file
code .gitignore to open the file with VScode
Add the file path, file and directory to be ignored and not being staged
Gitignore works only when we have already included file/directory in our repository
We should stage the files separately from the directory so that it will be in tracked stage
After staging the file and directory, if we include it in gitignore then it doesn't work (not ignored since it is already in the
staging area)
To view the files in staging area -> git ls-files
To remove file from staging area:
git rm -h -> all the flags used with rm command
git rm --cached bin/ -> to remove empty directory
git rm --cached -r bin/ -> to remove directory recursively
After ignoring files if we again change the file it doesn't shows the changes in git and it doesn't track the file
Java .gitignore default files are *.class, *.log, *.ctxt
# -> comments in the git
Short Status:
git status -s -> gives the shortcut description for the files like M [Link] -> modified and ?? [Link] -> untracked file
Output is 2 columns, left column-> staging area, right column -> working directory (M->modified and A->Added)
Viewing Staging and unstaging changes:
git diff --staged -> staging area
Changes in the old copy indicated with - and changes to new copy indicated by +
For new file added in the staging area --- value will be null means previous data is not exists
git diff -> working directory changes -> unstagged
Visual Diff tools:
- KDiff3
- P4Merge
- WinMerge (windows only)
- VSCode
Using VSCode,
git config --global [Link] vscode -> default diff tool
git config --global [Link] "code --wait --diff $LOCAL $REMOTE"
where wait-> wait till we don't close the vscode, diff-> for difference, $LOCAL -> old copy place and $REMOTE for
new copy place
git config --global -e -> allows us to edit the global file(.gitconfig) in default editor

JM-0 Page 3
git config --global -e -> allows us to edit the global file(.gitconfig) in default editor
git difftool -> to launch the difftool comparing with working directory -> unstaging area
git difftool --staged -> launch with comparing staging area
Viewing the history:
git log -> views history of commits
Main/master/truck -> main branch
Head-> reference to current branch
git log --oneline -> to show the summary of logs (short description) id-> max 7 characters
git log --oneline --reverse -> to show in reverse order (old to new commits)
Viewing commits:
git show <id> / git show HEAD~ <steps> no of steps to go back, Head -> points to last commit
git show HEAD~1:<path of file> exact version stored in that commit
To see all the files and directories of the commits with meta data -> git ls-tree HEAD~1
Files are represented as blob and directories are represented as tree
git show <id> -> used to view the objects
Git Objects can be commits, Blobs(files), Trees (Directories), Tags
Unstaging Files:
Previous commands -> git reset --hard/--soft
New command -> git restore --staged [Link] [Link] or simply . -> used to remove file from staging area to working directory
Discarding local changes:
git restore [Link] or simply . For all
To clean all untracked file -> git clean -> options are -h,-f,-d where f-> force deletion, d-> directory deletion
Restoring a file to an Earlier version:
git restore --source-HEAD~1 [Link] -> f1 file was deleted, if it was in staging then moves to working, if it is repository then
moves to staging
To move commit from one branch to other branch : git cherry-pick <commit-hash>
Deleting a branch : git branch -d <branch-name> -> -D for force delete
Adding a remote repository -> git remote add origin <url>
Pushing changes -> git push origin <branch-name>
Pulling changes -> git pull origin <branch-name>
Fetching Updates (to view changes in remote without merging) -> git fetch
Discarding unstaged changes -> git checkout -- <file>
Resetting Commits
Undo commits while keeping changes:
git reset --soft HEAD~1 # Undo last commit but keep changes staged
git reset --mixed HEAD~1 # Undo last commit and unstage changes
git reset --hard HEAD~1 # Undo last commit and discard changes
Stash changes ( save uncommitted work temporarily) -> git stash
Apply stashed Changes -> git stash apply
View Stash list -> git stash list
Rewriting History
Amending the Last commit -> git commit --amend -m "Updated"
git rebase -i HEAD~n
Purpose: Rewrites the commit history interactively (e.g., clean up commit messages, squash commits).
• n is the number of commits from HEAD you'd like to rebase.
• Example: git rebase -i HEAD~3 lets you interactively edit the last 3 commits.
You’ll see a list of commits in an editor, where you can change pick to squash, reword, etc.
git squash
Purpose: Combine multiple commits into a single one (used during rebase).
• Used in interactive rebase by replacing pick with squash or s.
• Example:
pick abc123 Initial commit
squash def456 Added README
squash ghi789 Minor fix
This merges all 3 into one commit.

JM-0 Page 4
This merges all 3 into one commit.
git blame
Purpose: Shows who changed what and when in each line of a file.
• Syntax: git blame <filename>
• Example: git blame [Link]
• Great for debugging and understanding history.
Git Fast-forward Merge
Scenario: Happens when your branch is directly ahead of the target branch.
• Example: If main hasn't moved and feature has new commits, merging feature into main is fast-forward.
• Command: git merge feature
• No merge commit is created, just a pointer move.
Resolving Git Merge Conflicts
1. git revert
• Used to undo changes by creating a new commit that reverses the effects.
• Syntax: git revert <commit_hash>
• Does not change history, safe for shared branches.
2. git merge --abort
• Used to abort an in-progress merge if conflicts arise.
• Syntax: git merge --abort
• Returns you to the state before the merge began.
For a rebase conflict: Use git rebase --abort.
Git init -> sets local repository
• The staging area is a file called index inside your .git folder on your local machine’s disk.
• Git reads from and writes to this file to keep track of what’s staged.
Git Flow Strategies
1. git flow
A branching model by nvie:
• main: Production-ready code
• develop: Integration branch for features
• feature/*: Feature branches
• release/*: Pre-release testing
• hotfix/*: Urgent fixes on main
Commands require the git-flow extension:
• Start a feature: git flow feature start <name>
• Finish feature: git flow feature finish <name>
2. Trunk-Based Development
• All developers commit to a single shared branch (usually main or trunk).
• Encourages short-lived feature branches or feature flags.
• Promotes CI/CD, automation, and small incremental changes.
Lightweight and fast-moving; commonly used in DevOps, microservices, etc.
3. (Add-on) GitHub Flow
• Only main and short-lived feature branches.
• Create feature → Push to remote → Open PR → Review & merge.

JM-0 Page 5
Maven
08 January 2025 21:15

Maven is a powerful project management tool that is based on POM (project object model). It is used for
projects build, dependency and documentation. It simplifies the build process like ANT. But it is too much
advanced than ANT.
In short, maven is a tool that can be used for building and managing any Java-based project. Maven makes
the day-to-day work of Java developers easier and generally help with the comprehension of any Java-based
project.
Maven project creation :
mvn archetype:generate -DgroupId=ToolsQA -DartifactId=<project_name> -DarchetypeArtifactId=maven-archetype-
quickstart -DinteractiveMode=false
Project Structure:

The src/main/java directory contains the project source code, the src/test/java directory contains the test source, and
the [Link] file is the project's Project Object Model, or POM
[Link]:
The [Link] file is the core of a project's configuration in Maven. It is a single configuration file that contains the
majority of information required to build a project in just the way you want. The POM is huge and can be daunting in its
complexity, but it is not necessary to understand all of the intricacies just yet to use it effectively.

JM-0 Page 6
You executed the Maven goal archetype:generate, and passed in various parameters to that goal. The
prefix archetype is the plugin that provides the goal. If you are familiar with Ant(Apache Ant is a Java library and
command-line tool whose mission is to drive processes described in build files as targets and extension points
dependent upon each other. The main known usage of Ant is the build of Java applications.), you may conceive of this
as similar to a task. This archetype:generate goal created a simple project based upon a maven-archetype-
quickstart archetype. Suffice it to say for now that a plugin is a collection of goals with a general common purpose. For
example the jboss-maven-plugin, whose purpose is "deal with various jboss items".
Build the project : mvn package
A phase is a step in the build lifecycle, which is an ordered sequence of phases. When a phase is given, Maven executes
every phase in the sequence up to and including the one defined.

Maven Build Life Cycle:


• validate - validate the project is correct and all necessary information is available
• compile - compile the source code of the project
• test - test the compiled source code using a suitable unit testing framework. These tests should not require the
code be packaged or deployed
• package - take the compiled code and package it in its distributable format, such as a JAR.
• verify - run any checks on results of integration tests to ensure quality criteria are met
• install - install the package into the local repository, for use as a dependency in other projects locally
• deploy - done in the build environment, copies the final package to the remote repository for sharing with other
developers and project.

Maven Phases
Although hardly a comprehensive list, these are the most common default lifecycle phases executed.
• validate: validate the project is correct and all necessary information is available
• compile: compile the source code of the project
• test: test the compiled source code using a suitable unit testing framework. These tests should not require the
code be packaged or deployed
• package: take the compiled code and package it in its distributable format, such as a JAR.
• integration-test: process and deploy the package if necessary into an environment where integration tests
can be run

JM-0 Page 7
• verify: run any checks to verify the package is valid and meets quality criteria
• install: install the package into the local repository, for use as a dependency in other projects locally
• deploy: done in an integration or release environment, copies the final package to the remote repository for
sharing with other developers and projects.
There are two other Maven lifecycles of note beyond the default list above. They are
• clean: cleans up artifacts created by prior builds
• site: generates site documentation for this project

Maven Commands:
Some basic Maven commands includes:
• mvn clean: Cleans the project and removes all files generated by the previous build.
• mvn compile: Compiles source code of the project.
• mvn test-compile: Compiles the test source code.
• mvn test: Runs tests for the project.
• mvn package: Creates JAR or WAR file for the project to convert it into a distributable format.
• mvn install: Deploys the packaged JAR/ WAR file to the local repository.
• mvn site: generate the project documentation.
• mvn validate: validate the project’s POM and configuration.
• mvn idea:idea: generate project files for IntelliJ IDEA or Eclipse.
• mvn release:perform: Performs a release build.
• mvn deploy: Copies the packaged JAR/ WAR file to the remote repository after compiling, running tests and
building the project.
• mvn archetype:generate: This command is used to generate a new project from an archetype, which is a
template for a project. This command is typically used to create new projects based on a specific pattern or
structure.
• mvn dependency:tree: This command is used to display the dependencies of the project in a tree format.
Used in troubleshooting.
Generally when we run any of the above commands in combine form,
mvn clean install
mvn -X install -> if we want to run the step in debug mode for more detailed build information and logs
mvn install -DskipTests->if we do not want to run the tests while packaging or installing the Java project.

JM-0 Page 8
Core Java
09 January 2025 10:44

Elements of a Java Application


Compiling and Executing Java code
- javac [Link]
- java className

You can use simply java [Link] for compiling and executing in one step.
Creating first java Class

Setting classpath in environment variable -


- set JAVA_HOME=D:\jdk\jdk-22
- Set PATH=%JAVA_HOME%\bin;%PATH%
Running the program
Java Language Basics:
1. Creating a variables and naming them
Variables - an object stores its state in fields
- Instance Variables (Non-static fields) : Their values are unique to each instance of a class.
- Class Variables (Static fields) : Tells compiler that there is exactly one copy of this variable in existence.
- Local Variables : Method will often store its temporary state in local variables.
- Parameters : variables in the method definition like args[].
A type's fields, methods, and nested types are collectively called its members.
Variables are case sensitive. It contains letters, digits, $ and _ .
- Constant names are capitalized
- One or more word variable uses camel-case
2. Creating primitive type variables in your programs

JM-0 Page 9
byte - 1 Byte (-128 to 127) signed two's complement integer - 0
short - 2 Byte (-32,768 to 32,767) signed two's complement integer - 0
int - default type - 4 Byte (-2^31 to (2^31)-1) - 0
signed two's complement integer
long - 8 byte (-2^63 to (2^63)-1) signed two's complement integer - 0L
float - 4 byte single-precision - 0.0f
double - default type - 8 byte - 0.0d
boolean - 1 bit (true/false) - false
char - 2 byte (\u0000-0 to \uffff-65,535) - \u0000
String - any object has default null reference.
Decimal - Base 10 (0-9)
Hexadecimal - Base 16 (0-9,A-F)
Binary - Base 2 (0,1)
Octal - Base 8 (0-7) if number starts with 0 then its considered as octal number
Special escape sequence for char and string literals are \b->backspace, \t->tab, \n-> linefeed, \f-> formfeed, \r->
carriage return, \"-> double quote, \'-> single quote, \\ backslash.
any number of underscore characters (_) can appear anywhere between digits in a numerical literal.
You can place underscores only between digits; you cannot place underscores in the following places:
• At the beginning or end of a number
• Adjacent to a decimal point in a floating point literal
• Prior to an F or L suffix
• In positions where a string of digits is expected
3. Creating arrays in your programs
An array is a container object that holds a fixed number of values of a single type. Indexing begins with 0.
Creating, Initiating, Accessing an Array:
int[] arr=new int[size];
Copying Arrays : System class has an arraycopy()
public static void arraycopy(Object src, int srcPos,
Object dest, int destPos, int length)
Array Manipulators : [Link]
- binarySearch()
- equals()
- fill()
- sort()
- parallelSort()
- stream()
- toString()
4. Using the var type Identifier
var type identifier to declare a local variable.
var message="hfd"
var path=[Link]("[Link]")
Restrictions of using var:

JM-0 Page 10
Restrictions of using var:
- Can be used as local variable in method, constructors, and initializer blocks.
- Cannot be used for fields, method or constructor parameters.
- Compiler must be able to choose a type when it is declared.
5. Using operators in your programs
Assignment operator : =
Arithmetic operator : +, -, *, /, %
Unary operator : +, -, ++, --, !
Relational/Equality operator : ==, !=, >, >=, <, <=
Conditional operator : &&, || -> exhibit short-circuiting
Ternary operator : ?:
Type Comparison operator : instanceof -> obj1 instanceof obj2
Bitwise operator : ~, <<, >>, >>>, &, |, ^
6. Summary of operators
7. Expressions, statements and blocks
An expression is a construct made up of variables, operators, and method invocations, which are constructed according
to the syntax of the language, that evaluates to a single value
Example : double d1 = 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1; d1!=1.0
A statement forms a complete unit of execution.
Types of expressions can be made into a statement by terminating the expression with a semicolon (;).
Example : a value=345;
A block is a group of zero or more statements between balanced braces and can be used anywhere a single statement is
allowed.
8. Control flow statements
Conditional statement ->If-then, if-then-else, nested if-else, switch
Looping statement -> while, do-while, for
branching statement -> break(labeled and unlabeled), continue, return, yield - The yield statement exits from the
current switch expression it is in. A yield statement is always followed by an expression that must produce a value. This
expression must not be void.
9. Branching with switch statements
The type of your selector variable among the following types:
byte, short, char, and int primitive data types
Character, Byte, Short, and Integer wrapper types
enumerated types
the String type.
The selector variable of a switch statement can be an object, so this object can be null. will throw a
NullPointerException.
10. Branching with switch expressions
In Java SE 14 you can use another, more convenient syntax for the switch keyword,
The syntax of switch label is now case L ->. Only the code to the right of the label is executed if the label is matched.

JM-0 Page 11
Collection Framework
09 January 2025 10:45

It includes interfaces like Collection, Map, and Iterator.


Collections includes interfaces like List, Set and Queue
It contains classes like ArrayList, Vector, LinkedList, PriorityQueue, HashSet, LinkedHashSet, TreeSet

Collection Methods:

Iterator Interface:
An iterator in Java is an interface that provides a way to access elements of a collection (like lists, sets, or maps) one at a
time, without exposing the underlying details of the collection's structure. It allows you to traverse through the elements

JM-0 Page 12
time, without exposing the underlying details of the collection's structure. It allows you to traverse through the elements
in a collection sequentially in forward direction only.
It has some important methods:
- hasNext(): Checks if there are more elements to iterate over and returns a boolean value.
- next(): Returns the next element in the collection.
- remove(): Removes the last element returned by next().
Iterator<String> iterator = [Link]();

List Interface:

JM-0 Page 13
List Interface:
The List interface represents an ordered collection of elements. It allows duplicate elements and provides methods to
access, insert, update, and remove elements at specific positions within the list.

ArrayList : An ArrayList in Java is a dynamic and ordered collection that can grow or shrink in size as needed. It is used to
store and manage a list of elements. ArrayList allows for easy insertion, retrieval, and removal of elements, making it a
versatile data structure for working with collections of data in Java programs. It provides the benefits of an array with
the added flexibility of automatic resizing, making it a popular choice for many programming tasks.

What is the RandomAccess interface?


• RandomAccess is a marker interface in Java (it has no methods) defined in the [Link] package.
• It is used to indicate that a List 7 implementation supports fast (usually O(1)) random access to its elements by
index.

JM-0 Page 14
LinkedList : A Linked List is a linear data structure in Java that consists of a sequence of elements, where each element
points to the next one in the sequence. It's made up of nodes, where each node holds both data and a reference (or link)
to the next node in the list. Unlike an array, a Linked List can efficiently insert or remove elements at any position in the
list, making it a flexible choice for certain data manipulation tasks. Linked Lists are often used when dynamic data
storage and efficient insertions and deletions are required in Java programs.

JM-0 Page 15
Vector : A Vector in Java is a dynamic, resizable array-like data structure .It's similar to an ArrayList but is synchronized,
which means it is thread-safe. Vectors can grow or shrink in size as needed, making them suitable for situations where
the size of the collection may change dynamically. They are primarily used when you need a collection that can be
accessed by multiple threads without the risk of data corruption.

Stack : A stack in Java is a linear data structure that follows the Last-In-First-Out (LIFO) principle. It is the subclass of
Vector and operates like a collection of items where you can only add or remove elements from the top, similar to a
stack of plates. Elements are added to the top of the stack and removed from the top as well. This means that the last
element added to the stack is the first one to be removed. Stacks are often used for tasks that require keeping track of
the order of elements, such as managing function calls in recursion, undo functionality in applications, or browser history
navigation.

Queue Interface :
The Queue interface in Java represents a collection that holds elements in a linear order and allows adding elements at
one end (enqueue) and removing elements from the other end (dequeue). It follows the "first-in-first-out" (FIFO)
principle, similar to a real-world queue. Queues are often used for tasks like managing tasks in a printer queue or
processing tasks in a concurrent system.

JM-0 Page 16
PriorityQueue Class :
The PriorityQueue class in Java is an implementation of the Queue interface that provides a priority-based ordering of
elements. Elements in a PriorityQueue are ordered based on their natural order or according to a specified comparator.
The element with the highest priority (according to the defined order) is always at the front and will be the first to be
removed when dequeued. This makes PriorityQueue suitable for tasks like task scheduling, job processing, or managing
elements with priorities.

Deque Interface :
The Deque (pronounced as "deck") interface in Java stands for "Double Ended Queue." It is a linear collection that
supports adding and removing elements from both ends, i.e., both the front and the rear. A Deque interface extends the
Queue interface, adding methods for operations at both ends of the queue, making it versatile for various data
manipulation scenarios.

ArrayDeque : (Stack+Queue)
An ArrayDeque in Java is a double-ended queue (Deque) implemented as a resizable array. It allows you to add and
remove elements from both ends efficiently, making it a versatile choice for various data structure operations. Unlike a
traditional array, an ArrayDeque can dynamically resize itself to accommodate elements as they are added. This data
structure is often used in scenarios where you need a queue or stack-like behaviour, and it provides constant time (O(1))
performance for basic operations like adding and removing elements from both ends.
Set Interface :
The Set interface represents an unordered collection of unique elements. Unlike lists, sets do not allow duplicate values,
making them ideal for scenarios where you need to ensure distinct elements. The Set interface includes several methods
for adding, removing, and checking the presence of elements. Popular implementations of the Set interface are HashSet,
LinkedHashSet, and TreeSet, each with its own characteristics and use cases. By using Set, you can efficiently manage
collections of elements without worrying about duplicates, making it a valuable tool in Java programming.

JM-0 Page 17
Hash Set :
HashSet provides a collection of unique elements without any specific order. This means that you can store elements in
a HashSet, and it will automatically ensure that duplicates are not allowed. It is highly efficient for checking the presence
of elements and adding or removing elements from the set. While elements are not stored in a particular sequence, this
data structure is particularly useful when you need to maintain a collection of items where uniqueness is a priority, and
the order of elements doesn't matter.
LinkedHashSet :
LinkedHashSet combines the features of both HashSet and LinkedHashMap, offering a collection of unique elements
with predictable iteration order. Unlike HashSet, LinkedHashSet maintains the order in which elements were inserted
into the set. This means that when you iterate over a LinkedHashSet, the elements will be returned in the order they
were added. This can be useful in situations where you need both uniqueness and a specific order for your elements.
TreeSet :
A TreeSet is a sorted collection in Java that implements the Set interface. Unlike a HashSet, which does not guarantee
any specific order of elements, a TreeSet maintains elements in sorted order. This sorting is typically in ascending order,
but you can customize it by providing a comparator during TreeSet creation. TreeSet uses a Red-Black Tree data
structure internally for efficient sorting and retrieval operations.
Map Interface:
The Map interface in Java represents a collection of key-value pairs, where each key is unique and maps to a specific
value. It allows for efficient data retrieval based on keys, making it useful for tasks like looking up values by identifiers.
Java provides various implementations of the Map interface, such as HashMap, TreeMap, and LinkedHashMap, each
suited for different use cases. Maps are commonly used to store and manage data where the relationship between keys
and values is critical. They enable quick and direct access to values based on their associated keys, enhancing the
efficiency of data retrieval and manipulation in Java programs.

JM-0 Page 18
HashMap:
A HashMap in Java is a fundamental data structure that facilitates the storage and retrieval of data using key-value pairs.
It is a part of the Java Collections Framework and provides efficient access to values based on their associated keys.
HashMaps use a hash function to compute an index into an array where the values are stored, making retrieval swift
even for large datasets. They do not allow duplicate keys and permit one null key along with multiple null values. Java
developers frequently use HashMaps to implement data structures like dictionaries and associative arrays, where data is
organized and accessed by unique keys, enabling efficient and fast data retrieval in various applications.
HashTable :
A HashTable is similar to a HashMap but has several differences. A HashTable is a synchronized collection, which means
it is thread-safe and can be used in multi-threaded applications without the need for external synchronization. It uses a
hash function to map keys to values, allowing for efficient key-value retrieval. However, HashTable has become
somewhat outdated, and it is recommended to use HashMap in most cases, as it offers similar functionality but is not
synchronized, making it more efficient for single-threaded applications. Additionally, HashTable does not allow null keys
or values, whereas HashMap permits one null key and multiple null values.

LinkedHashMap :
A LinkedHashMap in Java is a class that combines the features of a hash table and a linked list to store key-value pairs. It
maintains the order of elements based on the insertion sequence, allowing predictable iteration. This means that when
you iterate through a LinkedHashMap, the elements are returned in the order in which they were added. It provides
efficient access to elements via hashing and preserves the order of insertion, making it useful for scenarios where you

JM-0 Page 19
efficient access to elements via hashing and preserves the order of insertion, making it useful for scenarios where you
need both quick access to elements and a predictable iteration order.
TreeMap:
A TreeMap is a class in Java that implements the Map interface and extends the AbstractMap class. It is part of the Java
Collections Framework and provides a Red-Black tree-based implementation of the Map interface. TreeMap stores its
elements in a sorted and balanced tree structure, which allows for efficient operations like insertion, deletion, and
retrieval of elements.
Internal Structure of HashMap :
HashMap is an associative array data structure. Stores data in the form of key-value pair.
HashMap works an the basis of hashing.
Hashing uses the hashCode() which is coming from the Object class.
Default bucket size created when the HashMap is declared is 16.

JM-0 Page 20
Exception handling
09 January 2025 10:45

Java Exception handling is a technique for handling different types of errors.


Exception : Exceptions are unwanted events that disrupt the program's execution. Many a time, your program looks
error-free after writing the code. But, at the time of execution, some unexpected errors or events or objects come to the
surface, and the program prints an error message and stops executing. Such unexpected happenings are called exceptions
in Java.
Reasons for exception
• User's Invalid input
• Database Connection Error
• System failure
• Network Problem
• Security Compromises
• Errors in code
• Physical Limitations
Exception Handling : Exception Handling is a way of handling errors that occur during runtime and compile time. It
maintains your program flow despite runtime errors in the code and, thus, prevents unanticipated crashes. It facilitates
troubleshooting by providing error details, cutting down on development time, and improving user happiness.

Errors: An error is a severe condition that can occur only at run time and is irrecoverable. It prevents a program from
executing and cannot be handled by the programmer. An error belongs to the [Link] class.
Exceptions: A programmer can catch and handle exceptions in his program code. When an exception occurs within a
method, an object called the exception object is created. This object contains information about the exception, such as its
name and description and the state of the program when the exception occurred.

JM-0 Page 21
There are two types of built-in exceptions in Java:
1. Checked Exception
Checked exceptions are classes that inherit directly from the Throwable class, with the exception of RuntimeException
and Error. Examples include IOException, SQLException, and so on. Checked exceptions are checked at compilation time.
They must be either caught by the code or declared in the method signature using the throws keyword.
2. Unchecked Exception
Classes that inherit the RuntimeException class are known as unchecked exceptions. Examples include
ArithmeticException, NullPointerException, and ArrayIndexOutOfBoundsException. Unchecked exceptions are not
checked at compile-time but rather at runtime by JVM. They do not need to be explicitly caught or declared.
User-Defined Exceptions :
User-defined exceptions are also known as custom exceptions derived from the Exception class from [Link] package.
The user creates these exceptions according to different situations. Such exceptions are handled using five keywords: try,
catch, throw, throws, and finally.

Java Exception Handling :

JM-0 Page 22
Try :
A try block consists of all the doubtful statements that can throw exceptions.
A try block cannot be executed on itself; it requires at least one catch block or finally block.
If an exception occurs, the control flows from the try-to-catch block.
When an exception occurs in a try block, the appropriate exception object is redirected to the catch block. This catch
block handles the exception according to its statements and continues the execution.
Catch:
The catch block handles the exception raised in the try block.
The catch block or blocks follow every try block.
The catch block catches the thrown exception as its parameter and executes the statements inside it.
The declared exception must be the parent class exception, the generated exception type in the exception class hierarchy,
or a user-defined exception.
Finally :
The finally block in Java always executes even if there are no exceptions. This is an optional block. It is used to execute
important statements such as closing statements, releasing resources, and releasing memory. There could be one final
block for every try block. This finally block executes after the try...catch block.

JM-0 Page 23
Throw :
The throw keyword is used to explicitly throw a checked or an unchecked exception.
The exception that is thrown needs to be of type Throwable or a subclass of Throwable.
We can also define our own set of conditions for which we can throw an exception explicitly using the throw keyword.
The program's execution flow stops immediately after the throw statement is executed, and the nearest try block is
checked to see if it has a catch statement that matches the type of exception.
Throws:
The throws keyword is used in the method signature to indicate that a method in Java can throw particular exceptions.
This notifies the method that it must manage or propagate these exceptions to the caller.

Advantages of Exception Handling in Java


It helps to find which type of errors occur.
It helps to complete the program executions.
It allows the program to run continuously without any disruption.

JM-0 Page 24
It allows the program to run continuously without any disruption.
It provides the ability to catch the specific exception that occurred in the program.
It also helps the developers to write cleaner code and learn how to handle exceptions.

JM-0 Page 25
Generics
09 January 2025 10:45

Generics in Java are a powerful feature that enables developers to write flexible, reusable, and type-safe code.
Generics allow types (classes and interfaces) to be parameters when defining classes, interfaces, and methods. This
helps in creating code that works with any type and ensures type safety at compile-time.
Primitive Types: Java generics cannot use primitive types. For example, you must use Integer instead of int.
Type Safety: Generics provide compile-time type checking, reducing runtime errors.
Type Inference: Java can often infer the type parameter from the context, making the code cleaner.
Generic Classes
Generic classes enable you to create classes that can operate on any type specified at instantiation.
Type Parameters: Define the type parameter in angle brackets (<T>).
Multiple Type Parameters: You can define multiple type parameters (<K, V>).
Type Erasure: The compiler replaces generic types with their bounds or Object during compilation.

Generic Methods
Generic methods allow you to create methods that can operate on any type.
Type Parameters: Define the type parameter before the return type (<T>).
Static Methods: Generic type parameters can be used in static methods.
Varargs: Use @SafeVarargs annotation to suppress warnings when using varargs with generics.

JM-0 Page 26
Bounded Type Parameters
Bounded type parameters restrict the types that can be used as generics, providing more control.
Upper Bounds: Use <T extends Class> to restrict to subclasses of a specific class.
Multiple Bounds: Use <T extends Class1 & Interface1> for multiple bounds.
Lower Bounds: Use the super keyword in wildcards for lower bounds

Generic Interfaces
Generic interfaces allow you to define interfaces that can be implemented by any class with a specific type.
Type Parameters: Define the type parameter in the interface.
Implementation: Implementing classes must specify or inherit the type parameter.
Multiple Interfaces: A class can implement multiple generic interfaces.

JM-0 Page 27
Wildcards in Generics
Wildcards provide flexibility in generics, especially when working with collections of unknown types.
Unbounded Wildcards: Use <?> when the type is unknown.
Upper Bounded Wildcards: Use <? extends T> to specify an upper bound.
Lower Bounded Wildcards: Use <? super T> to specify a lower bound.
Implementing a Generic Cache
A generic cache can store objects of any type and provide efficient retrieval.
Type Safety: Ensure that the cache maintains type safety.
Key-Value Pairs: Use appropriate type parameters for keys and values.
Thread Safety: Consider thread safety for concurrent access.
Using Generics with Comparator
Generics can be used with Comparator to create flexible sorting logic.
Comparable Interface: Use the Comparable interface for natural ordering.
Custom Comparators: Implement custom comparators for specific ordering.
Type Safety: Ensure type safety in comparisons.
Multi-Level Generics
Generics can be used in complex scenarios involving multiple levels.
Nested Generics: Understand the nesting of generics in class hierarchies.
Type Parameter Propagation: Ensure type parameters are correctly propagated.
Flexibility: Multi-level generics provide enhanced flexibility and reusability.
Generic Utilities for BigDecimal
Generics can be particularly useful when dealing with financial calculations, where BigDecimal is often used.
Precision: Ensure precision is maintained with BigDecimal.
Type Safety: Utilize generics to maintain type safety in financial utilities.
Reusability: Generic utilities enhance reusability across different financial calculations.

JM-0 Page 28
String/StringBuilder/StringBuffer
09 January 2025 10:46

Strings are immutable in Java. This means we cannot manipulate the value of a String object. If we modify the value
of a String object in Java, a new String object with the modified value will be created in the heap memory.
StringBuilder and StringBuffer classes are used to provide us with the functionality of mutable Strings in Java.
StringBuffer provides us with strings that are safe to use with multiple threads but this added functionality also
makes it slower. StringBuilder lacks thread safety but because it does not have this added functionality, it has faster
implementation.
Strings in Java
Java program makes I/O operations only with strings. A string is a sequence of characters like “apple”, “1234”.
String class enables us to declare and define a string [Link] objects are immutable in nature. Whenever a
String object is manipulated it does not affect the original object rather it creates a new object and assigns the new
manipulated value to it.

Java StringBuffer Class


It provides us with a way to use mutable strings in Java. These strings are safe to be used by multiple threads
simultaneously. In order to give this advantage to the StringBuffer, the implementation of this class becomes less
time efficient. Thread-safe and synchronized
Syntax: StringBuffer a = new StringBuffer("Scaler");

Java StringBuilder Class


StringBuilder class also provides us with mutable strings but here we lack thread safety. It cannot be used by
multiple threads simultaneously. Since StringBuilder class is not applying this extra feature like StringBuffer, it is
faster than StringBuffer class. Thread-unsafe and not synchronized
Syntax: StringBuilder a = new StringBuilder("Scaler");

JM-0 Page 29
Performance :

String methods:

JM-0 Page 30
JM-0 Page 31
Annotation
16 January 2025 11:18

Annotations are used to provide supplemental information about a program.


Annotations start with ‘@’.
Annotations do not change the action of a compiled program.
Annotations help to associate metadata (information) to the program elements i.e. instance variables, constructors,
methods, classes, etc.
Annotations are not pure comments as they can change the way a program is treated by the compiler
Annotations basically are used to provide additional information, so could be an alternative to XML and Java marker
interfaces.
Hierarchy:

Categories of Annotations
1. Marker Annotations
2. Single value Annotations
3. Full Annotations
4. Type Annotations
5. Repeating Annotations
Marker Annotations
The only purpose is to mark a declaration. These annotations contain no members and do not consist of any data. Thus, its
presence as an annotation is sufficient. Since the marker interface contains no members, simply determining whether it is
present or absent is sufficient. @Override is an example of Marker Annotation.
Example - @TestAnnotation()

Single value Annotations


These annotations contain only one member and allow a shorthand form of specifying the value of the member. We only
need to specify the value for that member when the annotation is applied and don’t need to specify the name of the
member. However, in order to use this shorthand, the name of the member must be a value.
Example - @TestAnnotation(“testing”);

Full Annotations
These annotations consist of multiple data members, names, values, pairs.

JM-0 Page 32
These annotations consist of multiple data members, names, values, pairs.
Example - @TestAnnotation(owner=”Rahul”, value=”Class Geeks”)

Type Annotations
These annotations can be applied to any place where a type is being used. These are declared annotated with @Target
annotation.
Example - @Target(ElementType.TYPE_USE)

Repeating Annotations
These are the annotations that can be applied to a single item more than once. For an annotation to be repeatable it must
be annotated with the @Repeatable annotation, which is defined in the [Link] package. Its value field
specifies the container type for the repeatable annotation. The container is specified as an annotation whose value field is
an array of the repeatable annotation type. Hence, to create a repeatable annotation, firstly the container annotation is
created, and then the annotation type is specified as an argument to the @Repeatable annotation.

Predefined/ Standard Annotations


Java popularly defines seven built-in annotations as we have seen up in the hierarchy diagram.
Four are imported from [Link]: @Retention, @Documented, @Target, and @Inherited.
Three are included in [Link]: @Deprecated, @Override and @SuppressWarnings
@Deprecated
It is a marker annotation. It indicates that a declaration is obsolete and has been replaced by a newer form.
The Javadoc @deprecated tag should be used when an element has been deprecated.
@deprecated tag is for documentation and @Deprecated annotation is for runtime reflection.
@deprecated tag has higher priority than @Deprecated annotation when both are together used.

JM-0 Page 33
@deprecated tag has higher priority than @Deprecated annotation when both are together used.

@Override
It is a marker annotation that can be used only on methods. A method annotated with @Override must override a method
from a superclass. If it doesn’t, a compile-time error will result. It is used to ensure that a superclass method is actually
overridden, and not simply overloaded.

@SuppressWarnings
It is used to inform the compiler to suppress specified compiler warnings. The warnings to suppress are specified by name,
in string form. This type of annotation can be applied to any type of declaration.
Java groups warnings under two categories. They are deprecated and unchecked. Any unchecked warning is generated
when a legacy code interfaces with a code that uses generics.

@Documented
It is a marker interface that tells a tool that an annotation is to be documented. Annotations are not included in ‘Javadoc’
comments. The use of @Documented annotation in the code enables tools like Javadoc to process it and include the
annotation type information in the generated document.

@Target
It is designed to be used only as an annotation to another annotation. @Target takes one argument, which must be
constant from the ElementType enumeration. This argument specifies the type of declarations to which the annotation
can be applied.

@Retention
It determines where and how long the annotation is retent. The 3 values that the @Retention annotation can have:
SOURCE: Annotations will be retained at the source level and ignored by the compiler.

JM-0 Page 34
SOURCE: Annotations will be retained at the source level and ignored by the compiler.
CLASS: Annotations will be retained at compile-time and ignored by the JVM.
RUNTIME: These will be retained at runtime.

@Inherited
@Inherited is a marker annotation that can be used only on annotation declaration. It affects only annotations that will be
used on class declarations. @Inherited causes the annotation for a superclass to be inherited by a subclass. Therefore,
when a request for a specific annotation is made to the subclass, if that annotation is not present in the subclass, then its
superclass is checked. If that annotation is present in the superclass, and if it is annotated with @Inherited, then that
annotation will be returned.

User-defined (Custom)
User-defined annotations can be used to annotate program elements, i.e. variables, constructors, methods, etc. These
annotations can be applied just before the declaration of an element (constructor, method, classes, etc).
Syntax:
[Access Specifier] @interface <AnnotationName>
{
DataType <Method Name>() [default value];
}

JM-0 Page 35
Optional Class
16 January 2025 11:37

Optional is a generic class defined in the [Link] package, that got introduced in Java 8.
It facilitates the handling of potentially absent values in a more concise and expressive manner.
It provides a container-like structure to wrap objects, indicating the possibility of a value being present or absent.
Its primary purpose is to provide a safer alternative to handling null values, thereby reducing the risk of NullPointerException.
By explicitly acknowledging the possibility of an absent value, Optional encourages developers to write more robust and error-
resistant
Creating optional instances:
- [Link](T value)

If contains null value then throws NullPointerException


- [Link](T value)

Can contain null value which is considered as empty-> output =[Link]


- [Link]() - no value/null value

Methods and Usage :


1. boolean isPresent():
Returns true if the Optional contains a non-null value, otherwise returns false.

2. T get():
Returns the value wrapped by the Optional if present.
Throws: NoSuchElementException if the Optional is empty.

3. T orElse(T defaultValue):
Returns the value wrapped by the Optional if present.
Returns: defaultValue if the Optional is empty.

4. T orElseGet(Supplier<? extends T> supplier):


Returns the value wrapped by the Optional if present.
Invokes the supplier function to provide an alternative value if the Optional is empty.

JM-0 Page 36
5. T orElseThrow(Supplier<? Extends X> exceptionSupplier):
Returns the value wrapped by the Optional if present.
Throws an exception produced by the exceptionSupplier if the Optional is empty.

6. void ifPresent(Consumer<? super T> consumer):


Executes the specified consumer function with the value wrapped by the Optional if present.

JM-0 Page 37
Comparator and Comparable
16 January 2025 12:10

Comparator Interface:
Comparator interface in java is used to order the objects of user-defined classes. A comparator object is capable of comparing
two objects of same class.
Syntax - public int compare(Object obj1,Object obj2)
Alternative method - [Link]([Link](Class::Field1).thenComparing(Class::Field2));
int compare(T o1, T o2)
static Comparator<T> comparing(Function<? super T,? extends U> keyExtractor)
static Comparator<T> comparingDouble(ToDoubleFunction<? super T> keyExtractor)
static Comparator<T> comparingInt(ToIntFunction<? super T> keyExtractor)
static Comparator<T> comparingLong(ToLongFunction<? super T> keyExtractor)
boolean equals(Object obj)
static Comparator<T> naturalOrder()
static Comparator<T> nullsFirst(Comparator<? super T> comparator)
static Comparator<T> nullsLast(Comparator<? super T> comparator)
default Comparator<T> reversed() - returns comparator that contains reverse ordering of the provided comparator.
static Comparator<T> reverseOrder() - returns comparator that contains reverse of natural ordering.
default Comparator<T> thenComparing(Comparator<? super T> other) - returns a lexicographic-order comparator with
another comparator.
default Comparator<T> thenComparingDouble(ToDoubleFunction<? super T> keyExtractor)
default Comparator<T> thenComparingInt(ToIntFunction<? super T> keyExtractor)
default Comparator<T> thenComparingLong(ToLongFunction<? super T> keyExtractor)
Comparable Interface:
The Comparable interface in Java is used to define the natural ordering of objects for a user-defined class. It is part of the
[Link] package and it provides a compareTo() method to compare instances of the class. A class has to implement a
Comparable interface to define its natural ordering.
Syntax -
public interface Comparable<T> {
int compareTo(T obj);
}
It compares the current object with the specified object.
It returns:
Negative, if currentObj < specifiedObj.
Zero, if currentObj == specifiedObj.
Positive, if currentObj > specifiedobj.

JM-0 Page 38
JM-0 Page 39
Collections Class
20 May 2025 12:08

Java's Collections class (in [Link]) is a utility class that provides static methods to operate on or return collections
like List, Set, and Map.
🧰 Commonly Used Collections Methods
🔁 Sorting & Shuffling
[Link](list); // Sorts list in natural order
[Link](list, comparator); // Sorts with custom comparator
[Link](list); // Reverses the order of list
[Link](list); // Randomly shuffles the list
🔍 Searching
[Link](list, key); // Binary search (must be sorted)
[Link](collection); // Max element
[Link](collection); // Min element
🔒 Synchronization (Thread-Safe Wrappers)
[Link](list);
[Link](set);
[Link](map);
🧱 Immutability
Collec [Link]fiableList(list);
Collec [Link]fiableSet(set);
Collec [Link]fiableMap(map);
♻ Filling, Copying, Replacing
[Link](list, value); // Replace all with value
[Link](destList, srcList); // Copy source into dest (dest must be same size or bigger)
[Link](list, oldVal, newVal); // Replace all oldVal with newVal
🆕 Singletons, Empty Collections
[Link](); // Returns empty list
[Link]("A"); // Returns an immutable singleton set
[Link]("A"); // Singleton list
🔄 Frequency & Disjoint
[Link](list, value); // Count of value
[Link](list1, list2); // True if no common elements

JM-0 Page 40
Functional Interface
20 January 2025 14:51

A functional Interface is an interface that contains only one abstract method (SAM - Single Abstract Method). Functional
Interface serves as the target type for lambda expressions and method references.
Syntax - @FunctionalInterface
interface <Name>{
<method>;
}
Built-in functional Interface:
- Consumer : A consumer is a functional interface that represents an operation that takes a single input and performs
some action on it. It does not return any value.
@FunctionalInterface
interface Consumer<T>{
void accept(T t);
}

- Supplier : A supplier is a functional interface that represents an operation that supplies a result. It does not take any
input
@FunctionalInterface
interface Supplier<T>{
T get();
}

- Function : A function is a functional interface that represents an operation that takes an input of type 'T' and produces
an output of type 'R'
@FunctionalInterface
interface Function<T,R>{

JM-1 Page 1
interface Function<T,R>{
R apply(T t);
}

Methods:
1. apply : abstract method and instance method
the primary method of the Function interface. It takes one argument and returns a result.
2. andThen : Instance and default method
method returns a composed function that first applies this function to its input, and then applies the after function to
the result.
3. compose : instance and default method
method returns a composed function that first applies the before function to its input, and then applies this function
to the result.
4. Identity : static and default method
method returns a function that always returns its input argument.

Subclass of Function is UnaryOperator<T>


Method : static method = identity()
- Predicate : A predicate is a functional interface that represents an operation that takes an input of type 'T' and returns
a boolean result. It takes only object type parameter.
@FunctionalInterface
interface Predicate<T>{
boolean test(T t);
}

JM-1 Page 2
}

Custom Functional Interfaces :


To create a custom functional interface,
1. Define an interface with single abstract method that represents the functionality you want the lambda expression to
perform.
2. Optionally, use the '@FunctionalInterface' annotation to indicate that the interface is intended to be a functional
interface.
@FunctionalInterface
interface <Name>{
<method>;
}
Method References :
Method References provide a shorthand notation for lambda expressions that call only one method. They are especially
useful when lambda expression's sole purpose is to call an existing method. It is denoted by :: .
There are 4 types oof method references:
1. Reference to a static method : ClassName::staticMethodName
2. Reference to an Instance Method of a Particular Object : instance::instanceMethodName
3. Reference to an instance method of an Arbitrary Object of a Particular Type : ClassName::instanceMethodName
4. Reference to an Constructor : ClassName::new

JM-1 Page 3
Lambda Expressions
27 January 2025 14:29

The expression through which we can represent an anonymous function.


Syntax : () -> {//Body}
Where,
() - Parameter
-> - Expression
{} - body
Lambda Expressions are used for functional Interface
Functional Interface :
The interface who contains only one abstract method but can have multiple default and static method.
Ex: Runnable -> run()
Callable -> call()
Comparable -> compareTo()
Comparator -> compare()
Can be declared using @FunctionalInterface
Before Lambda:

JM-1 Page 4
Optional
21 January 2025 09:29

Purpose of the class is to provide a type-level solution for representing optional values instead of a null references.
Creating Optional Objects:
- To create an empty Optional object, need to use its empty() static method

- We can also create an Optional object with the static method of().

But if we expect some null values then we can use the ofNullable() method.

Checking Value Presence : isPresent() and isEmpty()


We can check if there is a value in it or not with the isPresent() method

isEmpty() -> If a value is not present, returns true, otherwise false.

JM-1 Page 5
Conditional Action :
If we use traditional code to check the null value, then this can result in a NullPointerException at runtime if a null value finds its way
into that code.
To handle this we use the Optional class
In typical functional programming style, we can execute perform an action on an object that is actually present

Default Value :
- orElse() : The orElse() is used to retrieve the value wrapped inside an Optional instance. It takes one parameter, which acts as a
default value. It takes object as input.

- orElseGet() : orElseGet() method is similar to orElse(). However, instead of taking a value to return if the Optional value is not
present, it takes a supplier functional interface, which is invoked and returns the value of the invocation.
If a value is present, returns the value, otherwise returns the result produced by the supplying function.

when using orElseGet() to retrieve the wrapped value, the getMyDefault() method is not even invoked since the contained value
is present. However, when using orElse(), whether the wrapped value is present or not, the default object is created. So in this
case, we have just created one redundant object that is never used.

JM-1 Page 6
- Exceptions with orElseThrow()
Instead of returning a default value when the wrapped value is not present, it throws an exception. Method can also be used
without arguments default exception-> NoSuchElementException.

- get() : get() can only return a value if the wrapped object is not null; otherwise, it throws a NoSuchElementException.
Syntax : public T get()
- filter() : It takes a predicate as an argument and returns an Optional object. If the wrapped value passes testing by the predicate,
then the Optional is returned as-is
Syntax : public Optional<T> filter(Predicate<? super T> predicate)
Throws NullPointerException -> if filter is null
- isPresent : returns true if there is a value or else false
Syntax : public boolean isPresent()
- ifPresent : if a value is present, invoke the specified consumer with the value, otherwise do nothing.
Throws NullPointerException -> if consumer is null
Syntax : public void ifPresent(Consumer<? super T> consumer)
- Map : If a value is present, apply the provided mapping function to it, and if the result is non-null, return an optional describing
the result.
Throws NullPointerException -> if mapping in null
Syntax : public <U> Optional<U> map(Function<? super T,? extends U> mapper)
- toString : returns a non-empty string representation of this optional suitable for debugging.
- Equals : overrides equals in class Object
Syntax : public boolean equals(Object obj)

JM-1 Page 7
Streams
24 January 2025 16:34

Stream API is used to process collections of objects.


A Stream is a sequence of objects that supports various methods which can be pipelined to produce the desired result.
It takes input from the Collections, Arrays or I/O channels.
They do not change the original data structure, they only provide the result as per the pipelined methods.

Package -> [Link]


Super Interfaces : AutoCloseable, BaseStream<T, Stream<T>>
Why we need Stream ?
- Functional Programming
- Code Reduce
- Bulk Operation
Map() and flatMap():
Java 8 Stream API provides map() and flatMap() method. Both these methods are intermediate methods and returns another stream
as a part of the output.
Map() used for transformation
flatMap() used for transformation and flattering
flatMap()->map()+flattering
Map() method -> Data transformation
Map() takes Stream<T> as input and return Stream<R>
Syntax : <R> Stream<R> map(Function<? Super T, ? extends R> mapper);
It's mapper function produces single value for each input value. Hence it is also called 1:1 mapping.
flatMap() method -> map()+flattering
flatMap() takes Stream<Stream<T>> as input and return Stream<R>
Syntax : <R> Stream<R> flatMap(Function<? super T, ? extends R>> mapper);
It's mapper function produces multiple value for each input value. Hence it is also called 1:M mapping.

JM-1 Page 8
Abstract Methods / Instance Methods / :
1. allMatch(Predicate) : returns whether all the elements of this stream match the provided predicate.
boolean allMatch(Predicate<? super T> predicate)
2. anyMatch(Predicate) : returns whether any elements of this stream match the provided predicate.
Boolean anyMatch(Predicate<? super T> predicate)
3. collect(Collector) : performs a mutable reduction operation on the elements of this stream using collector
<R,A> R collect(Collector<? super T,A,R> collector)
4. Collect(Supplier, BiConsumer, BiConsumer) : performs mutable reduction operation.
<R> R collect(Supplier<R> supplier, BiConsumer<R,? super T> accumulator, BiConsumer<R,R> combiner)
5. Count() : returns the count of elements in this stream
Long count()
6. Distinct() : returns a stream consisting of the distinct elements
Stream<T> distinct() -> [Link](Object)
7. Filter(Predicate) : returns a stream consisting of the elements of this stream that matches the given predicate.
Stream<T> filter(Predicate<? Super T> predicate)
8. findAny() : returns an Optional describing some element of the stream, or any empty Optional if the stream is empty.
Optional<T> findAny()
9. findFirst() : returns an Optional describing the first element of this stream, or an empty Optional if the stream is empty.
Optional<T> findFirst()
10. flatMap(Function) : returns a stream consisting of the results of replacing each element of this stream
<R> Stream<R> flatMap(Function)
DoubleStream flatMapToDouble(function)
IntStream flatMapToInt()
LongStream flatMapToLong()
11. forEach(Consumer) -> void
12. forEachOrdered(Consumer) -> void
13. Limit(long maxSize) -> Stream<T>
14. Map(Function) -> <R> Stream<R>
mapToDouble(Function)
mapToInt(Function)
mapToLong(Function)
15. Max(Comparator) -> Optional<T>

JM-1 Page 9
15. Max(Comparator) -> Optional<T>
16. Min(Comparator) -> Optional<T>
17. noneMatch(Predicate) -> boolean
18. Peek(Consumer) -> Stream<T>
19. Reduce(BinaryOperator) -> Optional<T>
Reduce(T identity, BinaryOperator) -> T
Reduce(U identity, BiFunction, BinaryOperator) -> <U> U
20. Skip(long) -> Stream<T>
21. Sorted() -> Stream<T>
Sorted(<Comparator>) -> Stream<T>
22. toArray() -> Object[]
toArray(IntFunction) -> <A> A[]
Static Methods / Default Methods:
1. Builder() : <T> [Link]<T>
2. Concat(Stream, Stream) : <T> Stream<T>
3. Empty() : <T> Stream<T>
4. Generate(Supplier) : <T> Stream<T>
5. Iterate(T seed, UnaryOperator) : <T> Stream<T>
6. Of(T… values) : <T> Stream<T>
Terminal and Intermediate Operators:

JM-1 Page 10
Record Class
29 January 2025 10:55

Record class by default extends [Link] class which is a common super abstract class of all record classes.
Introduced in java 14 but as integrated in java 16 as standard class.
Record classes are the special kind of classes, help to model plain data aggregates with less ceremony than normal classes.
In record, accessors, constructor, equals, hashCode, toString methods are created automatically.
Record are final and cannot extends any class, record but they can implements interface.
Record can be private but only in nested class or in a class which can be accessed within the class.
All fields are private and final by default and it can contain static variables.
The constructor can be modified in the record -> Canonical parameterized constructor
All methods are public and Records can be passed as a parameter to a method
We can also declare static fields, static initializers and static methods in record and behave same as normal class.
Cannot declare instance variables or instance initializers in record class.
All the methods and fields are by default public final.
Java allows method overloading, and method overloading depends on the method signature.
We can declare the instance methods in a record class, independent of whether you implement your own accessor methods.
We can also declare nested classes and interfaces in a record class, including nested record classes( which is implicitly static)
Features of Record classes :
1. Can create a generic record class
2. Can declare a record class that implements one or more interfaces.
3. Can annotate a record class and its individual components
Why use Records ?
- Immutability
- Efficiency
- Preservation of core logic rather than boiler codes
The class [Link] has two methods related to record classes:
- RecordComponent[] getRecordComponents(): Returns an array of [Link] objects, which
correspond to the record class's components.
- boolean isRecord(): Similar to isEnum() except that it returns true if the class was declared as a record class.

JM-1 Page 11
Sealed Classes
29 January 2025 10:21

A sealed class is a class that cannot be inherited by other classes. It is used to restrict the inheritance of a class, ensuring that no
other class can derive from it.
By sealing a class, we can specify which classes are permitted to extend it and prevent any other arbitrary class from doing so.
Declaring sealed classes:
Add the sealed modifier to its declaration. Then after any extends and implements clauses, add the permits clause.
If you have declared the permits class within the same file then you can omit the permits clause.

Constraints on permitted Subclasses :


1. They must be accessible by the sealed class at compile time.
2. They must directly extend the sealed class.
3. They must have exactly one of the modifiers to describe how it continues the sealing initiated by its superclass.
- Final : cannot be inherited further.
- Sealed : can only be extended by its permitted subclasses.
- Non-sealed : can be extended by unknown subclasses, sealed class cannot prevent its permitted subclasses from doing this.
4. They must be in the same module as the sealed class or in same package. If not you need to exports them in the main
package or explicitly give all the classes with the package names

Declaring sealed Interfaces :


To seal an interface, add the sealed modifier to its declaration. Then, after any extends clause, add the permits clause, which
specifies the classes that can implement the sealed interface and the interfaces that can extend the sealed interface.
Record classes as Permitted Subclasses.
We can name a record class in the permits clause of a sealed class or interface. Since record classes are implicitly final.
- Narrowing Reference Conversion and disjoint types :
Narrowing reference conversion is one of the conversions used in type checking cast expressions. It enables an expression of a
reference type S to be treated as an expression of a different reference type T, where S is not a subtype of T. A narrowing reference
conversion may require a test at run time to validate that a value of type S is a legitimate value of type T.

JM-1 Page 12
conversion may require a test at run time to validate that a value of type S is a legitimate value of type T.

The class UtahTeapot is final, it's impossible for a class to be a descendant of both Polygon and UtahTeapot. Therefore, Polygon and
UtahTeapot are disjoint, and the cast statement Polygon p = (Polygon) u isn't allowed.
APIs Related to Sealed Classes and Interfaces
The class [Link] has two new methods related to sealed classes and interfaces:
- [Link][] permittedSubclasses(): Returns an array containing [Link] objects
representing all the permitted subclasses of the class if it is sealed; returns an empty array if the class is not sealed
- boolean isSealed(): Returns true if the given class or interface is sealed; returns false otherwise

JM-1 Page 13
Collectors
29 January 2025 12:32

It implements the Collector interface


It is from [Link]
Collectors is final class and it extends the Object.
Implementations of Collector that implement various useful reduction operations, such as accumulating elements into
collections, summarizing elements according to various criteria, etc.
Methods :
1. averagingDouble(ToDoubleFunction) -> <T> Collector<T,?,Double>
averagingInt(ToIntFunction) -> <T> Collector<T,?,Double>
averagingLong(ToLongFunction) -> <T> Collection<T,?,Double>
2. collectingAndThen(Collector,Function) -> <T,A,R,RR> Collector<T,A,RR>
3. Counting() -> <T> Collector<T,?,Long>
4. groupingBy(Function) -> <T,K> Collector<T,?,Map<K,List<T>>>
groupingBy(Function, Collector) -> <T,K,A,D> Collector<T,?,Map<K,D>>
groupingBy(Function,Supplier,Collector) -> <T,K,D,A,M extends Map<K,D>> Collector<T,?,M>
groupingByConcurrent(Function) -> <T,K> Collector<T,?,ConcurrentMap<K,List<T>>>
groupingByConcurrent(Function,Collector)
groupingByConcurrent(Function,Supplier,Collector)
5. Joining() -> Collector<CharSequence,?,String>
6. Joining(CharSequence delimiter)
7. Joining(CharSequence delimiter, CharSequence prefix, CharSequence suffix)
8. Mapping(Function, Collector) -> <T,U,A,R> Collector<T,?,R>
9. maxBy(Comparator) -> max value
10. minBy(Comparator) -> min value
11. partitioningBy(Predicate) -> Map<Boolean, List<T>>
partitioningBy(Predicate,Collector)
12. Reducing(BinaryOperator) -> Optional<T>
Reducing(T identity, BinaryOperator)
Reducing(T identity, Function, BinaryOperator)
13. summarizingDouble(ToDoubleFunction)
summarizingInt(ToIntFunction)
summarizingLong(ToLongFunction)
14. summingDouble(ToDoubleFunction)
summingInt(ToIntFunction)
summingLong(ToLongFunction)
15. toCollection(Supplier)
16. toConcurrentMap(Function,Function)
toConcurrentMap(Function, Function, BinaryOperator)
toConcurrentMap(Function,Function,BinaryOperator, Supplier)
17. toList()
18. toMap(Function, Function)
toMap(Function, Function, BinaryOperator)
toMap(Function, Function, BinaryOperator, Supplier)
19. toSet()

JM-1 Page 14
Clean Code
30 January 2025 12:02

Bloaters:
Bloaters are code, methods and classes that have increased to such gargantuan proportions that they
are hard to work with.
Includes
- Long Method : method contains too many lines of code, longer than 10 lines of code.
- Primitive Obsession : use of primitives instead of small objects for simple tasks, use of constants
for coding information, use of string constants as field names for use in data arrays.
- Data Clumps : repeating data comprises the fields of a class, use extract class to move the fields to
their own class, introduce parameter object and preserve whole object.
- Large Class : when a class is wearing too many functional behavior then split it into extract class,
extract subclass and extract interface and keeping the data consistent by duplicating it and
observing the changes.
- Long Parameter List : replace parameter with method call, preserve whole object and introduce
parameter object.
Object-Orientation Abusers
Incorrect application of object-oriented programming principles.
Includes
- Alternative Classes with different interfaces : different classes with same method functionality, to
solve we can add the interface of classes and rename methods, move method, add parameter and
parameterize method, use of super if part of functionality is duplicate.
- Refused Bequest : if subclass uses only some of the methods and properties inherited from its
super class - Replace inheritance with delegation, extract all fields and methods needed by the
subclass from parent class, put them in new super class and set the both class to inherit new super
class.
- Temporary field : replace method with method object and introduce null object
- Switch statements
Change Preventers
It means if you need to change something in one place in your code, you have to make many changes in
other places too. Program development becomes much more complicated and expensive as a result.
Includes
- Divergent Change : split up the behavior of class and if same behavior combine them through
inheritance
- Parallel Inheritance Hierarchies :
Whenever you create a subclass for a class, you find yourself needing to create a
subclass for another class. - remove the inheritance and make the instance of one
hierarchy refer to instances of another hierarchy.
- Shotgun Surgery : making any modifications requires that you make many small changes to many
different classes. - use inline class and by creating new class with existing behavior.
Dispensables:
A dispensable is something pointless and unneeded whose absence would make the code cleaner, more
efficient and easier to understand.
Includes
- Comments : "The best comment is a good name for a method or a class." splitting the complex
expression into subexpression and use of assertion and renaming the method.
- Data Class :
A data class refers to a class that contains only fields and crude methods for accessing them
(getters and setters). These class are not independently operatable - encapsulate field, use of
collection, use records
- Lazy Class : If a class doesn't do enough to earn your attention, it should be deleted. - near-useless
should be used in inline Class

JM-2 Page 1
should be used in inline Class
- Duplicate Code - use same method in all calls, if same code exists in two subclasses then write the
method code in super class, Pull-up field, pull constructor body, form template method use
substitute algorithm for different algorithms, consolidate conditional expression.
- Dead Code : variable, parameter, field, method or class is no longer used.
- Speculative Generality : for future use
Couplers:
This group contribute to excessive coupling between the classes or show what happens if coupling is
replaced by excessive delegation.
Includes
- Feature Envy : if a method access the another object data more than its own data - move , extract
method
- Incomplete Library Class : library is read-only - introduce foreign method , use of local extension.
- Middle Man : if a class performs only one action, delegating work to another class - Remove
middle man , elimination of message chains.
- Inappropriate Intimacy : One class uses the internal fields and methods of another class - move
method and move field, extract class and hide delegate, change bidirectional association to
unidirectional, replace delegation with inheritance.
- Message Chains : a()->b()->c()->d() - hide delegates, move and extract delegate.

JM-2 Page 2
Principles of Software development
04 February 2025 11:31

Principles or concept of software development:

1. KISS (Keep It Simple, Stupid/Short)


Simplicity triumphs over complexity. Direct and clear codes are better for developing, maintaining,
and scaling, turning simplicity into a form of efficiency.
2. DRY (Don't Repeat Yourself)
Repeating code is an invitation to problems. Keep your logic in one place to avoid errors and
facilitate maintenance, ensuring consistency.

3. YAGNI (You Aren't Gonna Need it)


Avoid creating functions that are not essential. Focus on what is really necessary, keeping the
code simple and direct. The YAGNI practice is important for two main reasons:
Time Savings: You stop spending time developing functions that you may never use.
Cleaner Code: Your code becomes clearer and free of assumptions that often turn out to be
wrong.
4. TDA (Tell, Don't Ask)
The TDA principle suggests avoiding asking the object about its state; instead, tell it what to do
based on the decision, that is, tell the object what to do.
5. SOLID
SOLID is a set of five fundamental principles of software design in object-oriented programming.
These principles guide developers in creating more readable, flexible, and sustainable software

JM-2 Page 3
These principles guide developers in creating more readable, flexible, and sustainable software
systems. These are not rules, but rather suggestions that will facilitate the life cycle of an
application and code.
• S) Single-responsibility principle (SRP): Each object, class, and method needs to have a single
responsibility.
• O) Open–closed principle (OCP): Software entities should be open to extension but closed to
modification.
• L) Liskov substitution principle (LSP): Objects of a superclass should be substitutable by objects of
their subclasses, and the application should still function as expected.
• I) Interface segregation principle (ISP): Software should be divided into several independent
parts.
• D) Dependency inversion principle (DIP): We should rely on abstractions, not concrete
implementations.

JM-2 Page 4
Design Patterns
06 February 2025 11:11

Design patterns represent the best practices used by the experienced object-oriented software
developers. Design patterns are solutions to general problems that software developers faced during
software development. These solutions were obtained by trial and error by numerous software
developers over quite a substantial period of time.
Types:
1. Creational patterns:
These patterns provide various object creation mechanisms, which increase flexibility and reuse of
existing code.
- Factory Method * : It is a pattern that provides an interface for creating objects in a superclass,
but allows subclasses to alter the type of objects that will be created. - creating an interface. It is
used when all the object creation and its business logic we need to keep at one place.

- Abstract Factory * : It is a pattern that lets you produce families of related objects without
specifying their concrete classes. - creating an abstract class and by creating a reference for
abstract class.

JM-2 Page 5
- Builder * : It is a pattern that lets you construct complex objects step by step. The pattern allows
you to produce different types and representations of an object using the same construction
code. - creating a separate builder interface for the input handling

JM-2 Page 6
-

- Prototype : It is a pattern that lets you copy existing objects without making your code dependent
on their classes, since object creation is expensive.

- Singleton * : It is a pattern that lets you ensure that a class has only one instance, while providing
a global access point to this instance. - By providing the private constructor and creating a static
method that pass the private constructor as a parameter.
4 ways to achieve:
-> Eager : by creating private constructor and during loading only object is created and since
object is of static type so only one copy exists.

-> Lazy : Object should be created during the method invocation


Problem : Not thread-safe if 2 threads come at same time then 2 objects will be created. To
overcome this we use Synchronized method

JM-2 Page 7
-> Synchronized Method :
Problem : it is very expensive if I have 100 threads then if 1 accessing the method then it acquire
then and so on for all threads. Since Locking is expensive method. To overcome this we use
Double locking

-> Double Locking : before acquiring lock first we check and then in the synchronized block we are
checking again which make sure lock is not acquired to complete method.

-> Enum : Thread-safe, Serialization-safe, Reflection-safe, Best way to enforce a true singleton

-> Bill Pugh : clever way to implement lazy-loaded, thread-safe singletons without

JM-2 Page 8
-> Bill Pugh : clever way to implement lazy-loaded, thread-safe singletons without
synchronization overhead — using a static inner class.

2. Structural Patterns :
These patterns explain how to assemble objects and classes into larger structures while keeping
these structures flexible and efficient.
- Adapter : It allows object with incompatible interfaces to collaborate - It is special object that
converts the interface of one object so that another object can understand it.
Types : Object and class
- Bridge : It is that lets you split a large class or set of closely related classes into two separate
hierarchies - abstraction and implementation - which can be developed independently of each
other.
- Composite : It is that lets you compose objects into tree structures and then work with these
structures as if they were individual object.
- Decorator * : It is that lets you watch new behaviors to objects by placing these objects inside
special wrapper objects that contain the behaviors.
- Facade : It is that provides a simplified interface to a library, a framework, or any other complex
set of classes.
- Flyweight : It is that lets you fit more objects into the available amount of RAM by sharing
common parts of state between multiple objects instead of keeping all of the data in each object.
- Proxy : It is that lets us provide a substitute or placeholder for another object. A proxy controls
access to the original object, allowing us to perform something either before or after the request
gets through to the original object.
3. Behavioral patterns :
These patterns are concerned with algorithms and the assignment of responsibilities between
objects.
- Chain of responsibility : It is that lets us pass requests along a chain of handlers. Upon receiving a
request, each handler decides either to process the request or to pass it to the next handler in the
chain.
- Command : It is that turns a request into a stand-alone object that contains all information about
the request. This transformation lets us pass requests as a method arguments, delay or queue a
request's execution, and support undoable operations.
- Iterator : It is that lets you traverse elements of a collection without exposing its underlying
representation (list).
- Mediator : It is that lets you reduce chaotic dependencies between objects. The pattern restricts
direct communications between the objects and forces them to collaborate only via a mediator

JM-2 Page 9
direct communications between the objects and forces them to collaborate only via a mediator
object.
- Memento : It is that lets you save and restore the previous state of an object without revealing
the details of its implementation.
- Observer : It is that lets you define a subscription mechanism to notify multiple objects about any
events that happen to the object they're observing.
- State : It is that lets an object alter its behavior when its internal state changes. It appears as if the
object changed its class.
- Strategy * : It is that lets you define a family of algorithms, put each of them into a separate class,
and make their object interchangeable.
- Template Method : It is that defines the skeleton of an algorithm in the superclass but lets
subclasses override specific steps of the algorithm without changing its structure.
- Visitor : It is that lets you separate algorithms from the objects an which they operate.

JM-2 Page 10
Spring Framework
12 February 2025 11:09

Spring is use to create Java Enterprise applications. It provides to embrace the java language in an
enterprise environment, with support for Groovy and Kotlin as alternative languages on the JVM. It can
be used to create many kinds of architectures depending on an application's needs .
As of Spring Framework 6.0, Spring requires Java 17+.
Spring is open source. It has a large and active community that provides continuous feedback based on a
diverse range of real-world use cases.
What is Spring Framework?
Roderick B. Johnson, an Australian computer specialist officially released the Spring Framework in 2004.
Spring is a powerful lightweight application development framework used for Java Enterprise edition
(JEE).
Spring is a complete and a modular framework for developing enterprise applications.
Spring framework can be used for all layer implementations.
It is a framework of frameworks because it provides support to various frameworks such as Struts,
Hibernate, Tapestry, EJB, JSF, etc
Spring Features :
- Lightweight : with respect to size and transparency.
- Inversion of Control (IOC) : Loose coupling is achieved using Inversion of Control. The objects give
their own dependencies instead if creating or looking for dependent objects.
All objects in Spring are called as Beans.
- Aspect Oriented Programming (AOP) : By separating application business logic from system
services, it supports Aspect Oriented Programming and enables cohesive development.
- Container : Spring framework creates and manages the lifecycle and configuration of application
objects.
- Dependency Injection : Allows you to develop loosely coupled applications. The unit testing
becomes easier with loosely coupled.
- Transaction Management : It provides a generic abstraction layer. It is not tied to J2EE
environments, and it can be used in container-less environments.
- Integration with other frameworks : It doesn't try to solve the problems that have been already
solved. It just tries to integrate them with its framework which provides a solution to greater
problems.
Advantages of using Spring Framework :
- Works on POJO (Plain Old Java Object ) which makes your application lightweight.
- Provides predefined templates for JDBC, Hibernate, JPA etc. thus reducing the effort to writing
codes
- Objects are loosely coupled -> dependency injection feature
- The development of Java Enterprise Edition (JEE) applications become faster.
- It also provides strong abstraction to JEE specifications.

JM-3 Page 1
It also provides strong abstraction to JEE specifications.

It is a layered architecture and modular based


Core Container :
Spring Core : This module is core of the Spring Framework. It provides implementation for features like
IoC (Inversion of Control ) and dependency injection with singleton design pattern.
Spring Bean : It provides implementation for the factory pattern through BeanFactory.
Spring Context : It is build on the solid base provided by the core and the beans modules and is a
medium to access any object defined and configured.
Spring Expression Languages (SpEL) : It is an extension of expression language supported by Java server
pages. It provides a powerful expression language for querying and manipulating an object graph, at
runtime.
Spring Data Access/ Integration :
JDBC (Java DataBase Connectivity) : It provides JDBC abstraction layer which eliminates the need of
repetitive and unnecessary exception handling overhead.
ORM (Object Relational Mapping ) : It provides consistency/ portability to our code regardless of data
access technologies based on object oriented mapping concept.
OXM (Object XML Mappers ) : It is used to convert the objects into XML format and vice versa. It
provides an uniform API to access any of these OXM frameworks.
JMS (Java Messaging Service ) : It contains features for producing and consuming messages among
various clients.
Transaction : It supports programmatic and declarative transaction management for classes that
implement special interfaces and for all your POJOs. All the enterprise level transaction implementation
concepts can be implemented in Spring using this module.
Spring framework is divided into modules which makes it really easy to pick and choose in parts to use in
any application:
Core: Provides core features like DI (Dependency Injection), Internationalisation, Validation, and AOP
(Aspect Oriented Programming)
Data Access: Supports data access through JTA (Java Transaction API), JPA (Java Persistence API), and
JDBC (Java Database Connectivity)
Web: Supports both Servlet API (Spring MVC) and of recently Reactive API (Spring WebFlux), and
additionally supports WebSockets, STOMP, and WebClient
Integration: Supports integration to Enterprise Java through JMS (Java Message Service), JMX (Java
Management Extension), and RMI (Remote Method Invocation)
Testing: Wide support for unit and integration testing through Mock Objects, Test Fixtures, Context
Management, and Caching
Spring IoC Container :
It stands for Inversion of Control. It is the heart of the spring framework.
The advantages of this architecture are:
- decoupling the execution of a task from its implementation
- making it easier to switch between different implementations

JM-3 Page 2
- making it easier to switch between different implementations
- greater modularity of a program
- greater ease in testing a program by isolating a component or mocking its dependencies, and
allowing components to communicate through contracts
Tasks performed by IoC Container are
- Instantiating the bean
- Wiring the bean together
- Configuring the beans
- Managing the bean's entire life-cycle
IoC container receives metadata from either an XML file, Java annotations, or Java code and works
accordingly. IoC adds the flexibility and control of application, and provides a central place of
configuration management for Plain Old Java Objects (POJO) of our application.

There are 2 types of IoC containers:


1. BeanFactory
2. ApplicationContext
BeanFactory :
It is an interface defined in [Link].
Bean Factory provides the basic support for Dependency injection.
All beans are singleton by default.
It is based on factory design pattern which creates the beans of any type.
BeanFactory follows lazy-initialization technique which means beans are loaded as soon as bean factory
instance is created but the beans are created only when getBean() method is called.
The XmlBeanFactory is the implementation class for the BeanFactory Interface. To use the BeanFactory,
we need to create the instance of XmlBeanFactory class,
BeanFactory beanfactory=new XmlBeanFactory(new ClassPathResource("<path>[Link]"))
ApplicationContext :
It is an interface defined in [Link].
It is the advanced Spring container and is built on top of the BeanFactory interface.
It supports the features supported by Bean Factory but also provides some additional functionalities.
In the Spring framework, the interface ApplicationContext represents the IoC container. The Spring
container is responsible for instantiating, configuring and assembling objects known as beans, as well as
managing their life cycles.
It follows eager-initialization technique which means instance of beans are created as soon as you
create the instance of ApplicationContext.
The ClassPathXmlApplicationContext class is the implementation class of ApplicationContext interface.
We need to instantiate the ClassPathXmlApplicationContext class to use the ApplicationContext,
ApplicationContext context=new ClassPathXmlApplicationContext("[Link]");
The Spring framework provides several implementations of the ApplicationContext interface:
AnnotationConfigApplicationContext, ClassPathXmlApplicationContext and
FileSystemXmlApplicationContext for standalone applications, and WebApplicationContext for web
applications.
Bean Scopes

JM-3 Page 3
We can achieve Inversion of Control through various mechanisms such as: Strategy design pattern,
Service Locator pattern, Factory pattern, and Dependency Injection (DI).

Dependency Injection :

It is also one of the core concepts of Spring Framework.


It is a design pattern that removes the dependency from the code.
That is, the Spring Framework provides the dependencies of the class itself so that it can be easy to
manage and test the application.
You can provide information from the external source such as XML file.
Here, you do not create the objects instead you just define how they should be created and IoC
container will create the objects.
In Spring, dependencies can be injected in three ways :
1. By constructor
2. By setter method
3. Field injection
Main annotations :
1. @Configuration -> Indicates that a class declares one or more @Bean methods and can be
processed by the container to generate bean definitions when used along with @ComponentScan
2. @Bean -> Annotation is applied on a method to specify that it returns a bean to be managed by
Spring context. Spring Bean annotation is usually declared in Configuration classes methods.
3. @Component -> This annotation marks a java class as a bean so the component-scanning
mechanism of spring can pick it up and pull it into the application context.
4. @ComponentScan -> Using component scanning, spring can auto-scan all classes annotated with
the stereotype annotations @Component, @Controller, @Service and @Repository and configure
them with BeanFactory. By default, if we do not specify the path, it scans the current package and
all of its sub-packages for components.

JM-3 Page 4
all of its sub-packages for components.

5. @Autowired -> Marks a constructor field, setter method, or config method as to be autowired by
dependency injection. We can mark whether the annotated dependency is required or not using
"required" attribute. By default, its value is true.
6. @Primary -> Indicates that a bean should be given preference when multiple candidates are
qualified to autowire a single-valued dependency.
7. @Qualifier -> During autowiring, if more than one bean of same type is available in the container
then container will throw runtime exception. To fix this problem, we have to specifically tell spring
that which bean has to be injected using this annotation.
To remove the dependency of a class, we need to use interface which makes class loosely coupled.
However, for specific areas, they do form a compelling argument to pick as alternatives:
Guice: Offers a robust IoC container for Java applications
Play: Quite aptly fits in as a Web framework with reactive support
Hibernate: An established framework for data access with JPA support
Other than these there are some recent additions that offer wider support than a specific domain but
still do not cover everything that Spring has to offer:
Great question! These three concepts are fundamental to writing clean, flexible, and maintainable
code—especially in Spring Boot. Let me break each down clearly and show how they relate to each
other in Spring Boot apps.
Dependency Inversion Principle (DIP)
Definition:
One of the SOLID principles of OOP. It states:
“High-level modules should not depend on low-level modules. Both should depend on abstractions
(interfaces or abstract classes). Also, abstractions should not depend on details. Details should depend
on abstractions.”
Why it matters:
Reduces coupling between components.
Makes your code easier to extend and test.
Example:
Instead of a service directly creating or using a concrete repository class, both depend on an interface:
public interface UserRepository {
User findById(Long id);
}

public class UserRepositoryImpl implements UserRepository {


// concrete database code here
}

public class UserService {


private final UserRepository userRepository; // depends on abstraction

public UserService(UserRepository userRepository) {


[Link] = userRepository;
}
}
Dependency Injec on (DI)
Definition:
A design pattern and technique where an object’s dependencies are provided (injected) from outside
rather than the object creating them itself.

JM-3 Page 5
rather than the object creating them itself.
In Spring Boot:
Spring’s IoC container automatically injects dependencies for you.
Common injection types: constructor injection (preferred), setter injection, field injection.
Example in Spring Boot:
@Service
public class UserService {

private final UserRepository userRepository;

// Constructor injection
public UserService(UserRepository userRepository) {
[Link] = userRepository;
}

// business methods here


}

@Repository
public class UserRepositoryImpl implements UserRepository {
// implementation
}
Spring Boot automatically injects UserRepositoryImpl into UserService when it creates the beans.
Inversion of Control (IoC)
Definition:
A broad principle where the control of creating and managing objects is inverted — instead of the
program controlling object creation, an external container/framework (like Spring) does it.
How it works in Spring Boot:
You declare components (@Component, @Service, @Repository, etc.).
Spring IoC container manages their lifecycle and dependencies.
You don’t instantiate dependencies manually.

JM-3 Page 6
SpringBoot
17 February 2025 19:20

SpringBoot makes it easy to create stand-alone, production grade spring based applications that you
can Just Run.
Problems with Spring which is solved by SpringBoot:
- Huge Framework
- Multiple setup and Configuration steps
- Multiple Build and Deploy steps
What SpringBoot is not?
- It is not an application or web server
- Does not implement any specific framework (JPA,JMS)
- Does not generate code
- Is not a replacement for spring framework
What SpringBoot is?
- Opinionated : takes default packages for the project execution
- Convention over configuration : configuration are done automatically
- Standalone : it contains all server, containers, deploy, execution
- Production Ready
SpringBoot is a tool developed on top of core spring framework which provides RAD (Rapid Application
Development).
The main aim of SpringBoot is to let developers to create spring production grade applications and
services with very less effort
Normally in real-time spring applications, it includes writing many XML configurations, server setting,
adding dependencies, etc. But with SpringBoot we can avoid all these boilerplate code, writing XML
configurations and annotations.
We can create a real-time production ready applications within minutes.
SpringBoot comes with inbuilt server, we no longer have to use any external servers like Tomcat, Glass-
fish or anything else, so don't have to deploy WAR files.
Advantages of SpringBoot :
1. SpringBoot helps in resolving dependency conflict. It identifies required dependencies and import
them for you.
2. It has information of compatible version for all dependencies. It minimizes the runtime classloader
issues.
3. It's "opinionated defaults configuration" approach helps you in configuring most important pieces
behind the scene. Override them only when you need. Otherwise everything just works, perfectly.
It helps in avoiding boilerplate code, annotations and XML configurations.
4. It provides embedded HTTP server Tomcat so that you can develop and test quickly.
5. It has excellent integration with IDEs like eclipse and intelliJ idea.
SpringBoot Templates :
It is highly dependent on the starter templates feature which is very powerful and works flawlessly.
What is Starter Templates?
SpringBoot starters are templates that contain a collection of all the relevant transitive
dependencies(A->B, B->C=A->C) that are needed to start a particular functionality. For example, If you
want to create a Spring WebMVC application then in a traditional setup, you would have included all
required dependencies yourself. It leaves the chances of version conflict which ultimately result in more
runtime exceptions.
@SpringBootApplication Annotation:
This annotation is a shortcut of applying 3 annotations in one statement.
1. @SpringBootConfiguration : is new annotation in SpringBoot 2. Previously, we have been using
@Configuration. You can use @Configuration in place of this. Both are same thing. It indicates that
a class provides SpringBoot application @Configuration. It simply means that annotated class is a
configuration class and shall be scanned for further configurations and bean definitions.

JM-3 Page 7
configuration class and shall be scanned for further configurations and bean definitions.
2. @EnableAutoConfiguration : is used to enable auto-configuration of the Spring Application
Context, attempting to guess and configure beans that you are likely to need. Auto-configuration
classes are usually applied based on your class path and what beans you have defined.
3. @ComponentScan
What is spring-boot-starter-parent dependency?
The spring-boot-starter-parent dependency is the parent POM providing dependency and plugin
management for Spring Boot-based applications. It contains the default versions of Java to use, the
default versions of dependencies that SpringBoot uses, and the default configuration of the Maven
plugins.
Spring-boot-starter Maven Templates :
Dependency management was becoming very complex task which required good amount of technical
expertise to do it correctly. With the introduction of SpringBoot starter templates, you can get a lot of
help in identifying the correct dependencies to use in project if you want to use in project if you want to
use any popular library into your project.
SpringBoot comes with over 50+ different starter modules, which provide ready-to-use integration
libraries for many different frameworks, such as database connections that are both relational and
NoSQL, web services, social network integration, monitoring libraries, logging, template rendering, and
the list just keeps going on.

Creating SpringBoot Application:


1. Spring initializer and create a maven project with specified details of the project.
2. Create new project and select spring starter project.
[Link] contains <parent>, dependencies version, properties
Uniquely identifying details of project are groupId, artifacts, packaging, name, URL and version
3 kinds of logging:
1. Log4j
2. Sl4j
3. Logback classic
Mockito is testing framework.
If we don't want to download the specific package from the default framework then we can use
<exclusions> tags with groupId and artifact Id to excluded.
To work with web we use WebApplicationContext

JM-3 Page 8
To work with web we use WebApplicationContext
[Link] -> for logging info

SpringBoot is defaults configuration means it is opinionated default configuration


To change the configurations we can use [Link] file
When will [Link]("message") be printed?
If the logging level is set to DEBUG (or lower like TRACE), the message will be printed to the console.
If the logging level is set to INFO, WARN, ERROR, or FATAL, debug messages will NOT be printed.
How to Enable Debug Logging in Spring Boot?
You can configure the logging level in several ways:
Set logging level in [Link] or [Link]
For [Link]
[Link]=DEBUG

Default Logging Level in Spring Boot


The default logging level in Spring Boot is INFO.
This means [Link]("Message") will NOT be printed unless you explicitly set DEBUG logging.

To run java jar file -> java -jar [Link]


To change the port of the Tomcat Server -> [Link]=8000
ApplicationContext is interface and it has many classes like @ConfigApplicationContext,
ConfigurableApplicationContext which is returned by the [Link]([Link],args);

JM-3 Page 9
If value is not defined in [Link] then the application won't run and throws compile-time
error as Injection of autowired dependencies failed. To avoid this we can add default value in
@Value("${[Link]:default value}")
If we have default value and [Link] also then the precedence is given to
[Link] value.

JM-3 Page 10
JPA
20 February 2025 09:39

Java Persistence API is a set of guidelines to be followed to represent Java Objects in databases.
JPA provides a set of concepts in form of interfaces and annotations to configure Java Objects.
To reduce the burden of writing codes for relational object management, a programmer follows the JPA Provider
framework, which allows easy interaction with database instance.
JPA is just a specification that facilitates object-relational mapping to manage relational data in Java applications. It
provides a platform to work directly with objects instead of using SQL statements.
ORM
ORM tools are providing implementation for JPA

ORM can be defined as a framework used to map an object to a relational database.


It triggers the select query to get the data.
Java is OOP language which is represented as a graph of objects whereas relational database is represented in tabular
format using rows and columns.
When it comes to save an object in a database, there exist some obvious mismatch and to handle this mismatch we have
ORM.
ORM tools :
- Hibernate -> build on top of JPA Specification
- Ibatis
- Toplink
- EclipseLink
Hibernate :
The primary feature of hibernate is mapping from java classes to database tables

Hibernate framework provides the facility to create the tables of the database automatically.
Also provides data query and retrieval facilities.
It generates the SQL calls and attempts to relieve the developer from manual result set handling and object conversion.
It keeps the application portable to all supported SQL databases with little performance overhead.

JM-3 Page 11
Session Factory, Transaction Factory, Connection Provider and Transaction are interfaces and classes .
JNDI -> Java Named Data source Interface -> managing the data source connections
JDBC -> Java DataBase Connectivity
JTA -> Java Transaction API
Adding the dependency :

Dialects :
The dialects specifies the type of database used in hibernate so that hibernate generate appropriate type of SQL
statements. For connecting any hibernate application with the database, it is required to provide the configuration of SQL
dialect.
It is used for the translation of the objects to SQL queries.
We need to provide the dialect configuration to the hibernate for the translation.
Present based upon the driver provided, the Hibernate auto configures the dialects so it is not required to define in .xml
file, but if you want to add the property you can still add but it is optional property.
Configuration of [Link]

Hibernate.show_sql = true -> to show the logs


[Link] = update/create -> to automatically create the tables based upon the objects provided. Create ->

JM-3 Page 12
[Link] = update/create -> to automatically create the tables based upon the objects provided. Create ->
it only creates the tables initially and update -> it makes sure to triggers the table for every changes and makes on
changes as per the operations.
Coding the Entity class :
In order to work with the table in database, create a class with the name of table.
Use the annotation,
- @Entity -> to map the class to the table
- @Id -> to mark the field as primary key
- @GeneratedValue -> to indicate that its value is auto generated.
Generator Class :
It is used to generate the unique identifier for the objects of persistent class. There are many generator classes defined in
the Hibernate framework.
If we want the primary key value to be generated automatically for us, we can add the @GeneratedValue annotation.
This can use 4 generation types: Auto, IDENTITY, SEQUENCE, TABLE.
If we don't specify the value explicitly, the generation type defaults to AUTO.
Mapping Hibernate :
- Many to One : Many employees belong to one department.

- One to Many : One department has many employees. Usually, it’s the inverse side of Many-to-One.

JM-3 Page 13
- One to One : One person has one passport.

- Many to Many : Many students enrolled in many courses.

JM-3 Page 14
Tx Management :
A transaction simply represents a unit of work in step way. In such case, if one steps fails, the whole transaction fails. A
transaction can be described by ACID properties (Atomicity, Consistency, Isolation and Durability)

Void begin() -> starts a new transaction


Void commit() -> ends the unit of work unless we are in [Link]
Void rollback() -> forces this transaction to rollback
Boolean isAlive() -> checks if the transaction is still alive.
HQL (Hibernate Query Language)
HQL is same as SQL but it doesn't depends on the table of the database. Instead of table name, we use the class name in
HQL So it is database independent language.
There are many advantages of HQL. They are as follows:
- Database independent.
- Supports polymorphic queries
- Easy to learn for java programmer
It is an object oriented representation of Hibernate Query. The object of Query can be obtained by calling the
createQuery() session interface.

JM-3 Page 15
HCQL (Hibernate Criteria Query Language)
HCQL is used to fetch the records based on the specific criteria. The Criteria interface provides methods to apply criteria.
It uses builder pattern internally.
HCQL provides methods to add criteria, so it is easy for the java programmer to add criteria. The java programmer is able
to add many criteria on a query.
The Criteria interface provides many methods to specify the criteria. The object of criteria can be obtained by calling the
createCriteria() method of Session interface.

JM-3 Page 16
POJO - Pain Old Java Object
A POJO is a simple Java object that follows standard conventions without depending on any special framework or library
Characteristics of a POJO:
Encapsulation – Fields are usually private, with public getters and setters.
No Special Restrictions – It does not extend any framework-specific classes or implement interfaces.
No Annotations (Optional) – A pure POJO does not use annotations, but in ORM, annotations are used to define
mappings.
Serializable (Optional) – To support serialization, it can implement Serializable.
Why Use POJOs in ORM?
Decouples business logic from persistence logic.
Makes data handling simple and maintainable.
Ensures portability between different frameworks (Hibernate, EclipseLink, etc.).
Annotations :
- @Entity ->
- @Table(name="table") -> creates table with specified name rather than with class name
- @Id -> to keep the primary key
- @Column(name="Filed")
- @GeneratedValue(strategy=type)-> GenerationType. AUTO / IDENTITY / SEQUENCE / TABLE
Connect to database :
[Link] contains factory of persistence unit / properties.
[Link] contains all the configurations of the database.
[Link] is configured at src/main/resources/META-INF/[Link] file
[Link] contains
- [Link] property
- [Link]
- [Link]
- [Link]
- [Link]
[Link]("persistenceUnitName") -> to get the specified connection from the persistence unit. It
contains the database connection details -> returns EntityManagerFactory
EntityManager -> to get the entity manger from the entityManager factory -> it interacts with database layer and
persistence layer.
After connection to database, it will generate the logs.
- Uses hibernate connection pool
By default Auto Commit is false, if we want to enable it we need to add
<property name="[Link]" value="true"/> in [Link] file
Hibernate Default connection pool size is 20 and min is 1.
To Save the add in the table -> [Link](classObject)
To do any operation with the database, we need to begin the transaction , then operation and at last commit transaction.
Between the begin and commit, whatever operation is specified will be worked on database also
Select queries doesn't require any transactions.

JM-3 Page 17
Updating values

If the id doesn't exists in the database it will return null.


Delete

ReadAll Values

Mapping Foreign Key:

JM-3 Page 18
JM-3 Page 19
JM-3 Page 20
SpringBoot Data JPA
20 February 2025 20:47

SpringBoot Data JPA eliminates boiler plate code.


It uses hibernate implements the JPA.
Repository is a marker interface which is available in Spring Data JPA.
CRUDRepository interface as all the CRUD operations

JPARepository it extends the PagingAndSortingRepository


PagingAndSortingRepository which extends CRUDRepository

UserRepository it extends CRUDRepository


Query Methods:
Procedure :
1. Add SpringBoot starter DataJPA dependency in [Link] (version is not required since it takes the
parent version)
2. Add the data source in [Link]

3. To access the database values we need to create interface which extends


CrudRepository<entity,<type of primary key>>
Default persistence unit is EntityManagerFactory

JM-3 Page 21
JM-3 Page 22
Annotations
21 February 2025 09:34

@SpringBootApplication :
→ This is a meta-annotation that combines:
- @Configuration (Defines this as a configuration class)
- @EnableAutoConfiguration (Automatically configures Spring Boot)
- @ComponentScan (Scans for components, services, and controllers)

@Configuration : The @Configuration annotation in Spring Boot is used to define Java-based configuration classes that register
beans in the Spring container. It is an alternative to XML-based configuration.
How @Configuration Works
A class annotated with @Configuration acts as a source of bean definitions.
Methods within the class that are annotated with @Bean define beans that Spring will manage.
@Configuration is often used along with @ComponentScan and @EnableAutoConfiguration.
When to Use @Configuration
When you manually define beans instead of relying on @Component scanning.
When you externalize configurations (e.g., defining beans using properties).
When you define third-party beans that cannot be annotated with @Component.

@ComponentScan : The @ComponentScan annotation in Spring Boot is used to automatically detect and register Spring-managed
components (beans) in the application context. It tells Spring where to look for classes annotated with @Component, @Service,
@Repository, and @Controller.
How @ComponentScan Works
By default, Spring Boot scans the package where the main application class is located and all its subpackages.
If you need to scan additional or different packages, you can specify them explicitly.

JM-3 Page 23
Only CustomService is included, even if other services exist.
When to Use @ComponentScan
When your components are outside the default package.
When you need to filter specific beans to include/exclude.
When configuring modular applications with separate packages.
@EnableAutoConfiguration : The @EnableAutoConfiguration annotation in Spring Boot enables automatic configuration based on
the classpath dependencies. It allows Spring Boot to detect and configure beans automatically without requiring explicit
@Configuration setup.
How @EnableAutoConfiguration Works
Spring Boot scans the classpath for required dependencies.
It automatically registers beans based on the dependencies present with default configurations.
Uses Spring Boot’s auto-configuration classes from the spring-boot-autoconfigure module.
It is included in @SpringBootApplication, so it is usually not required explicitly.

We can exclude the class from scanning


When to Use @EnableAutoConfiguration
When not using @SpringBootApplication (e.g., modular Spring projects).
When excluding specific auto-configurations.
When testing custom configurations.
@Component : The @Component annotation in Spring Boot is used to mark a Java class as a Spring-managed bean. It allows
Spring to automatically detect and register the class in the application context.
How @Component Works
Classes annotated with @Component are automatically discovered if they are within a package scanned by Spring
(@ComponentScan or @SpringBootApplication).
Spring Boot creates an instance of the component and manages its lifecycle.
It is a generic stereotype for any Spring-managed component, whereas @Service, @Repository, and @Controller are specialized
types of @Component.

JM-3 Page 24
When to Use @Component
When defining utility classes or generic beans.
When using custom annotations (meta-annotations).
When manual registration using @Bean is unnecessary.
@Autowired : The @Autowired annotation in Spring Boot automatically injects dependencies (Spring beans) into a class. It
eliminates the need for manual bean instantiation, making dependency injection (DI) seamless.
How @Autowired Works
Spring automatically finds and injects the required bean from the application context.
Supports three injection types:
1. Constructor Injection (Recommended) -> Constructor-based injection is preferred because:
It ensures that the required dependencies are available when the object is created.
Makes the class immutable (safer for testing).

Works well with @RequiredArgsConstructor from Lombok.


2. Field Injection -> Field injection is simpler but discouraged because:
It makes unit testing harder (you need reflection for mocking).
It prevents proper dependency validation at the time of object creation.

3. Setter Injection -> Setter injection is useful when:


Dependencies are optional.
You want to modify dependencies dynamically.

Works with @Component, @Service, @Repository, and @Controller classes.


When multiple beans of the same type exist, use @Qualifier to specify which one to inject.

JM-3 Page 25
If a bean might not be available, set required = false.

When to Use @Autowired


When injecting dependencies into Spring-managed beans.
When using constructor injection (recommended).
When handling optional dependencies (required = false).
@Repository : The @Repository annotation in Spring Boot is a specialization of @Component used for Data Access Objects (DAO).
It marks a class as a Spring-managed bean responsible for interacting with the database.
Features of @Repository
- Automatic Component Scanning – Spring Boot automatically detects classes annotated with @Repository.
- Exception Translation – Converts database exceptions (e.g., SQLException) into Spring’s DataAccessException, making error
handling easier.
- Stereotype for Persistence Layer – Specifically used for database operations.
Spring Boot uses Spring Data JPA, which provides automatic CRUD operations through JpaRepository
Spring automatically translates SQLExceptions into DataAccessException.
When to Use @Repository
When interacting with the database (CRUD operations).
When using Spring Data JPA repositories.
When handling SQL exceptions automatically.
@PersistenceContext : The @PersistenceContext annotation in Spring Boot is used to inject an EntityManager to interact with the
database manually. It is typically used in custom repository implementations where you need more control over database queries
beyond what Spring Data JPA provides.
How @PersistenceContext Works
Injects an EntityManager, which is responsible for database operations like persist(), merge(), remove(), and find().
Used in custom repositories where JPA’s built-in methods (save(), findAll()) are not enough.
Works with Spring Data JPA and Hibernate.
EntityManager allows executing JPQL queries directly.
JPQL is database-independent and works with Hibernate.

When to Use @PersistenceContext


When writing custom JPA queries using EntityManager.
When performing manual transactions or batch inserts.
When default JPA methods (findAll(), save()) are not enough.
@Entity : The @Entity annotation in Spring Boot (from Jakarta Persistence API - JPA) is used to map a Java class to a database
table. It marks a class as a persistent entity that Spring Data JPA can manage.
How @Entity Works

JM-3 Page 26
How @Entity Works
Each entity represents a database table.
Each field corresponds to a column in the table.
The class must have a primary key (@Id).
Works with JPA (spring-boot-starter-data-jpa).
Spring Boot automatically creates the database table if [Link]-auto=update is set in [Link]

When to Use @Entity


When mapping Java classes to database tables.
When using Spring Boot with JPA/Hibernate.
When working with Spring Data JPA repositories.
@Bean : The @Bean annotation in Spring Boot is used to manually define and configure Spring beans inside a @Configuration
class. It tells Spring to manage the lifecycle of an object and make it available for dependency injection.
How @Bean Works
Used inside a @Configuration class.
Creates and manages objects (Spring Beans) manually.
Can be used to configure third-party libraries that are not directly supported by Spring.
Alternative to @Component, @Service, @Repository when you need custom bean creation logic.

When to Use @Bean?


When configuring third-party libraries.
When you need more control over the bean creation process.
When you manually instantiate objects that should be Spring-managed.
Example : Scanner class and ObjectMapper
@Bean(initMethod = "methodName") (Custom initialization in Spring Beans)
If you want a method to run before using a bean, specify an init method in a @Bean.

JM-3 Page 27
@Bean(destroyMethod = "methodName")
Specifies a custom destroy method for Spring beans.
Useful for manually managing cleanup logic.

@Service : The @Service annotation in Spring Boot is a specialized version of @Component, used to define business logic classes
(Service Layer) in a Spring application. It is part of the Service Layer in the MVC architecture.
Purpose of @Service
Marks a class as a Service so that Spring can detect and manage it.
Used for business logic (processing, calculations, validation, etc.).
Supports Dependency Injection with @Autowired.
Works like @Component, but semantically represents a Service Layer.
When to Use @Service?
When handling business logic in your application.
When interacting with repositories to process data before sending it to the controller.
When you need dependency injection for reusable business methods.
@Transactional : The @Transactional annotation in Spring Boot ensures that database operations (CRUD) happen within a
transaction. If an error occurs, all changes are rolled back automatically to maintain data consistency.
Why Use @Transactional?
Ensures atomicity – either all operations succeed or none.
Automatically rolls back if an exception occurs.
Manages multiple database operations in one unit of work.
Improves performance by reducing database calls.

JM-3 Page 28
Improves performance by reducing database calls.

When to Use @Transactional?


When performing multiple database operations that must be atomic.
When updating multiple tables in a single method.
When you need automatic rollback on failure.
@Primary : The @Primary annotation in Spring Boot is used to set the default bean when multiple beans of the same type exist in
the Spring context. It tells Spring which bean to prefer for dependency injection if there are multiple matching candidates.
Why Use @Primary?
Prevents NoUniqueBeanDefinitionException when multiple beans exist.
Specifies the default bean to be injected when no @Qualifier is provided.
Useful when multiple implementations of an interface exist.

When to Use @Primary?


When there are multiple beans of the same type.
When you want to set a default implementation.
When you want to avoid @Qualifier unless necessary.
@Qualifier : The @Qualifier annotation in Spring Boot is used to specify which bean to inject when multiple beans of the same
type exist in the Spring context. It helps resolve ambiguity when more than one candidate bean is available.
Why Use @Qualifier?
Prevents NoUniqueBeanDefinitionException when multiple beans exist.
Explicitly selects a specific bean instead of relying on @Primary.
Works with @Autowired to inject the right implementation.
Useful when multiple implementations of an interface exist.

When to Use @Qualifier?


When multiple beans of the same type exist.
When you need fine-grained control over bean selection.
When @Primary is not enough or needs to be overridden.
@PostConstruct : The @PostConstruct annotation in Spring Boot is used to execute a method automatically after the bean has
been initialized by the Spring container.
Why Use @PostConstruct?

JM-3 Page 29
Why Use @PostConstruct?
Runs initialization logic after dependency injection.
Useful for setting up resources (e.g., database connections, caches).
Ensures certain methods execute automatically when the application starts.
Avoids manual invocation of setup methods.
When to Use @PostConstruct?
When you need initial setup logic after Spring initializes a bean.
When you want to preload data in an application.
When you need to initialize caches or connections.
@PreDestroy : The @PreDestroy annotation is used to execute a method before a bean is destroyed by the Spring container. It is
mainly used for cleanup tasks, such as closing database connections, stopping background threads, or releasing resources.
Why Use @PreDestroy?
Ensures cleanup logic is executed before the application shuts down.
Prevents memory leaks by closing open resources.
Works with singleton-scoped beans (as Spring manages their lifecycle).
Runs automatically without requiring manual invocation.
@PreDestroy with Thread Management
If a service starts a background task (like a scheduled job), we can use @PreDestroy to stop it before shutdown.

When to Use @PreDestroy?


Closing resources (database connections, file streams).
Stopping background tasks (scheduled jobs, threads).
Logging shutdown messages.
Releasing external resources (sockets, caches).
@Scheduled : The @Scheduled annotation in Spring Boot is used to run a method automatically at a fixed interval or specific time.
It is commonly used for scheduled tasks, such as sending emails, cleaning up logs, or fetching data periodically.
To use @Scheduled, you must enable scheduling by adding @EnableScheduling to a configuration class or main application class.

It contains parameters like fixedRate, fixedDelay, cron (******) , initialDelay


When to Use @Scheduled?
Automated reports (e.g., daily reports at midnight).
Log cleanup (e.g., delete old logs every week).
Sending periodic emails or notifications.
Fetching data from APIs at regular intervals.
@Table : The @Table annotation in Spring Boot (JPA/Hibernate) is used to define the name and properties of a database table
that corresponds to an entity class.
Why Use @Table?
Customize the table name (instead of using the class name by default).
Specify schema, indexes, and unique constraints for the table.

JM-3 Page 30
Specify schema, indexes, and unique constraints for the table.
Helps Hibernate generate the correct table structure in the database.

When to Use @Table?


When you want to customize the table name.
When your table is in a specific schema.
When you need to enforce uniqueness constraints.
When you want to optimize queries with indexes.
@Id : The @Id annotation in Spring Boot (JPA/Hibernate) is used to specify the primary key of an entity. It marks a field as the
unique identifier for a database record.
Why Use @Id?
Defines the primary key for an entity.
Ensures uniqueness of records in the table.
Required for Hibernate to manage the entity properly.

you can use a UUID (random unique identifier).

When to Use @Id?


Always in JPA entities to define a primary key.
When you need auto-increment IDs (@GeneratedValue).
When you want to use UUIDs for global uniqueness.
@Column : The @Column annotation in Spring Boot (JPA/Hibernate) is used to customize database column properties for an
entity field. It allows you to set column names, constraints, and properties like uniqueness, nullability, and length.
Why Use @Column?
Customize column names (if different from field name).
Set constraints (e.g., nullable = false, unique = true).
Define column properties (e.g., length = 100, precision = 10, scale = 2).
Ensure database compatibility across different databases.

JM-3 Page 31
When to Use @Column?
When renaming a column to match the database.
When setting constraints (nullable = false, unique = true).
When defining length (length = 255 for String).
When specifying decimal precision (precision = 10, scale = 2).
In Spring Boot (JPA/Hibernate), relationships between entities are defined using @OneToOne, @OneToMany, @ManyToOne,
and @ManyToMany. These annotations help establish relationships between tables in a relational database.
@ManyToMany : Many entities are related to many other entities.
Example: Many Students are enrolled in many Courses.

JM-3 Page 32
@OneToMany : One entity is related to many other entities
Example: One Department has many Employees.

JM-3 Page 33
@ManyToOne : Many entities are related to one entity (opposite of @OneToMany).
Example: Many Employees belong to one Department

@OneToOne : One entity is related to exactly one other entity.


Example: An Employee has one Address.

JM-3 Page 34
What is orphanRemoval?
orphanRemoval = true automatically removes child entities when they are no longer referenced by the parent.
Works with @OneToOne and @OneToMany relationships.
Prevents orphan records in the database.

@GeneratedValue :
@JoinColumn :
@Override :

JM-3 Page 35
Bean Life Cycle
23 February 2025 19:18

A JavaBean is a class that follows these rules:


Must be public
Must have a no-arg constructor
Must have private fields
Must provide getters and setters
A Spring Bean is simply a Java object managed by the Spring IoC container.
3 Ways to Create a Bean in Spring
a) Using @Component (Annotation-Based)
b) Using @Bean in a @Configuration class
c) XML Configuration (Old Style)

JM-3 Page 36
The Spring Boot Lifecycle
Bean Creation: Spring Boot initializes the IoC container and creates beans based on configurations provided by @Bean,
@Component, and other annotations.
Bean Scanning: Spring Boot scans for classes annotated with @Component, @Service, @Repository, and @Controller, which is
configured in the main application class with @SpringBootApplication
@SpringBootApplication
public class MySpringBootApplication {
public static void main(String[] args) {
[Link]([Link], args);
}
}
@SpringBootApplication: Includes @Configuration, @EnableAutoConfiguration, and @ComponentScan.
Dependency Injection: After creating beans, Spring Boot performs dependency injection based on annotations like @Autowired
and @Qualifier.
Application Context Refresh: The application context is refreshed, making the application ready to handle requests or perform
tasks.
Bean Destruction: When the application context is closed, Spring Boot handles the destruction of beans. Beans with
@PreDestroy methods or those implementing DisposableBean are invoked for cleanup. This ensures resources are properly
released.
Example:
@Component
public class MyBean {
@PreDestroy
public void cleanup() {
[Link]("Cleaning up resources");
}
}
@PreDestroy: Marks a method to be called before the bean is destroyed.
BeanNameAware:
If the bean implements BeanNameAware or BeanFactoryAware or ApplicationContextAware, Spring injects the bean's name and

JM-3 Page 37
If the bean implements BeanNameAware or BeanFactoryAware or ApplicationContextAware, Spring injects the bean's name and
the bean factory into it, respectively.
It allows a bean to know its own name defined in the Spring container. This can be useful for logging or debugging.

BeanFactoryAware:
BeanFactoryAware is an interface that allows a bean to be aware of the BeanFactorythat created it. By implementing this
interface, the bean can interact with its BeanFactory directly. This can be particularly useful for dynamic bean lookups or
complex initialization logic.
BeanFactoryAware helps in scenarios where the standard dependency injection isn't flexible enough, like when you need to
create new instances of a bean on the fly.
Overusing BeanFactoryAware can lead to tight coupling with the Spring framework and make your code harder to test. Usually,
dependency injection should cover most of your needs.
Another thing to consider is to leverage other lifecycle interfaces or annotations like @PostConstruct and @PreDestroy to
manage your bean's lifecycle more cleanly. These can sometimes achieve what you need without resorting to
BeanFactoryAware.

ApplicationContextAware
This is similar to BeanFactoryAware, but it provides even more capabilities. ApplicationContext is like a superset of BeanFactory.
ApplicationContextAware enables beans to interact directly with the Spring IoC container by providing a callback interface. This
can be quite useful in scenarios where beans need to dynamically fetch other beans or access application-level resources. By
implementing the setApplicationContext method, beans can receive a reference to the ApplicationContext when they are
initialized.
ApplicationContext is the heart of Spring application. ApplicationContextAware allows beans to tap into the ApplicationContext’s
full capabilities, such as retrieving other beans by name or type, publishing events, accessing resources, and more.
It’s best to use ApplicationContextAware sparingly and only when absolutely necessary. In most cases, dependency injection
should suffice.

Pre-initialization (postProcessBeforeInitialization)
Before the bean initialization callbacks, the postProcessBeforeInitialization method of BeanPostProcessor is called. It allows

JM-3 Page 38
Before the bean initialization callbacks, the postProcessBeforeInitialization method of BeanPostProcessor is called. It allows
custom modification of new bean instances before initialization.
InitializingBean
The InitializingBean interface allows beans to perform initialization after their properties have been set. The afterPropertiesSet
method is called after dependency injection is complete.
Custom init
A custom init method is one you define and specify in the bean configuration. It provides more flexibility than
afterPropertiesSet.
Post-initialization (postProcessAfterInitialization)
After the initialization callbacks, the postProcessAfterInitialization method of BeanPostProcessor is called. This allows additional
custom modifications of new bean instances.
At this point, the bean is fully initialized and ready for use by other beans or components in the application.
Destruction Phases (DisposableBean and Custom Destroy Methods)
When the application shuts down or explicitly destroys the bean, Spring calls the destroy methods, either defined by
DisposableBean or custom methods specified by the developer.
Bean Lifecycle Stages
1. Definition -> Bean definition
2. Instantiation → Bean instance is created.
3. Populate Properties → Dependencies are injected.
4. Bean Name Aware → If the bean implements BeanNameAware, its setBeanName() method is called.
5. Bean Factory Aware → If the bean implements BeanFactoryAware, setBeanFactory() is called.
6. Pre-Initialization (BeanPostProcessor) → postProcessBeforeIni aliza on() is invoked.
7. Initialization → If the bean implements Ini alizingBean, a erProper esSet() is called OR init-method is executed.
8. Post-Initialization (BeanPostProcessor) → postProcessA erIni aliza on() is invoked.
9. Ready to Use → The bean is now available for use in the applica on.
10. Destruction → If the bean implements DisposableBean, destroy() is called OR destroy-method is executed before the bean
is removed.

JM-3 Page 39
Spring Rest
24 February 2025 09:08

What is Web Service?


A web service can be defined by following ways :
• Is a client server application or application component for communication
• Method of communication between two devices over network.
• Is a software system for interoperable machine to machine communication
• Is a collection of standards or protocols for exchanging information between two devices or application.
Before this we had RMI -> Remote Method Invocation -> constraint client and server should be in same language format.

There are mainly two types of web services


1. SOAP web services -> Simple Object Access Protocols -> protocol based web service
Represents data in one format like XML format
Client and Server should know about XML
To access server, client should do proper handshake for request to get the specific response
Server will have schema definition like WSDL (Web Services Description Language)
As the schema is transferred it consumes high bandwidth
2. RESTful web services -> an independent architectural style which uses HTTP as a protocol
Introduced by Roy Fielding in 2000-01
Represents the data in multiple formats like JSON,XML..
What is REST?
REST stands for Representational State Transfer. REST is a web standards-based architecture and uses HTTP Protocol for
data communication. It revolves around resources where every component is a resource and a resource is accessed by a
common interface using HTTP standard methods.
In REST architecture, a REST Server simply provides access to resources and the REST client accesses and presents the
resources. Each resource is identified by URIs(Uniform Resource Identifiers) / Global IDs. REST uses various representations
to represent a resource like Text, JSON and XML. JSON is now most popular format being used in web services.
JSON is a default format of web services.
REST is light weight, easy and flexible. SOAP is mostly used in Banking services since it is more secured
REST defines 6 architectural constraints / Guiding Principles which make any web service - a true RESTful API.
1. Uniform interface : It defines the interface between clients and servers. It simplifies and decouples the architecture,
which enables each part to evolve independently. REST is defined by four interface constraints: identification of
resources, manipulation of resources through representations, self-descriptive messages, and hypermedia as the
engine of application state(HETIOS).
2. Client-Service : The uniform interface separates clients from servers. It means that client are not concerned with the
server storage and servers are not concerned with the user interface or state.
3. Stateless : RESTful Web service should not keep a client state on the server. This restriction is called Statelessness. It is
the responsibility of the client to pass its context to the server and then the server can store this context to process
the client's further request.
RESTful web services should adhere to this restriction. The server does not store any client session between requests.
4. Cacheable : Caching refers to storing the server response in the client itself, so that a client need not make a server
request for the same resource again and again. A server response should have information about how caching is to be
done, so that a client caches the response for a time-period or never caches the server response.
5. Layered system : The layered system style allows an architecture to be composed of hierarchical layers by constraining
component behavior such that each component cannot see beyond the immediate layer with which they are
interacting. Intermediary servers may improve system scalability by enabling load balancing and by providing shared

JM-3 Page 40
interacting. Intermediary servers may improve system scalability by enabling load balancing and by providing shared
caches. They may also enforce security policies.
6. Code on demand (optional) : REST allows client functionality to be extended by downloading and executing code in
the form of applets or scripts. This simplifies clients by reducing the number of features required to be pre-
implemented.
Advantages:
Rest is an architectural style and not a protocol.
Fast. RESTful Web Services are fast because there is no strict specification like SOAP.
Language and platform independent : RESTful web services can be written in any programming language and executed in
any platform.
Permits different data format
REST requires less bandwidth and resource than SOAP.
REST is more preferred than SOAP.
HTTP Protocols :
RESTful web services make use of HTTP protocols as a medium of communication between client and server. A client sends a
message in form of HTTP Request and the server responds in the form of an HTTP Response. This technique is termed as
Messaging. These messages contain message data and metadata.
A HTTP Request has 5 major parts :

Verb -> HTTP methods such as GET, POST, DELETE, PUT


URI -> Uniform Resource Identifier to identify the resource on the server
HTTP version -> Indicates HTTP version. HTTP v1.1
Request Header -> Contains metadata for the HTTP Request message as key-value pairs. (client type, format supported by
client, format of message body, cache settings)
Request Body -> message content or Resource representation.
HTTP Response :

An HTTP Response has 4 major parts -


Status/Response Code - indicates the server status for the requested resource (404=resource not found, 200=ok)
HTTP version - HTTP v1.1
Response Header - contains metadata for the HTTP response message as key/value pairs. (content length, content type,

JM-3 Page 41
Response Header - contains metadata for the HTTP response message as key/value pairs. (content length, content type,
response date, server type)
Response Body - Response message content or resource representation.
HTTP methods :
GET- provides a read only access to a resource
POST - Used to create a new resource
DELETE - Used to remove a resource
PUT - Used to update an existing resource or replace a resource
Response Codes:

Constructing a Standard URI :


Use Plural Noun : Use plural noun to define resources (users)
Avoid using spaces : Use underscore(_) or hyphen(-) when using a long resource name
Use lowercase letters : Although URI is case-insensitive. It is good practice to keep the url in lower case letters only.
Maintain Backward Compatibility : As Web service is a public service, a URI once made public should always be available. In
case, URI gets updated, redirect the older URI using HTTP status code, 3000.
Use HTTP verb : GET, PUT, DELETE
Richardson Maturity Level :
It is a model developed by Leonard Richardson.
It grades APIs by their Restful maturity.
There are 4 levels, Only when the APIs reach level 4, then we can confirm it is a RESTful API.
1. Level0 -> Plain OLD xml
Http is used only as a Transport protocol. Http is used for remote interaction.
To get the data and to post the data we send request to the same URL.
2. Level1 -> Each resource is mapped to a specific URI.
Still, only one HTTP method POST is used for retrieving and creating data.

3. Level2 -> Correct HTTP verbs are used with each request.
For each of those requests, Http response code is provided.

JM-3 Page 42
For each of those requests, Http response code is provided.
4. Level3 -> The APIs support HATEOAS (Hypermedia As The Engine Of Application State)

Helps in Self-documentation.
RestController and Controller :
RestController=Controller + ResponseBody
@Controller
Used in traditional MVC applications.
Returns View (JSP, Thymeleaf, etc.) or data (if @ResponseBody is used).
If you want to return JSON/XML, you need @ResponseBody.
@RestController (@Controller + @ResponseBody)
Used in RESTful web services.
Returns data directly (JSON/XML) instead of a view.
Every method inside @RestController automatically has @ResponseBody.
ResponseEntity:
ResponseEntity<T> – Handling HTTP Responses
ResponseEntity<T> is a powerful way to send HTTP status codes, headers, and body.
It provides fine-grained control over the HTTP response.
Idemponent API :
An idempotent API is an API that produces the same result no matter how many times you call it with the same request.
If the request is executed once, twice, or multiple times, the outcome remains unchanged.

Why are Idempotent APIs Important?


Prevents duplicate operations
Ensures consistency in distributed systems
Improves reliability in network failures (retries won't cause unintended effects)
DispatcherServlet
The DispatcherServlet is the front controller in Spring MVC.
It’s the main gatekeeper that intercepts all incoming HTTP requests and dispatches them to the correct handlers (like your
controllers).
Think of it like a traffic cop 👮 directing cars (requests) to the right destinations (controllers, views, etc).
Request Life Cycle:
Client sends HTTP request (e.g. GET /users/1)
DispatcherServlet receives it (mapped to / by default)
It checks with:
HandlerMapping → Finds the right controller/method
HandlerAdapter → Invokes the controller method
Controller processes and returns:
A ModelAndView (for regular HTML)
Or a ResponseEntity / object (for REST)
ViewResolver resolves the view name to an actual template (e.g. Thymeleaf, JSP)
DispatcherServlet renders the response back to the client

JM-3 Page 43
Rest API
24 February 2025 09:26

REST stands for Representational State Transfer and API stands for Application Program Interface. REST is a software
architectural style that defines the set of rules to be used for creating web services. Web services that follow the REST
architectural style are known as RESTful web services. It allows requesting systems to access and manipulate web resources by
using a uniform and predefined set of rules. Interaction in REST-based systems happens through the Internet’s Hypertext
Transfer Protocol (HTTP).
A Restful system consists of a:
A client who requests for the resources server who has the resources.
Architectural Constraints of RESTful API
There are six architectural constraints that makes any web service are listed below:

Uniform Interface
Stateless
Cacheable
Client-Server
Layered System
Code on Demand
The only optional constraint of REST architecture is code on demand. If a service violates any other constraint, it cannot strictly
be referred to as RESTful.
Uniform Interface
It is a key constraint that differentiates between a REST API and a Non-REST API. It suggests that there should be a uniform way
of interacting with a given server irrespective of device or type of application (website, mobile app).
There are four guidelines principles of a Uniform Interface are:
Resource-Based: Individual resources are identified in requests.
Manipulation of Resources Through Representations: The client has a representation of the resource and it contains enough
information to modify or delete the resource on the server, provided it has permission to do so.
Self-descriptive Messages: Each message includes enough information to describe how to process the message so that the
server can easily analyze the request.
Hypermedia as the Engine of Application State (HATEOAS): It need to include links for each response so that client can
discover other resources easily.
Stateless :
It means that the necessary state to handle the request is contained within the request itself and server would not store
anything related to the session. In REST, the client must include all information for the server to fulfill the request whether as a
part of query params, headers or URI. Statelessness enables greater availability since the server does not have to maintain,
update or communicate that session state. There is a drawback when the client need to send too much data to the server so it
reduces the scope of network optimization and requires more bandwidth.
Cacheable
Every response should include whether the response is cacheable or not and for how much duration responses can be cached
at the client side. Client will return the data from its cache for any subsequent request and there would be no need to send the
request again to the server. A well-managed caching partially or completely eliminates some client–server interactions, further
improving availability and performance. But sometime there are chances that user may receive stale data.
Client-Server
REST application should have a client-server architecture. A Client is someone who is requesting resources and are not
concerned with data storage, which remains internal to each server, and server is someone who holds the resources and are

JM-3 Page 44
concerned with data storage, which remains internal to each server, and server is someone who holds the resources and are
not concerned with the user interface or user state. They can evolve independently. Client doesn’t need to know anything
about business logic and server doesn’t need to know anything about frontend UI.
Layered system
An application architecture needs to be composed of multiple layers. Each layer doesn’t know any thing about any layer other
than that of immediate layer and there can be lot of intermediate servers between client and the end server. Intermediary
servers may improve system availability by enabling load-balancing and by providing shared caches.
Code on demand
It is an optional feature. According to this, servers can also provide executable code to the client. The examples of code on
demand may include the compiled components such as Java Servlets and Server-Side Scripts such as JavaScript.
Rules of REST API
There are certain rules which should be kept in mind while creating REST API endpoints.
REST is based on the resource or noun instead of action or verb based. It means that a URI of a REST API should always end
with a noun.
HTTP verbs are used to identify the action. Some of the HTTP verbs are – GET, PUT, POST, DELETE, GET, PATCH.
A web application should be organized into resources like users and then uses HTTP verbs like – GET, PUT, POST, DELETE to
modify those resources. And as a developer it should be clear that what needs to be done just by looking at the endpoint and
HTTP method used.
Always use plurals in URL to keep an API URI consistent throughout the application.
Send a proper HTTP code to indicate a success or error status.
Note: You can easily use GET and POST but in order to use PUT and DELETE you will need to install method override.
HTTP verbs
Some of the common HTTP methods/verbs are described below:
GET: Retrieves one or more resources identified by the request URI and it can cache the information receive.
POST: Create a resource from the submission of a request and response is not cacheable in this case. This method is unsafe if
no security is applied to the endpoint as it would allow anyone to create a random resource by submission.
PUT: Update an existing resource on the server specified by the request URI.
DELETE: Delete an existing resource on the server specified by the request URI. It always return an appropriate HTTP status for
every request.
GET, PUT, DELETE methods are also known as Idempotent methods. Applying an operation once or applying it multiple times
has the same effect. Example: Delete any resource from the server and it succeeds with 200 OK and then try again to delete
that resource than it will display an error message 410 GONE.

The HTTP response comes with the response code. It informs about the result of the operation. It’s especially useful for UI
developers, as they can perform appropriate action basing on the code. There are the following groups of HTTP response
codes :
1xx – informational – indicates that the request was received and the process is continued. The examples are: 100 – Continue,
101 – Switching Protocols
2xx – success – when the request was received, understood, and successfully processed. The well-known examples are 200 –
OK and 201 – Created
3xx – redirection – client needs to take additional action to fulfill the request, e.g., 300 – Multiple Choice or 301 – Moved
Permanently
4xx – client errors – indicates that there is an error on the client’s side, such as 400 – Bad Request or 401 – Unauthorized
5xx- server errors – informs that an error occurred on the server’s side, e.g., 500 – Internal Server Error, 501 – Unimplemented

JM-3 Page 45
JM-3 Page 46
JM-3 Page 47
We have three ways to use @ResponseStatus to convert an Exception to an HTTP response status:
using @ExceptionHandler
using @ControllerAdvice
marking the Exception class
ResponseEntity provides two nested builder interfaces: HeadersBuilder and its subinterface, BodyBuilder.

JM-3 Page 48
Validation Framework
27 February 2025 11:31

Spring Boot provides a powerful validation framework using Jakarta Validation (formerly Javax Validation) with
Hibernate Validator as the default implementation.

JM-3 Page 49
JM-3 Page 50
Lombok
27 February 2025 11:45

Lombok is a Java library that reduces boilerplate code by auto-generating getters, setters, constructors,
toString, equals, hashCode, and more at compile time using annotations.
Why Use Lombok?
Reduces boilerplate code
Improves code readability
Enhances developer productivity
Works with Spring Boot, Hibernate, and JPA
Lombok provides compile-time annotations to reduce boilerplate code in Java applications, especially in
Spring Boot, Hibernate, and JPA projects.

JM-3 Page 51
JM-3 Page 52
Global Exception Handler
27 February 2025 11:48

In Spring Boot, we can handle exceptions globally using @ControllerAdvice and @ExceptionHandler.
This approach helps in centralizing error handling for REST APIs, improving code readability and
maintainability.

JM-3 Page 53
Mapper
27 February 2025 11:52

JM-3 Page 54
Important
21 May 2025 15:35

[Link]
Format: Simple key-value pairs
Structure: Flat and less readable for complex nested data
Example:
[Link]=8080
[Link]=jdbc:mysql://localhost:3306/mydb
[Link]=root
[Link]=pass123
🧾 [Link] or .yaml
Format: YAML (YAML Ain't Markup Language)
Structure: Supports nested and hierarchical data, more human-readable

JM-3 Page 55
Testing
14 May 2025 13:06

Testing is the process of checking if your code works as expected, helping catch bugs before users
encounter them.
Types of Testing (Key Points):
1. Smoke Testing
○ Purpose: Quick checks for core functionality and environment assumptions.
○ When: Run early in the testing cycle.
○ Goal: Catch major issues early; stop deeper testing if smoke tests fail.
2. Unit Testing
○ Purpose: Test individual units (e.g., functions, methods) in isolation.
○ Tools: Mocks/stubs used to isolate code.
○ When: Often first after smoke tests; run on developer machines and CI servers.
3. Integration Testing
○ Purpose: Ensure different components/modules work together.
○ When: After unit tests; run by CI servers automatically.
○ Catches: Bugs in inter-component communication.
4. System Testing
○ Purpose: Validate the entire system functions as a whole.
○ Focus: External interfaces, overall system behaviour.
5. Acceptance Testing
○ Purpose: Ensure software meets business/user requirements.
○ Who: Stakeholders, internal users, or beta users.
○ Types: Automated and manual; often run in staging environments.

JM-4 Page 1
Junit 5
14 May 2025 15:21

What is JUnit?
JUnit is a Java testing framework used to write and run repeatable automated tests.
JUnit 5 is the latest version, bringing more flexibility and power than JUnit 4.
JUnit 5 Structure
JUnit 5 consists of three main components:
1. JUnit Platform
○ Launches testing frameworks on the JVM.
○ Acts as a base to run tests with IDEs, build tools, and plugins.
2. JUnit Jupiter
○ Core API for writing tests using new JUnit 5 features.
○ Introduces new annotations and lifecycle methods.
3. JUnit Vintage
○ Supports running older JUnit 3 & JUnit 4 test cases on JUnit 5.
The basics of JUnit 5 are,
-> Annotations
-> Test Life cycle methods
-> Assertions
-> Assumptions
-> Parameterized Test
-> Dynamic Tests
-> Tagging and Filtering
Annotations
The JUnit 5 framework uses different Annotations based on the test case design. Mostly in JUnit 5
@Test, @BeforeEach, @AfterEach, @BeforeAll, @AfterAll, @DisplayName, @Disabled these
annotations are used. Basically, Annotations provides supplement information about the program in
java. Annotations are always start with "@" symbol. ( reference ).
@Test: Marks a method as a test method.
@BeforeEach: Indicates that the annotated method should be executed before each test.
@AfterEach: Indicates that the annotated method should be executed after each test.
@BeforeAll: Indicates that the annotated method should be executed before all tests in the test class.
@AfterAll: Indicates that the annotated method should be executed after all tests in the test class.
@DisplayName: Provides a custom name for the test class or test method.
@Disabled: Disables the test method or class.
Annotation Purpose
@Test Marks a method as a test method
@BeforeEach Runs before each test method
@AfterEach Runs after each test method
@BeforeAll Runs once before all tests in the class
@AfterAll Runs once after all tests in the class
@DisplayName Provides a custom name for the test
@Disabled Skips/ignores the test
Test Life cycle methods:
Control when setup and teardown code runs in relation to test execution, these methods are executed
at specific point in the test life cycle. The Life cycle methods are,
@BeforeEach, This Annotated method executes before each test method in the test class.

JM-4 Page 2
@BeforeEach, This Annotated method executes before each test method in the test class.
@AfterEach, This Annotated method executes after each test method in the test class, by sending
signals to JUnit
@BeforeAll, this send signals to JUnit, Like the annotated method should be executed once before all
test cased in the class.
@AfterAll, this annotation send signal to JUnit that is this annotated method should be run after all test
cases are executed in the class.
Assertions
The JUnit 5 provides different methods in Assertions class for checking the expected Result. Assertions
are used to check if a condition is true. If the condition is false, the test fails. Common assertions
include:
assertSame and assertEquals -> == and equals()

JM-4 Page 3
JM-4 Page 4
JM-4 Page 5
Mockito
24 March 2025 21:53

Unit testing is a software testing method where individual components (or units) of a program are tested independently
to ensure they function correctly. These tests are typically automated and focus on small, isolated sections of code—
such as functions or methods—without dependencies on external systems like databases or APIs.
Key Aspects of Unit Testing:
Isolation: Tests one unit at a time without external dependencies.
Automation: Often performed using frameworks like JUnit (Java), pytest (Python), or Jest (JavaScript).
Early Detection: Helps catch bugs early in development.
Regression Prevention: Ensures new changes don’t break existing functionality.
Unit testing framework :
JUnit – Most widely used for Java.
TestNG – More advanced, supports parallel execution.
Mockito – For mocking dependencies in Java tests.
To test only service layer we don’t require database but we require data to test. In this case we use the stub class.
Stub Class : dummy implementation -> sample implementation of particular classes.
A stub class is a simplified version of a class used in software testing, specifically in unit testing. It replaces a real class to
provide controlled responses for specific method calls. Stubs help isolate the unit being tested by removing
dependencies on external systems like databases, APIs, or complex logic.
Key Features of Stub Classes:
Predefined Behavior: Returns hardcoded values when methods are called.
No Logic: Unlike the real class, it doesn’t have actual logic—just placeholder implementations.
Used for Testing: Helps test code in isolation without dependencies.

DTO : (Data Transfer Object)


A DTO is an object used to transfer data between different layers of an application (e.g., from the database layer to the
service layer, or from the service layer to the frontend).
Key Characteristics:
Only holds data (no business logic).
Used for serialization (JSON, XML, etc.).
Improves efficiency by reducing the number of calls between layers.
Immutable or mutable, depending on design.
DAO (Data Access Object)
A DAO is responsible for interacting with the database. It provides an abstraction over database operations (CRUD:
Create, Read, Update, Delete).
Key Characteristics:
Encapsulates database access logic.
Helps separate business logic from database logic.
Typically uses JDBC, JPA, Hibernate, or another ORM.

JM-4 Page 6
Typically uses JDBC, JPA, Hibernate, or another ORM.

JM-4 Page 7
JM-4 Page 8
Annotations
22 May 2025 17:25

Here are the key MockMVC annotations and their uses in Spring MVC testing:
Test Setup Annotations:
@WebMvcTest -> For testing MVC controllers specifically
@AutoConfigureMockMvc -> For auto-configuring MockMvc
@SpringBootTest -> For full integration testing
Request Mapping Annotations:
@GetMapping
@PostMapping
@PutMapping
@DeleteMapping
@PatchMapping
@RequestMapping
Common MockMvc Test Annotations:
@MockBean -> Creates a mock of a bean in Spring context
@SpyBean -> Creates a spy of an existing bean
@Autowired -> Injects dependencies
MockMVC methods with descriptions and examples:
REQUEST BUILDERS
Request
[Link](get("/api/users/{id}", 1)) -> Creates GET request
Use when: Testing GET endpoints
REQUEST CUSTOMIZATION
Content Type
.contentType(MediaType.APPLICATION_JSON) -> Description: Sets request content type
Use when: Specifying request format
Accept
.accept(MediaType.APPLICATION_JSON) -> Description: Sets accepted response type
Use when: Specifying expected response format
Headers
.header("Authorization", "Bearer token") -> Adds request headers
Use when: Testing with headers
Parameters
.param("key", "value") -> Adds query parameters
Use when: Testing with query parameters
Request Body
.content([Link](object)) -> Sets request body
Use when: Testing with request body
Example:
@Test
void testCreateUser() throws Exception {
User user = new User("John");
[Link](post("/api/users")
.contentType(MediaType.APPLICATION_JSON)
.content([Link](user))
.header("Authorization", "Bearer token"))
.andExpect(status().isCreated());
}
RESPONSE MATCHERS
Status Matchers
.andExpect(status().isOk()) // 200

JM-4 Page 9
.andExpect(status().isOk()) // 200
.andExpect(status().isCreated()) // 201
.andExpect(status().isBadRequest()) // 400
.andExpect(status().isUnauthorized()) // 401
.andExpect(status().isForbidden()) // 403
.andExpect(status().isNotFound()) // 404
Verifies response status
Use when: Testing HTTP status codes
Content Matchers
.andExpect(content().contentType(MediaType.APPLICATION_JSON)) -> Verifies response content type
Use when: Testing response format
.andExpect(content().json("expected json")) -> Verifies JSON response
Use when: Testing JSON response body
.andExpect(content().string("expected string")) -> Verifies string response
Use when: Testing string response body
Example:
@Test
void testGetUser() throws Exception {
[Link](get("/api/users/1")
.accept(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
.andExpect(jsonPath("$.name").value("John"));
}
JSON PATH MATCHERS
Value Matching
.andExpect(jsonPath("$.property").value("expectedValue")) -> Verifies JSON property value
Use when: Testing specific JSON fields
Array Matching
.andExpect(jsonPath("$.items").isArray()) -> Verifies JSON array
Use when: Testing JSON arrays
Size Matching
.andExpect(jsonPath("$.[Link]()").value(3)) -> Verifies array size
Use when: Testing collection sizes
Example:
@Test
void testJsonResponse() throws Exception {
[Link](get("/api/users"))
.andExpect(status().isOk())
.andExpect(jsonPath("$[0].id").value(1))
.andExpect(jsonPath("$[0].name").value("John"))
.andExpect(jsonPath("$").isArray())
.andExpect(jsonPath("$.length()").value(2));
}
HEADER MATCHERS
Header Existence
.andExpect(header().exists("headerName")) -> Verifies header exists
Use when: Testing header presence
Header Value
.andExpect(header().string("headerName", "expectedValue")) -> Verifies header value
Use when: Testing specific header values
RESULT ACTIONS
Print Response
.andDo(print()) -> Prints request/response details

JM-4 Page 10
.andDo(print()) -> Prints request/response details
Use when: Debugging tests
Get Result
.andReturn() -> Gets test result for further assertions
Use when: Need to access response details
SECURITY TESTING
With User Authentication
@WithMockUser(username = "user", roles = {"USER"}) -> Simulates authenticated user
Use when: Testing secured endpoints
With Anonymous User
.with(anonymous()) -> Simulates anonymous access
Use when: Testing unauthenticated access
Here's a comprehensive list of Mockito annotations with explanations and examples:
@Mock -> Creates a mock instance of a class or interface
private UserRepository userRepository;
@InjectMocks -> Automatically injects mock objects into the tested class
private UserService userService;
@Spy -> Creates a real object and spies on it
private List<String> spyList = new ArrayList<>();
@Captor -> Creates an ArgumentCaptor for capturing method arguments
private ArgumentCaptor<User> userCaptor;
@ExtendWith([Link]) -> JUnit 5 extension for Mockito
public class UserServiceTest { }
@MockitoSettings -> Configures Mockito behavior for a test class
@MockitoSettings(strictness = [Link])
public class UserServiceTest { }
@MockBean (Spring Boot) -> Creates a mock bean in the Spring application context
@MockBean
private UserRepository userRepository;
@SpyBean (Spring Boot) -> Creates a spy bean in the Spring application context
@SpyBean
private UserService userService;
@WithMockUser (Spring Security) -> Simulates an authenticated user for testing
@WithMockUser(username = "admin", roles = {"ADMIN"})
public void testSecuredMethod() { }
@PrepareForTest -> Prepares classes for PowerMock testing (static methods)
@PrepareForTest([Link])
public class TestClass { }
Mockito methods with their purposes and examples:
STUBBING METHODS
Returns a specific value when the method is called
when([Link]()).thenReturn(value);
Defines what value should be returned when a specific method is called on a mock object
Use when: You need to specify the behavior of a mock method
Throws an exception when the method is called
when([Link]()).thenThrow(exception);
Makes a mock method throw an exception when called
Use when: Testing error handling scenarios
Custom response based on arguments
when([Link]()).thenAnswer(invocation -> {
Object arg = [Link](0);
return processArg(arg);
});
Provides custom logic for mock method responses

JM-4 Page 11
Provides custom logic for mock method responses
Use when: Need dynamic responses based on input parameters
VERIFICATION METHODS
Basic verification
verify(mock).method();
Verifies that a method was called exactly once
Use when: Need to ensure a method was called
Verify number of invocations
verify(mock, times(n)).method();
Verifies a method was called exactly n times
Use when: Need to check specific number of method calls
Verify method was never called
verify(mock, never()).method();
Verifies a method was never called
Use when: Need to ensure a method wasn't called
Verify at least one call
verify(mock, atLeastOnce()).method();
Verifies method was called at least once
Use when: Need to ensure minimum number of calls
Verify no more interactions
verifyNoMoreInteractions(mock);
Verifies no other methods were called on the mock
Use when: Need to ensure no unexpected method calls
ARGUMENT MATCHERS
Basic matchers
any();
anyInt();
anyString();
Matches any value of the specified type
Use when: Method arguments are not important for the test
Specific value matcher
eq(value);
Matches a specific value
Use when: Need to match exact argument values
Custom matcher
argThat(argument -> [Link]());
Creates custom matching logic
Use when: Need complex argument matching conditions
Reset mock
reset(mock);
Resets mock to clean state
Use when: Need to reset mock behavior
Clear invocations
clearInvocations(mock);
Clears recorded invocations
Use when: Need to clear interaction history

JM-4 Page 12
JM-4 Page 13
Logging
14 May 2025 13:42

Definition of Logging (in Computing):


Logging is the process of recording events that occur in a computer system, such as errors, problems, or
operational information, through log entries. These logs help monitor system behavior, debug issues,
and support audits.
Relevant Types of Logs:
1. Event Logs – Track system events for monitoring and problem diagnosis, especially in apps with
minimal user interaction.
2. Transaction Logs – Used by databases to record data changes, enabling recovery from crashes and
maintaining data consistency.
3. Message Logs – Save textual communications in chat systems or games; often stored as plain text,
HTML, or custom formats.
4. Server Logs – Maintained by servers (e.g., web servers) to log requests, including IPs, timestamps,
pages accessed, and user agents.
JCL vs SLF4J (Logging Frameworks):
• JCL (Jakarta Commons Logging): Resolves logging implementation at runtime using class loaders;
can cause issues with custom class loaders.
• SLF4J (Simple Logging Facade for Java): Resolves bindings at compile time; simpler and more
reliable.

JM-4 Page 14
Logging-Log4j
28 February 2025 09:18

Logging is the process of writing log messages during the execution of a program to a central place. This
logging allows you to report and persist error and warning messages as well as info messages (e.g.,
runtime statistics) so that the messages can later be retrieved and analyzed.
The object which performs the logging in applications is typically just called Logger.
Logs are required for debugging purpose
Why Logging
If we use SOP statements to print log messages, then we can run into some disadvantages like:
- SOP prints all the messages one by one in console, since it is a single threaded environments and it
is time consuming process.
- We can print log messages on the console only. So, when the console is closed, we will lose all of
those logs.
- We can't store log messages in any permanent place. These messages will print one by one on the
console because it is a single-threaded environment.
To overcome these problems, the Log4j framework came into the picture. Log4j is an open source
framework provided by Apache for Java projects.
Advantages of Logging:
- Quick debugging
- Problem Diagnosis
- Easy Maintenance
- Cost and Time savings
Log4j is a reliable, fast and flexible logging framework (APIs) written in Java, which is distributed under
the Apache Software License.
Log4j is highly configurable through external configuration files at runtime.
Log4j has 3 main components :
- Logger
- Appender
- Layout
It is thread-safe.
It is optimized for speed
It is based on a named logger hierarchy.
It supports multiple output appenders per logger.
Logging behavior can be set at runtime using a configuration file.
Logging is an important component of the software development. A well-written logging code offers
quick debugging, easy maintenance, and structured storage of an application's runtime information.
Logger :
Logger is a class in the [Link].log4j.* package. We have to initialize one logger object for each Java
class. We use Logger's methods to generate log statements. Log4j provides the factory method to get
logger objects.
Private static Logger logger=[Link]([Link])
Methods in Logger class:
- [Link]()
- [Link]()
- [Link]()
- [Link]()
- [Link]()
Levels :
Level is a class in the [Link].log4j.* package. Each level has a different priority order as below

JM-4 Page 15
Appender :
Appender is used to write messages into a file or DB or SMTP.
Log4j has different types of appenders.
• ConsoleAppender -> to write message on console -> by default
• DailyRollingFileAppender - writing message into File System
• FileAppender -> writing message into File System
• JDBCAppender -> writing message into DataBase
• SMTPAppender -> to send the messages to a configured email
• RollingFileAppender -> writing message into File System
Layout :
This is used to define the formatting in which logs will print in a repository.
We have different types of layouts.
• PatternLayout
• SimpleLayout
• XMLLayout
• HTMLLayout
To work with Log4j we required log4j-core and log4j-api dependencies.
To use the loggers we need to configure it , by default it uses console and it only prints the errors in
console if not configured since it use error level.
To configure the logger, we can use any format like xml, json, properties
Minimum properties required to configure logger

-5p -> five character as priority level


%c -> print class name
{n} -> if n=1 prints Class name and n= 2, prints the package of that class and so on….
%L -> Line number
%m -> message to be printed
%n -> new line
For file creation for logs

JM-4 Page 16
For log file to be html file

JM-4 Page 17
Best Practices
14 May 2025 13:54

Logging Best Practices:


1. Don't Write Logs by Yourself (Don't reinvent the wheel)
Never ever use printf or write your log entries to files by yourself, or handle log rotation by
yourself. Use Standard library or system API call for this.
Library -> Log4j, JCL, slf4j, logback
System API -> syslog(3)
2. Log at the Proper Level
One of the most difficult task is to find at what level this log entry should be logged
- Trace level: This is a code smell if used in production.
- Debug level: It is mostly used during debugging.
- Info level: log at this level all actions that are user-driven or system specific
- Notice level: This will certainly be the level at which the program will run when in production. Log
at this level all the notable events that are not considered an error.
- Warn level: log at this level all events that could potentially become an error.
- Error level: log every error condition at this level.
- Fatal level: too bad, it's doomsday. Use this very scarcely, this shouldn't happen a lot in a real
program.
3. Employ the proper log category
Simple responsibility principle
4. Write meaningful log messages
5. Write log messages in English -> ASCII characters
6. Add Context to your log messages
7. Log in Machine Parseable Format
8. But make the logs Human-Readable as well
9. Don't log too much or too little
10. Think of your audience
11. Don't log for Troubleshooting Purposes only
12. Avoid vendor Lock-in
13. Don't log sensitive information

JM-4 Page 18
Scrum
14 May 2025 12:52

What is Scrum?
Scrum is a process framework used to manage product development and other knowledge work. Scrum
is empirical in that it provides a means for teams to establish a hypothesis of how they think something
works, try it out, reflect on the experience, and make the appropriate adjustments. That is, when the
framework is used properly. Scrum is structured in a way that allows teams to incorporate practices
from other frameworks where they make sense for the team’s context.
When is Scrum Applicable?
Scrum is best suited in the case where a cross-functional team is working in a product development
setting where there is a nontrivial amount of work that lends itself to being split into more than one 2 –
4 week iteration.
Scrum Values
Teams following scrum are expected to learn and explore the following values:
Commitment
Team members personally commit to achieving team goals
Courage
Team members do the right thing and work on tough problems.
Focus
Concentrate on the work identified for the sprint and the goals of the team.
Openness
Team members and stakeholders are open about all the work and the challenges the team encounters.
Respect
Team members respect each other to be capable and independent.
Principles of Scrum
The following principles underpin the empirical nature of scrum:
Transparency
The team must work in an environment where everyone is aware of what issues other team members
are running into. Teams surface issues within the organization, often ones that have been there for a
long time, that get in the way of the team’s success.
Inspection
Frequent inspection points are built into the framework to allow the team an opportunity to reflect on
how the process is working. These inspection points include the Daily Scrum meeting and the Sprint
Review Meeting.
Adaptation
The team constantly investigates how things are going and revises those items that do not seem to
make sense.
Scrum Practices
Events
Sprint
The Sprint is a timebox of one month or less during which the team produces a potentially shippable
product Increment. Typical characteristics of Sprints:
Maintain a consistent duration throughout a development effort
A new Sprint immediately follows the conclusion of the previous Sprint
The start date and end date of Sprint are fixed
Sprint Planning
A team starts out a Sprint with a discussion to determine which items from the product backlog they will
work on during the Sprint. The end result of Sprint Planning is the Sprint Backlog.
Sprint Planning typically occurs in two parts. In the first part, the product owner and the rest of the team
agree on which product backlog items will be included in the Sprint.
In the Second Part of Sprint Planning, the team determines how they will successfully deliver the
identified product backlog items as part of the potentially shippable product increment. The team may

JM-5 Page 1
identified product backlog items as part of the potentially shippable product increment. The team may
identify specific tasks necessary to make that happen if that is one of their practices. The product
backlog items identified for delivery and tasks if applicable make up the Sprint Backlog.
Once the team and product owner establish the scope of the Sprint as described by the product backlog
items no more items can be added to the Sprint Backlog. This protects the team from scope changes
within that Sprint.
Daily Scrum
The Daily Scrum is a short (usually limited to 15 minutes) discussion where the team coordinates their
activities for the following day. The Daily Scrum is not intended to be a status reporting meeting or a
problem-solving discussion.
Sprint Review
At the end of the Sprint, the entire team (including the product owner) reviews the results of the sprint
with stakeholders of the product. The purpose of this discussion is to discuss, demonstrate, and
potentially give the stakeholders a chance to use, the increment in order to get feedback. The Sprint
Review is not intended to provide a status report. Feedback from the sprint review gets placed into the
Product Backlog for future consideration.
Sprint Retrospective
At the end of the Sprint following the sprint review, the team (including the product owner) should
reflect upon how things went during the previous sprint and identify adjustments they could make going
forward. The result of this retrospective is at least one action item included on the following Sprint’s
Sprint Backlog.
Artifacts
Product Backlog
The product backlog is an ordered list of all the possible changes that could be made to the product.
Items on the product backlog are options, not commitments in that just because they exist on the
Product Backlog does not guarantee they will be delivered. The Product Owner maintains the product
backlog on an ongoing basis including its content, availability, and ordering.
Sprint Backlog
The Sprint Backlog is the collection of product backlog items selected for delivery in the Sprint, and if the
team identifies tasks, the tasks necessary to deliver those product backlog items and achieve the Sprint
Goal.
Increment
The increment is the collection of the Product Backlog Items that meet the team’s Definition of Done by
the end of the Sprint. The Product Owner may decide to release the increment or build upon it in future
Sprints.
Definition of Done
The definition of done is a team’s shared agreement on the criteria that a Product Backlog Item must
meet before it is considered done.
Roles
The Product Owner
The product owner is a role team responsible for managing the product backlog in order to achieve the
desired outcome that the team seeks to accomplish. The product owner role exists in Scrum to address
challenges that product development teams had with multiple, conflicting directions or no direction at
all with respect to what to build.
The Scrum Master
The scrum master is the team role responsible for ensuring the team lives agile values and principles and
follows the processes and practices that the team agreed they would use. The name was initially
intended to indicate someone who is an expert at Scrum and can therefore coach others. The role does
not generally have any actual authority. People filling this role have to lead from a position of influence,
often taking a servant-leadership stance.
The Development Team
The development team consists of the people who deliver the product increment inside a Sprint. The
main responsibility of the development team is to deliver the increment that delivers value to every
Sprint. How the work is divided up to do that is left up to the team to determine based on the conditions

JM-5 Page 2
Sprint. How the work is divided up to do that is left up to the team to determine based on the conditions
at that time.
Lifecycle
Scrum is a framework that allows development teams the flexibility to respond to changing situations.
This framework has sufficient control points in place to ensure the team does not stray from the desired
outcome, and that issues can be identified and resolved and process adjustments made while the effort
is still underway.
The Scrum Lifecycle starts with a prioritized backlog but does not provide any guidance as to how that
backlog is developed or prioritized.
The Scrum Lifecycle consists of a series of Sprints, where the end result is a potentially shippable
product increment. Inside these sprints, all of the activities necessary for the development of the
product occur on a small subset of the overall product. Below is a description of the key steps in the
Scrum Lifecycle:
Establish the Product Backlog.
The product owner and development team conduct Sprint Planning. Determine the scope of the Sprint
in the first part of Sprint Planning and the plan for delivering that scope in the second half of Sprint
Planning.
As the Sprint progresses, the development team performs the work necessary to deliver the selected
product backlog items.
On a daily basis, the development team coordinates their work in a Daily Scrum.
At the end of the Sprint, the development team delivers the Product Backlog Items selected during
Sprint Planning. The development team holds a Sprint Review to show the customer the increment and
get feedback. The development team and product owner also reflect on how the Sprint has proceeded
so far and adapted their processes accordingly during a retrospective.
The Team repeats steps 2–5 until the desired outcome of the product has been met.

JM-5 Page 3
Agile Methodology
14 May 2025 12:52

Agile Software Development is an iterative and incremental approach to Software Development that
emphasizes the importance of delivering a working product quickly and frequently. It involves close
collaboration between the development team and the customer to ensure that the product meets their
needs and expectations.
Why is Agile Used?
Agile is used because it helps teams deliver value quickly and continuously. By prioritizing the delivery of
difficult results early in the project, customers benefit from seeing and using the product sooner,
allowing for quick feedback and adjustments. Agile also encourages teams to focus on what truly
matters, concentrating on tasks that add value and avoiding unnecessary work.
Agile as a Mindset: Agile represents a shift in culture that values adaptability, collaboration, and client
happiness. It gives team members more authority and promotes a cooperative and upbeat work
atmosphere.
Quick Response to Change: Agile fosters a culture that allows teams to respond swiftly to constantly
shifting priorities and requirements. This adaptability is particularly useful in sectors of the economy or
technology that experience fast changes.
Regular Demonstrations: Agile techniques place a strong emphasis on regular demonstrations of project
progress. Stakeholders may clearly see the project’s status, upcoming problems, and upcoming new
features due to this transparency.
Cross-Functional Teams: Agile fosters self-organizing, cross-functional teams that share information
effectively, communicate more effectively and feel more like a unit.
Agile Software Development Process
Agile software development, often just called Agile, focuses on being flexible and practical when
delivering software. Instead of launching everything at once, Agile delivers small, valuable updates to
users over time. This approach allows teams to adjust and improve the product along the way, verifying
that each update brings real value to the users. It’s all about making progress in manageable steps and
responding quickly to changes.
Agile Software Development
1. Requirements Gathering
This is the first step where the development team works closely with the customer to understand what
they really need from the software. The team listens carefully to the customer’s needs, then sorts and
prioritizes these requirements to make sure the most important features are developed first.
2. Planning
In this stage, the team creates a clear plan for how they’ll build the software. They decide which

JM-5 Page 4
In this stage, the team creates a clear plan for how they’ll build the software. They decide which
features to focus on in each development cycle (called an iteration). Think of it like mapping out the
journey of the project, so everyone knows what to expect and when things will be delivered.
3. Development
This is where the team starts turning their plan into reality. They work in short, focused cycles, building
small, usable pieces of the product. Each cycle builds on the last, which helps the team stay on track and
get quick feedback to keep improving.
4. Testing
As the software gets built, it’s also tested to make sure it works properly and meets the customer’s
needs. Testing ensures the product is of high quality and free from errors, so problems are caught early
on before they become bigger issues.
5. Deployment
Once everything is tested and working as expected, the software is deployed, which means it’s ready for
customers or end-users to start using. It’s the moment when all the development work comes to life.
6. Maintenance
Even after the software is released, the job isn’t done. The team keeps maintaining the software,
verifying it continues to work well and stays up-to-date with any new needs or changes from the
customer. This keeps the software relevant and helpful over time.
Agile Software Development Cycle
Step 1: In the first step, concept, and business opportunities in each possible project are identified and
the amount of time and work needed to complete the project is estimated. Based on their technical and
financial viability, projects can then be prioritized and determined which ones are worthwhile pursuing.
Step 2: In the second phase, known as inception, the customer is consulted regarding the initial
requirements, team members are selected, and funding is secured. Additionally, a schedule outlining
each team’s responsibilities and the precise time at which each sprint’s work is expected to be finished
should be developed.
Step 3: Teams begin building functional software in the third step, iteration/construction, based on
requirements and ongoing feedback. Iterations, also known as single development cycles, are the
foundation of the Agile software development cycle.
4 Core Values of Agile Software Development
The four core values of Agile software development, as outlined in the Agile Manifesto, focus on what
truly matters for creating successful software. The Agile Software Development Methodology Manifesto
describe four core values of Agile in software development.
1. Individuals and Interactions over Processes and Tools: This value stresses that the strength of the
team and how well they work together is more important than the tools or processes they use. Of
course, tools and processes help, but the real success of a project comes from good teamwork, open
communication, and collaboration.
2. Working Software over Comprehensive Documentation: Agile prefers delivering functional software
quickly rather than getting down in lengthy documentation. While some documentation is needed, the
focus is on getting a working product into the hands of the user and improving it based on feedback.
3. Customer Collaboration over Contract Negotiation: Agile values regular collaboration with customers
over sticking strictly to contracts. The idea is to involve the customer throughout the development,
verifying that the product meets their needs and making adjustments based on their feedback.
4. Responding to Change over Following a Plan: In Agile, change is expected, and the approach
encourages flexibility. Rather than rigidly following a plan that may no longer apply, Agile teams adapt
and adjust based on new information, changing market conditions, or including customer requirements.
12 Principles of Agile Software Development
There are 12 agile principles mentioned in the Agile Manifesto. Agile principles are guidelines for flexible
and efficient software development. They emphasize frequent delivery, embracing change,
collaboration, and continuous improvement. The focus is on delivering value, maintaining a sustainable
work pace, and ensuring technical excellence.
These principles include:
Ensuring customer satisfaction through the early delivery of software.
Being open to changing requirements in the stages of the development.

JM-5 Page 5
Being open to changing requirements in the stages of the development.
Frequently delivering working software with a main focus on preference for timeframes.
Promoting collaboration between business stakeholders and developers as an element.
Structuring the projects around individuals. Providing them with the necessary environment and
support.
Prioritizing face to face communication whenever needed.
Considering working software as the measure of the progress.
Fostering development by allowing teams to maintain a pace indefinitely.
Placing attention on excellence and good design practices.
Recognizing the simplicity as crucial factor aiming to maximize productivity by minimizing the work.
Encouraging self organizing teams as the approach to design and build systems.
Regularly reflecting on how to enhance effectiveness and to make adjustments accordingly.
Advantages Agile Software Development
Increased collaboration and communication: Agile Software Development Methodology emphasize
collaboration and communication among team members, stakeholders, and customers. This leads to
improved understanding, better alignment, and increased buy-in from everyone involved.
Flexibility and adaptability: Agile methodologies are designed to be flexible and adaptable, making it
easier to respond to changes in requirements, priorities, or market conditions. This allows teams to
quickly adjust their approach and stay focused on delivering value.
Improved quality and reliability: Agile methodologies place a strong emphasis on testing, quality
assurance, and continuous improvement. This helps to ensure that software is delivered with high
quality and reliability, reducing the risk of defects or issues that can impact the user experience.
Enhanced customer satisfaction: Agile methodologies prioritize customer satisfaction and focus on
delivering value to the customer. By involving customers throughout the development process, teams
can ensure that the software meets their needs and expectations.
Increased team morale and motivation: Agile methodologies promote a collaborative, supportive, and
positive work environment. This can lead to increased team morale, motivation, and engagement, which
can in turn lead to better productivity, higher quality work, and improved outcomes.
Deployment of software is quicker and thus helps in increasing the trust of the customer.
Can better adapt to rapidly changing requirements and respond faster.
Helps in getting immediate feedback which can be used to improve the software in the next increment.
People – Not Process. People and interactions are given a higher priority than processes and tools.
Continuous attention to technical excellence and good design.
Disadvantages Agile Software Development
Lack of predictability: Agile Development relies heavily on customer feedback and continuous iteration,
which can make it difficult to predict project outcomes, timelines, and budgets.
Limited scope control: Agile Development is designed to be flexible and adaptable, which means that
scope changes can be easily accommodated. However, this can also lead to scope creep and a lack of
control over the project scope.
Lack of emphasis on testing: Agile Development places a greater emphasis on delivering working code
quickly, which can lead to a lack of focus on testing and quality assurance. This can result in bugs and
other issues that may go undetected until later stages of the project.
Risk of team burnout: Agile Development can be intense and fast-paced, with frequent sprints and
deadlines. This can put a lot of pressure on team members and lead to burnout, especially if the team is
not given adequate time for rest and recovery.
Lack of structure and governance: Agile Development is often less formal and structured than other
development methodologies, which can lead to a lack of governance and oversight. This can result in
inconsistent processes and practices, which can impact project quality and outcomes.
In the case of large software projects, it is difficult to assess the effort required at the initial stages of the
software development life cycle.
Agile Development is more code-focused and produces less documentation.
Agile development is heavily dependent on the inputs of the customer. If the customer has ambiguity in
his vision of the outcome, it is highly likely that the project to get off track.
Face-to-face communication is harder in large-scale organizations.

JM-5 Page 6
Face-to-face communication is harder in large-scale organizations.
Only senior programmers are capable of making the kind of decisions required during the development
process. Hence, it’s a difficult situation for new programmers to adapt to the environment.
Practices of Agile Software Development
Scrum: Scrum is a framework for agile software development that involves iterative cycles called sprints,
daily stand-up meetings, and a product backlog that is prioritized by the customer.
Kanban: Kanban is a visual system that helps teams manage their work and improve their processes. It
involves using a board with columns to represent different stages of the development process, and
cards or sticky notes to represent work items.
Continuous Integration: Continuous Integration is the practice of frequently merging code changes into
a shared repository, which helps to identify and resolve conflicts early in the development process.
Test-Driven Development: Test-Driven Development (TDD) is a development practice that involves
writing automated tests before writing the code. This helps to ensure that the code meets the
requirements and reduces the likelihood of defects.
Pair Programming: Pair programming involves two developers working together on the same code. This
helps to improve code quality, share knowledge, and reduce the likelihood of defects.
Advantages of Agile over traditional software development approaches
Increased customer satisfaction: Agile development involves close collaboration with the customer,
which helps to ensure that the software meets their needs and expectations.
Faster time-to-market: Agile development emphasizes the delivery of working software in short
iterations, which helps to get the software to market faster.
Reduced risk: Agile development involves frequent testing and feedback, which helps to identify and
resolve issues early in the development process.
Improved team collaboration: Agile development emphasizes collaboration and communication
between team members, which helps to improve productivity and morale.
Adaptability to change: Agile Development is designed to be flexible and adaptable, which means that
changes to the project scope, requirements, and timeline can be accommodated easily. This can help
the team to respond quickly to changing business needs and market demands.
Better quality software: Agile Development emphasizes continuous testing and feedback, which helps to
identify and resolve issues early in the development process. This can lead to higher-quality software
that is more reliable and less prone to errors.
Increased transparency: Agile Development involves frequent communication and collaboration
between the team and the customer, which helps to improve transparency and visibility into the project
status and progress. This can help to build trust and confidence with the customer and other
stakeholders.
Higher productivity: Agile Development emphasizes teamwork and collaboration, which helps to
improve productivity and reduce waste. This can lead to faster delivery of working software with fewer
defects and rework.
Improved project control: Agile Development emphasizes continuous monitoring and measurement of
project metrics, which helps to improve project control and decision-making. This can help the team to
stay on track and make data-driven decisions throughout the development process.

JM-5 Page 7
CI v/s CD
14 May 2025 13:03

What are the differences between continuous integration, continuous delivery, and continuous
deployment (CI/CD)?
Continuous integration
Developers practicing continuous integration merge their changes back to the main branch as often as
possible. The developer's changes are validated by creating a build and running automated tests against
the build. By doing so, you avoid integration challenges that can happen when waiting for release day to
merge changes into the release branch.
Continuous integration puts a great emphasis on testing automation to check that the application is not
broken whenever new commits are integrated into the main branch.
Continuous delivery
Continuous delivery is an extension of continuous integration since it automatically deploys all code
changes to a testing and/or production environment after the build stage.
This means that on top of automated testing, you have an automated release process and you can
deploy your application any time by clicking a button.
In theory, with continuous delivery, you can decide to release daily, weekly, fortnightly, or whatever
suits your business requirements. However, if you truly want to get the benefits of continuous delivery,
you should deploy to production as early as possible to make sure that you release small batches that
are easy to troubleshoot in case of a problem.
Continuous deployment
Continuous deployment goes one step further than continuous delivery. With this practice, every
change that passes all stages of your production pipeline is released to your customers. There's no
human intervention, and only a failed test will prevent a new change to be deployed to production.
Continuous deployment is an excellent way to accelerate the feedback loop with your customers and
take pressure off the team as there isn't a "release day" anymore. Developers can focus on building
software, and they see their work go live minutes after they've finished working on it.

JM-5 Page 8
Microservices Architecture
17 April 2025 09:36

On-premises Datacenter : A company keeps all of their IT environment on the premises of the
organization and maintained by IT team.
Disadvantages of On-premises Datacenter:
- Privacy
- Cost - Significant upfront hardware and software costs.
- Publicly not accessible
- Managing is difficult since it requires big specialized team
- Agility and Scalability
- Security - solid security policy and in-house expertise is needed.
- Disaster recovery and backup
- IT support
Advantages of Cloud over On-Premises:
- Cost : Pat as you use
- Security : Delivery superior data security
- Recovery and backup : Regular backup takes place
- Agility and Scalability : Cloud resources can be easily adjusted
- IT support : IT team can manage more with less time and effort
Cloud Providers:
Google -> Google Cloud Provider
Microsoft -> Azure
Amazon -> AWS
Monolithic application:
All modules in single application under single server.

Advantages :
- Single server for whole application.
- One deployment is required for all the modules.
Drawbacks
- Agility : If application is too large and complex to understand, it is challenging to make changes
fast and correctly.
- Scalability : We can't scale individual modules, so we always scale entire application
- Reliability : Buy in any module (ex: memory leak) can potentially bring down the entire process.
- Tightly coupled
Microservices:

JM-6 Page 1
Advantages:
- Loosely coupled
- Agility : Services are smaller and faster development and testing
- Scalability : Each service can scale individually as per the need and requirement
- Reliability : Bug in any service (Ex : memory leak) can impact only that service
- Deployment Time : Services can be deployed independently and can start quickly
- Eliminates any long-term commitment to a technology stack.
Common Problems :
- Need to rebuild on every configuration change - Centralized
Configuration
- No self registry and discovery - Service Registry (common to all services IP address )
- No centralized way to communicate outsiders - Single server with multiple client - API Gateway
- No self-healing
- No centralized logs monitoring
- No distributed tracing
- Server-side and client-side load balancing : Microservices uses client-side load balancing as help in
traffic management
- Distributed communication

Load Balancer : Handles the traffic and routes the api's to multiple server. Handles which server to be
called from the server

JM-6 Page 2
1. Centralized Configuration
• Tool: Spring Cloud Config Server
• Purpose: Manages externalized configuration in a distributed system.
• Benefit: Centralized management of properties across all environments (Dev, QA, Prod).
2. Service Registry
• Tool: Spring Cloud Eureka Server
• Purpose: Service discovery — helps microservices find and communicate with each other.
• Benefit: Avoids hard-coding host/port; simplifies dynamic scaling.
3. API Gateway
• Tool: Spring Cloud Gateway
• Purpose: Routes API requests to appropriate microservices.
• Benefit: Adds security, monitoring, metrics, and resiliency at the entry point.
4. Fault Tolerance
• Tool: Hystrix (by Netflix)
• Purpose: Adds resilience to services by handling failures and latency gracefully.
• Benefit: Prevents cascading failures by isolating failing services.
5. Logging and Tracing
• Tools: Spring Cloud Sleuth & Zipkin
• Purpose: Distributed tracing by attaching trace IDs and span IDs to logs.
• Benefit: Helps analyse and troubleshoot latency issues in complex systems.
6. Load Balancing
• Tools: Ribbon / Spring Cloud Load Balancer
• Purpose: Client-side load balancing of HTTP/TCP traffic.
• Benefit: Direct communication with services (no extra network hops), offering fine-grained
control.

JM-6 Page 3
control.

JM-6 Page 4
Eureka Server
21 April 2025 11:10

Eureka server behaves like a private DNS for the cluster of services from the cloud
Interactions between the services is handled by the eureka
It is naming server named Netflix Eureka Server, it acts like a DNS, every information will be stored at
server side.
When the client server is started then it automatically registers itself in eureka server and passes the IP
address and port number to the eureka server.
Server will store the service name rather than storing all the IP address and port number of the service
from the application properties.
Eureka Server maintains the details of the server and client which are running.
Microservices Communication:
Microservices may need to communicate to execute some tasks - REST - one service can access the
other service with the IP address and port number of that service.
Direct communication Limitations:
- Not Practical : It is not practical to know the IP address and port number of each microservices as
there are multiple microservices to connect from client
- Dynamic Host & IP : whenever the IP address or port number get changed
Service Registration and Discovery:
When we sign in into Chat Client
- We are registered with the server - Server knows about you, that we are online
- At the same time, Server provides list of all known clients.
- Displays all our contacts who are online at that time.
Here we as a client has discovered other clients in exchange for the act of registering / login. Other side,
client has itself been discovered by other clients.
It provides lookup service that is self-maintaining because the client registers themselves and, in the
process, it discover the other registrations.
Service Registration and Discovery : Eureka
The microservices should register themselves in the centralized location (Eureka Server) with an
identifier by providing their details such as host name, IP address, port and health indicators etc. This is
known as Service Registration.
Each microservice should be able to look up the list of registered services in the centralized location and
it is known as Service Discovery
Eureka Server is an implementation for the Service Registration and Discovery pattern
The Eureka server will maintain a list of registered microservices with their provided details. Eureka
server expects continuous ping messages (known as heartbeats) from the registered microservices to
verify they are alive (up and running)
If any service fails to send the heartbeat (ping message) continuously, it will be considered as a dead
service and will be removed from the registry.

JM-6 Page 5
For server,
[Link]-with-eureka=false -> mark is as server and do not create any registry
[Link]-registry=false -> don’t try to fetch the registry from the server

[Link]=library-service -> Names the microservice library-service.


This name is important for Eureka registration and discovery, and is used when other services route to
this one.
[Link]=8083 -> Sets the port for this microservice to run on: [Link]
🌐 Eureka Client Configuration
[Link]=[Link] -> Tells this service where the

JM-6 Page 6
[Link]=[Link] -> Tells this service where the
Eureka Server is located.
defaultZone is the default URL used to register with Eureka.
[Link]-ip-address=true -> Registers the service using the IP address instead of the
hostname.
Useful when running in Docker or cloud environments where DNS/hostnames are unreliable.
[Link]-with-eureka=true -> Tells the service to register itself with Eureka.
[Link]-registry=true -> Enables this service to fetch the list of other registered services from
Eureka — essential for inter-service communication.
🗄 Database Configura on (MySQL)
[Link]=jdbc:mysql://localhost:3306/microservice -> JDBC URL for the MySQL database
named microservice.
[Link]=root
[Link]=root
Credentials to connect to the MySQL database.
[Link]-class-name=[Link] -> JDBC driver class for MySQL 8+.
🛠 JPA (Java Persistence API) / Hibernate Configura on
[Link]-platform=[Link].MySQL8Dialect
Tells Hibernate to use SQL dialect specific to MySQL 8 for compatibility.
[Link]-auto=update -> Automatically creates or updates the database schema based
on your JPA entities.
Options include:
none
validate
update
create
create-drop
[Link]-sql=true -> Logs the actual SQL queries generated by Hibernate to the console — helpful
for debugging.
📝 Logging Configuration
[Link]=INFO -> Logs Spring framework-related messages at INFO level.
[Link]=DEBUG -> Logs raw SQL statements executed by Hibernate.
[Link]=TRACE -> Logs the binding of parameter
values to SQL queries (e.g., binding id=5 to SELECT * FROM ... WHERE id=?).
[Link]=%d{yyyy-MM-dd HH:mm:ss} - %msg%n -> Customizes the log output format in
the console.
Here, it shows: Date and time, Log message, New line
⚙ Advanced Spring MVC & Boot Behavior
[Link]-exception-if-no-handler-found=true -> Throws an exception instead of returning a 404
error when no controller is found for a request.
Useful for customizing error handling (e.g., global exception handlers).
[Link]-bean-definition-overriding=true -> Allows one Spring bean definition to override
another of the same name.
Useful in test setups or when custom configuration beans override defaults.
🔧 Configuration for Eureka Server
[Link]=8761
This sets the port on which the Eureka server will run.
Default port for Eureka is 8761, so this is the standard setup.
[Link]=eureka-server
This gives a name to the application.
The name is mainly used for identification/logging purposes and can appear in Eureka dashboards or
logs.
[Link]-with-eureka=false
Disables self-registration of this service with Eureka.

JM-6 Page 7
Disables self-registration of this service with Eureka.
Since this is the Eureka Server itself, it should not register with itself as a client — hence this is set to
false.
[Link]-registry=false
Disables fetching the registry from other Eureka servers.
This is because this server is acting as a standalone Eureka Server and doesn’t need to fetch service info
from others.
If you were running multiple Eureka servers in a clustered setup, you might set this to true to allow peer
discovery.
1. @SpringBootApplication: This is a convenience annotation that includes:
@Configuration: Allows Java-based Spring configuration.
@EnableAutoConfiguration: Automatically configures Spring application based on dependencies.
@ComponentScan: Scans the current package and subpackages for Spring-managed components.
Yes, it's required for all Spring Boot apps — it bootstraps the entire application.
2. @EnableEurekaServer: This annotation enables the Eureka Server in your Spring Boot application.
It brings in all the necessary configuration to expose the Eureka dashboard at [Link]
Allows other microservices (Eureka clients) to register themselves and discover each other through the
registry.
Yes, it's required to turn your Spring Boot app into a Eureka Server.
3. (Optional) @Configuration, @Component, @RestController
These annotations are not required just for a Eureka Server, but they can be used for extending or
customizing its behavior:
Annotation Purpose Example Use
@ConfigurationDeclare a Java configuration class Add custom beans
@Component Mark a class as a Spring-managed bean Custom health indicators
@RestController Create custom REST endpoints /status, custom diagnostics

JM-6 Page 8
Feign REST Client
21 April 2025 12:21

Feign is a declarative web service client. It makes writing web service clients easier. To use Feign create
an interface and annotate it. It has pluggable annotation support including feign annotations and JAX-RS
annotations.
Reduces the boilerplate code required for the REST API.
Feign Client also known as Spring Cloud Open Feign is a Declarative REST Client in Spring Boot Web
Application. Declarative REST Client means we need to specify the client specification as an Interface
and Spring Boot will take care of the implementation for us. Writing web services with the help of Feign
Client is very easier. Feign Client is mostly used to consume REST API endpoints which are exposed by
third-party or microservice.
What is RestTemplate?
RestTemplate is a synchronous client provided by Spring for making HTTP requests. It was introduced in
Spring 3 and has been widely used for many years. However, it is being deprecated in favor of more
modern solutions like WebClient.
Key Features of RestTemplate
- Synchronous: RestTemplate is a blocking client, meaning it waits for the server to respond before
proceeding. This can result in slower performance, especially when dealing with many requests.
- Easy to Use: It provides straightforward methods to perform common HTTP operations like GET,
POST, PUT, DELETE, etc.
- Configuration: Allows configuration of headers, request parameters, and timeouts.

What is WebClient?
WebClient is a non-blocking, reactive client introduced in Spring 5 as part of the WebFlux framework. It
is designed for reactive programming and offers better performance for applications that need to
handle multiple requests concurrently.
Key Features of WebClient
- Asynchronous: WebClient is non-blocking, allowing it to handle many requests simultaneously
without waiting for each one to finish.
- Reactive: Built on top of Project Reactor, making it suitable for reactive applications.
- Modern: Recommended for new Spring applications due to its flexibility and performance.
- Streaming: Supports streaming of data, making it ideal for handling large datasets.

JM-6 Page 9
What is Feign Client?
Feign Client is a declarative HTTP client developed by Netflix and integrated with Spring Cloud. It
simplifies HTTP API consumption by allowing you to define HTTP clients using interfaces and
annotations. Feign Client is well-suited for microservices architecture and can be integrated with other
Spring Cloud components.
Key Features of Feign Client
- Declarative: Allows you to define HTTP clients using interfaces and annotations, making the code
cleaner and more readable.
- Load Balancing: Integrates seamlessly with Netflix Ribbon for client-side load balancing.
- Fault Tolerance: Can be integrated with Netflix Hystrix for circuit breaker functionality.
- Integration: Works well with other Spring Cloud components, making it ideal for microservices.

JM-6 Page 10
JM-6 Page 11
When to Use:
- RestTemplate:
Use in legacy applications where blocking operations are sufficient.
Simple use cases with straightforward HTTP operations.
- WebClient:
Use in new applications that require non-blocking and reactive operations.
Applications that need to handle many concurrent requests efficiently.
Projects that require streaming data or advanced HTTP interactions.
- Feign Client:
Use in microservices architectures to simplify HTTP API consumption.
When you want to leverage Spring Cloud features like load balancing and circuit breaking.
Declarative syntax makes it easier to manage and read.

JM-6 Page 12
API Gateway
25 April 2025 09:44

Why gateway?
- All the services has different port number if we want to use all the services in single port then api
gateway is used.
- Easy to host a single IP address rather than hosting all the service api's
API Gateway :
It acts as a single point of contact or a single entry point of contact for the clients who want to interact
with the multiple services behind the gateway. It acts as a reverse proxy (A reverse proxy is a type of
server that sits in front of one or more backend servers and forwards client (e.g., browser) requests to
those servers. It's called "reverse" because, unlike a forward proxy, which sits between clients and the
internet, a reverse proxy sits between the internet and web servers.)
- An API gateway is an API management tool that sits between a client and a collection of backend
services.
- An API gateway acts as a reverse proxy to accept all application programming interface (API) calls,
aggregate the various services required to fulfill them, and return the appropriate result.

All services can be on private IP addresses and api gateway can be on public IP address.
Without gateway :

With Gateway :

Why API Gateway?


- Insulates the clients from how the application is partitioned into microservices.
- Insulates the clients from the problem of determining the locations of service instances
- Provides the optimal API for each client.
- Reduces the number of requests/roundtrips.

JM-6 Page 13
- Reduces the number of requests/roundtrips.
For example, the API gateway enables clients to retrieve data from multiple services with a single
round-trip. Fewer requests also means less overhead and improves the user experience. An API
gateway is essential for mobile applications.
- Simplifies the client by moving logic for calling multiple services from the client to API gateway
Security
Abstraction
Auditing
Routing
Loose Coupling
API gateway drawbacks :
- Increased complexity
The API gateway is yet another moving part that must be developed, deployed and managed
- Latency
Increased response time due to additional network hop through the API gateway - however, for
most applications the cost of an extra roundtrip is insignificant
Variation : Backends for frontends
A variation of this pattern is the backends for frontends pattern. It defines a separate API gateway for
each kind of client.

API gateway Providers :


- Zuul :
Zuul is a blocking API.
A blocking gateway API makes use of as many threads as the number of incoming requests. So,
this approach is more resource intensive.
If no threads are available to process the incoming request, then the request has to wait in queue.
- Spring Cloud gateway :
Spring Cloud gateway is an non-blocking API.
A thread is always available to process the incoming request. These requests are then processed
asynchronously in the background and once completed the response is returned
So, incoming requests never gets blocked when using Spring Cloud gateway.
Spring Cloud gateway :
Spring cloud gateway is an implementation by Spring Cloud team on top of Spring reactive ecosystem.
It has the following building blocks :
- Route : Route the basic building block of the gateway. It consists of ID, destination URI, Collection
of predicates and a collection of filters
- Predicate : This is similar to Java 8 Function Predicate. Using this functionality we can match HTTP
request, such as headers, URI, cookies or parameters.
- Filter : These are instances Spring Framework Gateway Filter. Using this we can modify the
request or response as per the requirement.
Spring Cloud Gateway Architecture :

JM-6 Page 14
Filters follows the chain responsibility design patterns
Implementation :

Predicates types are path predicate, cookie predicate, header predicate, parameter predicate, request
parameter predicate
Route Predicate factories :
- After Route Predicate factory
- Before Route Predicate factory
- Between Route Predicate factory
- Cookie Route Predicate factory
- Header Route Predicate factory
- Host Route Predicate factory
- Method Route Predicate factory
- Path Route Predicate factory
- Query Route Predicate factory
- RemoteAddr Route Predicate factory
- Weight Route Predicate factory
Spring Cloud Gateway Architecture
The main components of the spring cloud gateway are:
Route: It is an important component in the spring cloud gateway. I consist of ID, destination URI,
predicates, and filters.
Predicates: It is the same as Java 8 function predicate. A Predicate simply evaluates the input against a
condition defined by the Predicate and returns true if the condition is satisfied. Here the Predicate is
used to match the HTTP requests. A route is matched if the Predicate returns true.
Filter Chain: It is a series of filters applied to incoming requests and responses. It can be used for various
purposes like authentication, requests or response transformation, and many more
Spring Cloud Gateway Implementation
There are two ways to create an API gateway.
Programmatic configuration: Here we create Spring Cloud Gateway as Java bean. The routes, predicates,
and all are created as a traditional Java program using RouteLocator
Property configuration: Here, we create components of Spring Cloud Gateway as properties in the
[Link] or [Link] file.
[Link]
General Application Configuration
[Link]=api-gateway

JM-6 Page 15
[Link]=api-gateway
Sets the name of the Spring Boot application. This is important for Eureka registration and identifying
the service.
[Link]=8080
The port number the application will run on. In this case, the gateway runs on port 8080.
🌐 Eureka Client Configuration
[Link]=[Link]
Tells the application where the Eureka server is located. It’s used for service registration and discovery.
[Link]-with-eureka=true
Indicates that this application (the gateway) should register itself with Eureka.
[Link]-registry=true
Tells the application to fetch the registry of other services from Eureka. This allows it to discover other
services like book-service, user-service, etc.
🌉 Spring Cloud Gateway (MVC Style) Configuration
[Link]=true
Enables Spring Cloud Gateway using Spring MVC instead of the reactive stack (WebFlux). This is helpful if
you're using Spring MVC throughout your project.
[Link]=/
Sets the root path of the servlet to /. This means the app handles requests from the root URL.
🛣 Routes Configura on (Gateway Routes)
These define routing rules for the gateway. Each route has an id, a uri, and one or more predicates.
📘 Route 0: Book Service
[Link][0].id=book-service
[Link][0].uri=lb://book-service
[Link][0].predicates[0].name=Path
[Link][0].predicates[0].args[pattern]=/books/**
id: Identifier for the route.
uri: Uses lb:// (load balancer) to send requests to a registered service called book-service in Eureka.
predicate: Matches any incoming requests with path starting /books/** and routes them to the book-
service.
📈 Actuator Configuration
[Link]=*
Exposes all Spring Boot Actuator endpoints (like /actuator/health, /actuator/routes, etc.) over HTTP for
monitoring and management.
📝 Logging Configuration
[Link]=DEBUG
[Link]=DEBUG
Sets detailed logging levels for troubleshooting:
[Link]=DEBUG enables debug logs for all Spring Web components.
[Link]=DEBUG enables debug logs specifically for the Gateway's internal
logic.
✅ Core Annotations for the API Gateway
@SpringBootApplication -> Main entry point for Spring Boot applications. Combines @Configuration,
@EnableAutoConfiguration, and @ComponentScan.
@EnableDiscoveryClient -> Enables the gateway to register itself with Eureka or any other discovery
service. Required if you're using Eureka for service discovery.
@EnableConfigurationProperties(optional) -> Enables support for externalized configuration classes, if
you define custom configuration properties.
@Configuration -> To define a class as a source of bean definitions for route configuration.
@Bean -> To manually define beans, e.g., route definitions using Java DSL (not always needed if using
properties).
@RestController -> If you want to expose any custom endpoints from the API Gateway (like a /status or
diagnostics endpoint).

JM-6 Page 16
diagnostics endpoint).
@RequestMapping -> For mapping HTTP paths to methods in the above controller.

JM-6 Page 17
Load Balancer
28 April 2025 10:07

Server side :
Server side load balance requires all the services to have load balancing which may increase the network
traffic.
It requires separate hardware and installation which is costly
Server-side load balancing is involved in monolithic applications.
Load Balancer has public IP and DNS
It mainly uses Round Robin or sticky session algorithms
Problems with Microservice architecture:
1. Server-side load balancing is am manual effort, and we need to add/remove instances manually to
the load balancer to work.
2. Loosing todays on demand scalability to auto-discover and configure
3. Fail-over policy to provide the client a seamless experience
4. Need a separate server to host the load balancer instance which has the impact on cost and
maintenance.
Client side:
They reside in the application as inbuilt component and bundled along with the application, so we don't
have to deploy them in separate servers.
On-demand scaling can be done with auto-discover and configure with the help of service discovery
pattern
It one microservice wants to communicate with another, it generally looks up the service registry using
discovery client and eureka server returns all the instances of that target microservice to the caller
service. Then it is the responsibility of the caller service to choose which instance to send request.
Client-side load balancing automatically handles the complexities around the situation and delegates to
proper instance in load balanced fashion.
We can specify the load balancing algorithm to use
There are two load balancer sites
1. Ribbon - Client side load balancer :
Ribbon is a client-side load balancer that gives a lot of control over the behavior of HTTP and TCP
clients.
Ribbon primarily provides client-side load balancing algorithms.
Spring cloud implements Ribbon as a wrapper over RestTemplate.
Ribbon could also be used independently by providing servers list
Default load balancing algorithm is Round-robin
Features of Ribbon :
- Service Discovery Integration :
Ribbon load balancers provide service discovery in dynamic environments like a cloud. Integration
with Eureka and Netflix service discovery component is included in the ribbon library
- Fault Tolerance :
Ribbon API can dynamically determine whether the servers are up and running in a live
environment and can detect those servers that are down
- Configurable load-balancing rules :
Ribbon supports RoundRobinRule, AvailabilityFilteringRule (circuit tripped),
WeightedResponseTimeRule and out of the box it supports defining custom rules.

JM-6 Page 18
Microservices Pattern
21 May 2025 10:34

Microservices:
1. Decomposition Patterns
These patterns help break down a monolith into microservices.
🔹 a) Decompose by Business Capability
Split services by domains like User Service, Order Service, Inventory Service.
Reflects the bounded context of Domain-Driven Design (DDD).
🔹 b) Decompose by Subdomain
Use strategic DDD to divide large domains into core, supporting, and generic subdomains.
🛠 2. Integra on Pa erns
Used for communication between services.
🔹 a) API Gateway Pattern
A single entry point for all client requests.
Handles routing, authentication, rate limiting.
Client → API Gateway → Microservices
Popular tools: Spring Cloud Gateway, Zuul, Kong
🔹 b) Aggregator Pattern
Combines multiple service calls into one response.
Useful when frontend needs data from several microservices.
🔄 3. Communication Patterns
How services talk to each other.
🔹 a) Synchronous (REST, gRPC)
Simple to implement.
Can cause tight coupling and latency.

JM-6 Page 19
Can cause tight coupling and latency.
🔹 b) Asynchronous (Event-Driven)
Uses message brokers like Kafka, RabbitMQ, etc.
Improves decoupling and resilience.
💣 4. Resilience Patterns
These patterns protect your system from failures.
🔹 a) Circuit Breaker Pattern
Prevents calling a failed service repeatedly.
Libraries: Resilience4j, Hystrix (deprecated)
🔹 b) Retry Pattern
Automatically retry a failed request after a delay.
🔹 c) Bulkhead Pattern
Isolate failures so one service doesn’t take down others.
🧠 5. Data Management Patterns
Each microservice owns its data — so coordination is tricky.
🔹 a) Database per Service
Every service has its own DB schema.
Avoids tight coupling, but needs careful coordination.
🔹 b) Saga Pattern
Manages distributed transactions.
Orchestration (central controller) or Choreography (event-driven).
🔹 c) CQRS (Command Query Responsibility Segregation)
Split read and write models for performance and scalability.
6. Observability Pa erns
Help in monitoring, logging, and tracing.
🔹 a) Log Aggregation
Collect logs from all services (e.g., ELK stack, Grafana + Loki).
🔹 b) Distributed Tracing
Track a request across multiple services.
Tools: Zipkin, Jaeger, OpenTelemetry
🔹 c) Health Check Pattern
Every service exposes a /health endpoint.
Used for monitoring and auto-scaling.
🔐 7. Security Patterns
🔹 a) Token-Based Security
Use JWT tokens for authentication.
Validate tokens at API Gateway or per service.
🔹 b) Service-to-Service Authentication
Use mTLS or tokens (e.g., OAuth2) for internal service calls.
📦 8. Deployment Patterns
🔹 a) Service Registry and Discovery
Services register themselves and discover others dynamically.
Tool: Eureka, Consul, Zookeeper
🔹 b) Sidecar Pattern
Add non-functional capabilities (e.g., logging, proxy) via a separate container in the same pod.
Used with Istio, Envoy in Kubernetes.

JM-6 Page 20
Spring Security
30 April 2025 09:55

Token Signing algorithms are HMAC, RSA, ECDSA, etc


JWT (Json Web Token) :
Json Web Token (JWT) is an open standard (RFC 7519) that defines a compact and self-contained way
for securely transmitting information between parties as a JSON object. This information can be verified
and trusted because it is digitally signed.
JWTs can be signed using a secret (with the HMAC algorithm) or a public/private key pair using RSA
A JWT consists of three parts:
1. Header : Specifies the signing algorithm
2. Payload : Contains the claims
3. Signature : Verify the sender of the JWT

JWT Implementation (HMAC)


Both signing and verification use the same secret key
If an attacker gains access to the secret key, they can create and validate tokens.
An attacker with access to the key can forge the token.
Token forging is the process of programmatically creating a token that contains information (like user ID,
roles, expiration, etc.), and it’s usually signed to prevent tampering.
To implement the spring security for token forging we use RSA algorithm.
JWT Asymmetric Encryption With RSA
RSA (Rivest-Shamir-Adleman) is a widely used public-key cryptographic algorithm. RSA is used for secure
data transmission and relies on the mathematical properties of large prime numbers
Signing and Verification :
- Private key : Used for signing the JWT, only the issuer of the token has token has access to the
private key
- Public key : Used for verifying the signature of the JWT. The public key is shared and can be used
by an recipient to verify that the JWT was indeed signed by the issuer's private key.
Encryption and Decryption :
- Public key : Used for encrypting data. Anyone can use the public key to encrypt data, but only the
holder of the corresponding private key can decrypt it.
- Private key : Used for decrypting data that was encrypted with public key.

JM-7 Page 1
JM-7 Page 2
🧾 What is the JWT Header?
It contains metadata — information about the token itself — specifically:
The type of token (which is usually JWT)
The signing algorithm used to secure the token
It’s a small JSON object that's then Base64Url-encoded.
⚙ How the Header Works
The header JSON is created during token generation (like you do in .signWith(...)).
It’s Base64Url-encoded (not regular Base64) — this means:
No padding characters (=)
URL-safe characters (- and _ instead of + and /)
<header>.<payload>.<signature>
🔐 Why the Header Matters
It tells whoever is parsing/validating the token how to interpret and verify it.
When your backend receives a token, it looks at the header to know:
What algorithm to use for verifying the signature
Whether it’s a valid JWT structure
If someone tampers with the token, the signature won’t match anymore — making the token invalid

JM-7 Page 3
📦 What Is the Payload in JWT?
The payload is the middle part of the JWT token and contains the claims, which are pieces of
information (key-value pairs) about the user or token itself.
In a JWT like this:
xxxxx.**yyyyy**.zzzzz
The yyyyy part is the payload, Base64Url-encoded.

JM-7 Page 4
🔐 What Is the Signature in JWT?
The signature is the third part of a JWT ([Link]), and its main purpose is to ensure the
integrity of the token. It makes sure that:
The token wasn't modified after being created.
The token was created by a trusted source (e.g., your server).
🧬 How the Signature Is Created
Formula (simplified):
Signature = HMACSHA256(
Base64UrlEncode(Header) + "." + Base64UrlEncode(Payload),
SecretKey
)
🛠 In Your Code:
.signWith(getSigningKey(), SignatureAlgorithm.HS256)
You pass in the signing key and choose an algorithm (e.g., HS256).
The JWT library handles encoding the header and payload, then signing it.

JM-7 Page 5
The JWT library handles encoding the header and payload, then signing it.
⚙ Types of JWT Signature Algorithms
There are two main families of algorithms:
🔹 1. HMAC (Symmetric)
Same key is used to sign and verify.
Fast and simple.
Suitable when the same service handles both token creation and validation.

🔹 2. RSA & ECDSA (Asymmetric)


Private key signs, public key verifies.
More secure; used when different systems/services handle signing and verification.

🧩 What is Base64Url?
Base64Url is a variant of the Base64 encoding scheme, which is designed to safely encode data that can
be used in URLs or filenames without causing issues.
While Base64 encoding is widely used to represent binary data as text (like in JWTs), it has some
characters (+, /, =) that are not URL-safe. Base64Url replaces these problematic characters to make the
encoding safe for URLs and HTTP headers.
🎯 Why Use Base64Url?
URL Safe: It avoids characters that could interfere with URL encoding (+, /, =, etc.).
JWT Compatibility: JWTs are designed to be URL-safe since they are often passed in HTTP headers or as
query parameters in URLs.

JM-7 Page 6
🔧 [Link] — Configuration
🔹 @Configuration & @EnableWebSecurity
Tells Spring this is a configuration class for web security.
🔹 securityFilterChain(HttpSecurity httpSecurity)
Defines how Spring Security should protect your endpoints.
csrf(AbstractHttpConfigurer::disable)
Disables CSRF since JWT makes CSRF less relevant (stateless).
authorizeHttpRequests(...)
Allows public access to:
/library/login
/library/users (for registration)
All other endpoints require authentication.
sessionManagement(...)
[Link]: No HTTP session is created. Every request must carry a valid token.
addFilterBefore(jwtAuthFilter(), [Link])
Adds your custom JWT filter before Spring’s default username/password authentication filter.
exceptionHandling(...)
If an unauthenticated user accesses a protected endpoint, it returns 401 Unauthorized.
🔹 passwordEncoder()
Uses BCrypt to hash passwords securely.
🔹 jwtAuthFilter()
Registers the custom JWT filter that you'll define in the next class.
🧱 [Link] — JWT Token Validation
🔹 Extends OncePerRequestFilter
Ensures the filter is applied once per request.

JM-7 Page 7
When a request is sent:
Spring Security Intercepts the Request First – This includes your SecurityFilterChain configuration.
JwtAuthenticationFilter Gets Triggered – It's checked before the default Spring authentication filter.
Filter Checks Path & Authorization Header:
If it's a public path (like /login or /users), it skips authentication.
If it's a protected path, it looks for the JWT token in the Authorization header.
JWT Token is Extracted & Validated:
The token is sent to JWTService, which checks if it's valid and not expired.
If valid, it sets the authentication in SecurityContextHolder.
Access is Granted or Denied Based on whether the user is authenticated.
So yes — the security filter acts like a gatekeeper, validating JWT tokens before the request reaches any
controller or endpoint logic.

JM-7 Page 8
API Gateway
13 May 2025 10:09

Features of Spring Cloud Gateway:


- Routing
- Filtering
- Load Balancing
- Circuit breaking

JM-7 Page 9
Spring Security terms
13 May 2025 20:55

🔐 Spring Security Core Concepts


1. Authentication
Verifying the identity of a user (e.g., username and password).
In Spring Security, this is typically handled by an AuthenticationManager.
2. Authorization
Determining whether an authenticated user has permission to access a specific resource.
Implemented through roles or authorities.
3. Principal
Represents the currently logged-in user.
Often accessed using [Link]().
4. AuthenticationManager
Core interface used to process authentication requests.
Often used in custom login logic.
5. SecurityContext
Holds the security information (e.g., the authenticated user's details).
Stored in SecurityContextHolder.
6. SecurityContextHolder
A utility class that holds the SecurityContext.
Usually thread-local, meaning each thread has its own security context.
🔑 User Details and Roles
7. UserDetails
An interface representing a user's core information (username, password, authorities).
Custom implementations are used to define your user model.
8. UserDetailsService
Interface used to load user-specific data.
Usually implements the method loadUserByUsername().
9. GrantedAuthority
Represents an authority (or a role) granted to the user.
Used for authorization.
10. Role vs Authority
ROLE_USER is a role; READ_PRIVILEGES is an authority.
Roles are typically prefixed with ROLE_.
🛡 Security Filters & Configura on
11. Security Filter Chain
A chain of filters that process security-related logic for each request.
Custom filters can be added to handle things like JWT authentication.
12. HttpSecurity
The main entry point for configuring web security.
You configure which endpoints are secured, which are open, and more.
13. WebSecurityConfigurerAdapter (Deprecated in Spring Security 5.7+)
Used to customize Spring Security configurations. Replaced by beans of type SecurityFilterChain.
14. CSRF (Cross-Site Request Forgery)
A security measure that prevents malicious sites from making unwanted requests on behalf of the user.
Can be enabled/disabled in configuration.
15. CORS (Cross-Origin Resource Sharing)
Allows or restricts resources from being requested from another domain.
🔐 JWT & Stateless Authentication
16. JWT (JSON Web Token)
A compact token format used for secure transmission of information.
Used for stateless authentication in REST APIs.
17. Bearer Token
A type of token (like JWT) that is included in the HTTP Authorization header.
18. AuthenticationEntryPoint

JM-7 Page 10
18. AuthenticationEntryPoint
Used to handle unauthorized access (e.g., returning a 401 error).
19. OncePerRequestFilter
Ensures your custom filter (e.g., JWT filter) only runs once per request.
🧰 Session and Stateless Management
20. Stateless Authentication
No session is stored server-side. Each request must include authentication credentials (e.g., JWT).
21. Session Management
Controls how sessions are created and managed (e.g., STATELESS, ALWAYS, etc.).
🧪 Testing with Spring Security
22. @WithMockUser
Annotation used in unit tests to mock an authenticated user.
23. SecurityMockMvcRequestPostProcessors
Utilities for testing secure endpoints with MockMvc.
JWT Token Creation in Spring Boot
✅ Step 1: User Sends Login Request -> The user submits their username and password to the backend (e.g., via a login form or
API call).
🔍 Step 2: Backend Authenticates User -> Spring Security checks the submitted credentials against the database (or another
user store).
If credentials are valid, the user is considered authenticated.
🛠 Step 3: Generate the JWT Token
After successful login:
The server creates a JWT token that includes user info (usually the username) and optional data like user roles or permissions.
It adds a timestamp for when the token was created.
It adds an expiration time (e.g., valid for 1 hour).
The token is then digitally signed using a secret key so it can't be tampered with.
🎁 Step 4: Send the Token Back to the Client
The server sends the JWT token back to the client (usually in the response body or header).
The client stores it — typically in local storage or session storage (for browsers) or securely in mobile apps.
📲 Step 5: Client Uses Token in Future Requests
For all future requests, the client includes the JWT in the Authorization header like this:
Authorization: Bearer <token>
This allows the server to know who the user is without asking for a password again.
🔐 Step 6: Backend Validates the Token
For every request with a JWT:
The backend extracts the token from the request.
It checks if the token is valid:
Is it properly signed?
Has it expired?
Is the user still allowed access?
If all checks pass, the user is allowed to access the requested resource.
🚫 Step 7: Token Expiration / Renewal (Optional)
JWTs often expire after a certain time (e.g., 1 hour).
Once expired, the user needs to:
Log in again, or
Use a refresh token (optional strategy) to get a new access token without logging in.

JM-7 Page 11
Algorithms
13 May 2025 21:40

Common Types of Password Encoders


1. BCryptPasswordEncoder
PasswordEncoder encoder = new BCryptPasswordEncoder();
✅ Most recommended and secure
Uses the BCrypt hashing algorithm
Adds a salt automatically (helps prevent rainbow table attacks)
Computationally expensive → slows down brute-force attacks
Adjustable strength (new BCryptPasswordEncoder(strength))
Default in Spring Security 5+
2. NoOpPasswordEncoder
PasswordEncoder encoder = [Link]();
⚠ Not secure — use only for tes ng or demos.
Stores and compares passwords in plain text
Spring forces you to explicitly declare it to prevent accidents
3. Pbkdf2PasswordEncoder
PasswordEncoder encoder = new Pbkdf2PasswordEncoder();
✅ Secure and configurable
Based on PBKDF2 with HMAC-SHA1 or other algorithms
Slow hashing with salt, good for password protection
You can customize hash width, iteration count, etc.
4. SCryptPasswordEncoder
PasswordEncoder encoder = new SCryptPasswordEncoder();
✅ Very strong, memory-hard algorithm
Even more secure than BCrypt in some cases
Resistant to hardware brute-force (like ASICs or GPUs)
More CPU + memory intensive
5. Argon2PasswordEncoder
PasswordEncoder encoder = new Argon2PasswordEncoder();
✅ 🏆 Winner of the Password Hashing Competition
Highly secure, modern, and customizable
Built to defend against both CPU and GPU brute-forcing
Good choice if your environment supports it
6. DelegatingPasswordEncoder
PasswordEncoder encoder = [Link]();

JM-7 Page 12
PasswordEncoder encoder = [Link]();
✅ Smart and flexible
Supports multiple encoders at once
Stores the encoding algorithm in the password string itself
Example stored password: {bcrypt}$2a$10$EJ4...
Super useful for migrating from one hashing algorithm to another without breaking existing passwords.
What Are Signing Algorithms?
A signing algorithm is a cryptographic method used to sign a JWT (JSON Web Token). It ensures that the
data in the token has not been tampered with and can be trusted. This is achieved by creating a digital
signature using the payload (the data part of the token) and a secret key (or private key in case of
asymmetric algorithms).
Purpose of Signing Algorithms:
Data Integrity: Ensures that the payload (data) inside the token hasn't been modified.
Authentication: Confirms that the token was issued by a trusted source (e.g., your application/server).
Types of Signing Algorithms
There are two main families of signing algorithms:
1. Symmetric Signing Algorithms (Shared Secret)
In these algorithms, the same key is used both to sign and verify the token.
Fast, simple, but less secure if the secret key is not properly managed.
Example: HMAC (Hash-based Message Authentication Code).
2. Asymmetric Signing Algorithms (Public/Private Key Pair)
In these algorithms, a private key is used to sign the token, and the corresponding public key is used to
verify it.
More secure because the private key is never exposed and can be safely kept on the server while
anyone can use the public key to verify the token.
Example: RSA, ECDSA.
Symmetric Signing Algorithms
1. HMAC (Hash-based Message Authentication Code)
HMAC is the most commonly used symmetric algorithm in JWTs.
How it works: A hash function (like SHA-256) is applied to the message (JWT header + payload), and the
result is then signed with a shared secret key.
Common Variants:
HS256: HMAC with SHA-256 (most commonly used)
HS384: HMAC with SHA-384
HS512: HMAC with SHA-512
Pros: Fast, simple to implement, and suitable for simple systems where you control both the signing and
verification.
Cons: If the secret key is exposed or leaked, anyone can generate valid tokens.
Asymmetric Signing Algorithms
2. RSA (Rivest-Shamir-Adleman)
RSA is an asymmetric cryptographic algorithm, meaning it uses two keys:
Private key for signing.
Public key for verification.
How it works: The private key signs the payload, and anyone with the public key can verify that the
signature is correct without knowing the private key.
Common Variants:
RS256: RSA with SHA-256 (most common for JWTs)
RS384: RSA with SHA-384
RS512: RSA with SHA-512
Pros: Strong security since the private key is not shared.
Cons: Slower than symmetric algorithms because of the computational cost of asymmetric encryption.
3. ECDSA (Elliptic Curve Digital Signature Algorithm)
ECDSA is a variant of RSA but based on elliptic curve cryptography.
It uses smaller key sizes than RSA for the same level of security, which makes it more efficient.

JM-7 Page 13
It uses smaller key sizes than RSA for the same level of security, which makes it more efficient.
How it works: Like RSA, ECDSA uses a private key to sign and a public key to verify the signature.
Common Variants:
ES256: ECDSA with SHA-256
ES384: ECDSA with SHA-384
ES512: ECDSA with SHA-512
Pros: More efficient than RSA, providing the same level of security with smaller key sizes.
Cons: Slightly more complex to implement compared to RSA.
How These Signing Algorithms Work in Practice:
1. Symmetric Signing (e.g., HMAC):
The server generates a JWT using a shared secret key.
The client sends the JWT back to the server in each request.
The server recalculates the signature with the same shared key and compares it to the signature in the
token.
If the signature matches, the token is valid; otherwise, it’s tampered with.
2. Asymmetric Signing (e.g., RSA, ECDSA):
The server uses a private key to sign the JWT and sends it to the client.
The client sends the JWT back in each request.
The server uses a public key to verify the signature, ensuring it was signed with the private key.
If the signature matches, the token is valid; otherwise, it’s invalid or tampered with.

JM-7 Page 14
Multi-Threading
12 May 2025 09:40

By default programming languages are sequential in nature. Code execution happens line by line in
usual scenario.

Problem with the sequential execution: In a single threaded program these instructions will be executed
one by one. The time consuming sections of the code can freeze the entire application.
Solution: Figure out the time consuming tasks and decide if they can be run separately. If yes, run such
tasks in separate threads.
Multi-Threading is the ability to CPU to perform different tasks concurrently.
Pros and Cons of Multi-threading:
Pros
- We can build responsive applications
- Better resource utilization
- Better performance applications
- CPU is not idle for more time.
Cons
- Synchronization is tricky
- Difficult to design and test MT apps
- Thread context switch is expensive
Differences between Concurrency v/s Parallelism :

JM-8 Page 1
Concurrency is fake parallelism, it deals with independent process and parallelism deals with dependent
process since it divides the process into small tasks.

Process and Threads :


Process: Process is an instance of program execution. When you enter an application, it's a process. The
OS assigns it's own Stack and Heap memory area.
Thead: Thread is a lightweight process. It is a unit of execution within a given program. A single process
may contain multiple threads. Each thread in the process shares the memory and resources.
Time Slicing Algorithm:

JM-8 Page 2
Time Slicing Algorithm:
It is timeframe for which process is allotted to run in preemptive multitasking CPU. The scheduler runs
each process every single time-slice. The period of each time slice can be very significant and crucial to
balance CPUs performance and responsiveness.
If time slice is quite short, scheduler will take more processing time. In contrast, if the time slice is too
long, scheduler will again take more processing time.
Advantages :
Fair allocation of CPU resources.
It deals all process with equal priority.
Easily implementable on the system.
Context switching method used to save states of preempted processes
gives best performance in terms of average processing time.
Disadvantages :
If the slicing time is short, processor output will be delayed.
It spends time on context switching.
Performance depends heavily on time quantum.
Priorities can’t be fixed for processes.
No priority to more important tasks.
Finding an appropriate time quantum is quite difficult.

Thread Lifecycle:

Each program by default has main thread created by JVM which is also called as parent thread. All
program has only one thread and works sequentially until it doesn't contain multithread invocation
called by the programmers.
Thread creation :
A thread can programmatically be created by:
- Implementing the [Link] interface.
- Extending the [Link] class.
- Using Lambda Expressions
- Using ExecutorService
1. Thread Class
The Thread class provides constructors and methods for creating and operating on threads. The thread
extends the Object and implements the Runnable interface.
Method: public void start()
It starts a newly created thread. Thread moves from new state to runnable state when it gets a chance,
executes the target run() method
Use Case: Suitable for simple applications for creating a thread that performs a specific task.

JM-8 Page 3
✅ Pros:
Simple and straightforward.
Good for quick experiments or small tasks.
❌ Cons:
Not flexible — you're extending a class, so you can't extend another one.
Harder to manage multiple threads or reuse.
2. Runnable Interface
Any class with instances that are intended to be executed by a thread should implement the Runnable
interface. The Runnable interface has only one method, which is called run().
Use Case: It is suitable for cases where you want to separate the task from the thread management.
Also, Runnable is a interface so allows us to perform multiple inheritance.
✅ Pros:
More flexible than extending Thread (can still extend another class).
Encourages separation of task from the thread itself.
❌ Cons:
Slightly more verbose than Thread or lambda.
Manual thread creation and management required.
3. Using Lambda Expressions
Lambda Expressions are very useful for creating the Threads in the cases when the operations to be
performed are limited.
Use Case: Used for Threads performing simple tasks.
✅ Pros:
Very concise.
Useful for short tasks or when passing behavior as parameters.
❌ Cons:
Not suitable for long or complex logic (can hurt readability).
Still requires manual thread management.
4. Using ExecutorService (for Managing Thread Pools)
The ExecutorService framework provides a higher-level way to manage threads. It allows you to create a
pool of threads and manage their execution.
Use Case: Used for concurrent execution of multiple threads.
✅ Pros:
• Best for scalability and production.
• Thread pooling = better resource management.
• Can return Future results.
• Supports scheduling, fixed-size thread pools, etc.
❌ Cons:
• Slightly more setup code.
• Need to remember to shut down the executor.

JM-8 Page 4
The execution happens sequentially,
Once the thread is started then it is available to be scheduled by the thread scheduler and once the
thread scheduler finds an available spot for a particular thread to be run in CPU then it is assigned to
CPU for running.
Join() Method :
Main Thread has highest priority.
Normally first main is executed then the other threads are executed. All threads are executed
independently.
If we want to execute the main thread after the execution child thread then we need to use [Link]().
Join() methods throws the interruptException, to handle this exception we need to use the try-catch
block or throw in method itself.
[Link] class provides the join() method which allows one thread to wait until another thread
completes its execution. If t is a Thread object whose thread is currently executing, then [Link]() will
make sure that t is terminated before the next instruction is executed by the program.
If there are multiple threads calling the join() methods that means overloading on join allows the
programmer to specify a waiting period.
However, as with sleep, join is dependent on the OS for timing, so you should not assume that join will
wait exactly as long as you specify. There are three overloaded join functions.
1. join(): It will put the current thread on wait until the thread on which it is called is dead. If a thread is
interrupted then it will throw InterruptedException.
Syntax: public final void join()
2. join(long millis): It will put the current thread on wait until the thread on which it is called is dead or
wait for the specified time (milliseconds).
Syntax: public final synchronized void join(long millis)
3. join(long millis, int nanos): It will put the current thread on wait until the thread on which it is called is
dead or wait for the specified time (milliseconds + nanos).
Syntax: public final synchronized void join(long millis, int nanos)
On basis of surface of execution threads can be of two types:
1. Daemon Threads
2. User Threads
When a Java Program starts the main thread(main() method thread) starts running immediately. We can
start child threads from the main thread. The main thread is the last thread to finish execution in normal
circumstances, because it has to perform various shutdown operations.
Daemon Threads: Daemon threads are intended to be helper threads which can run in background and
are of low priority. Example GC thread
Daemon threads are terminated by the JVM when all other user threads are terminated (done with their
execution)
So, under normal circumstances, user threads are allowed to terminate once they are done with their
execution. However, the daemon threads are shutdown by JVM once all the other threads are done

JM-8 Page 5
execution. However, the daemon threads are shutdown by JVM once all the other threads are done
executing.
By default, any thread is not a daemon thread.
Whether the daemon thread has completed its execution or not but it gets terminated as soon as the
child and main threads have completed their execution.
[Link](milliseconds) -> throws Interrupted exception
Thread Priority :
Thread scheduler is used to schedule the thread to CPU for execution.
Each thread has certain priority and under normal circumstances the thread with higher priority is
executed on CPU.
Priority Value from 1 to 10 can be assigned to any thread. 1 -> MIN_PRIORITY and 10 -> MAX_PRIORITY.
By default, the priority of thread is 5, represented as NORM_PRIORITY
Threads with same priority are executed in FIFO manner. The thread scheduler store the threads in a
queue.
Regardless of the priority main thread has the highest priority and given first preference for execution
since it is the starting point for the JVM.
Thread Synchronization:
Change in the value of counter can be using non-atomic operations
This condition is called as race-condition.
To achieve mutual exclusion, where all threads share their resources, we need to use synchronized
keyword which makes the resource to be accessed by one thread at a time.
The code in synchronized method are called as critical section code which should be handled by multi-
threaded environment
You can’t mark a field synchronized, but you can:
Synchronize methods that access the field
Use synchronized blocks
Use locks (ReentrantLock)
Use atomic variables for primitive types
Working of Synchronization:
In Java, every object has an intrinsic lock (also called a monitor lock or just monitor). When a thread
wants to execute a synchronized method or block, it must acquire the monitor lock of the associated
object.
Only one thread can hold the monitor lock for an object at a time. Others are blocked until it’s released.
JVM uses monitorenter and monitorexit bytecode instructions.
These manage the monitor lock when entering and exiting synchronized code blocks.
Problems with synchronization:
- Blocking small code, reduces concurrency and performance bottlenecks
- When used at method level we lose the fine grained control of complexity
- If a super class method is synchronized then the child class method should also be synchronized.
Synchronized keyword at block level is used for decoupling of the threads.
Wait and Notify:
These methods are interruptible methods so they might throw exception to handle them we use
exception handler.
wait(): The wait() method makes a thread voluntarily give up its lock on an object, allowing another
thread to execute code within a synchronized block. The thread that calls wait() will enter a waiting state
until another thread calls notify() or notifyAll() on the same object, allowing it to resume execution.
notify(): The notify() method wakes up one of the waiting threads on the same object. If multiple
threads wait, it is not specified which one will be awakened. The awakened thread will then compete for
the lock on the object. If notify is used in the synchronized block then after the completely the execution
of that block only the other threads will be executed.
notifyAll(): The notifyAll() method wakes up all waiting threads on the same object. This can be useful
when multiple threads are waiting, and you want them to be notified simultaneously.
Why wait(), notify() and notifyAll() are in Object Class:
- Object-level Synchronization

JM-8 Page 6
- Object-level Synchronization
- Wait and Notify Semantics
- Multiple Threads per Object
- Avoids Coupling to Thread
- Encourages better design
Wait() is used in Inter Thread Communication and synchronization

What if a thread goes a long time without invoking a method that throws InterruptedException? Then it
must periodically invoke [Link], which returns true if an interrupt has been received. For
example:

for (int i = 0; i < [Link]; i++) {


heavyCrunch(inputs[i]);
if ([Link]()) {
// We've been interrupted: no more crunching.
return;
}
}
The Interrupt Status Flag
The interrupt mechanism is implemented using an internal flag known as the interrupt status. Invoking
[Link] sets this flag. When a thread checks for an interrupt by invoking the static method
[Link], interrupt status is cleared. The non-static isInterrupted method, which is used by
one thread to query the interrupt status of another, does not change the interrupt status flag.
By convention, any method that exits by throwing an InterruptedException clears interrupt status when
it does so. However, it's always possible that interrupt status will immediately be set again, by another
thread invoking interrupt.
Producer-Consumer Problem :

JM-8 Page 7
Volatile
05 May 2025 09:51

To overcome visibility problem - Volatile


The volatile keyword in Java is used to mark a Java variable as “being stored in the main memory.” Every
thread that accesses a volatile variable will read it from the main memory and not from the CPU cache.
This way, all threads see the same value for the volatile variable.
The volatile keyword can be used with variables of any kind, including primitive types and object
references. When used with objects, all threads will see the most up-to-date values for all fields in the
object.
It is used to solve the visibility problem
To solve the synchronization problem
1. synchronized keyword :
The synchronized keyword can be applied to methods or blocks within methods. When a method
or block is declared as synchronized, a lock is obtained on the specified object, and other threads
are blocked from accessing the synchronized code until the lock is released.
Syntax
Synchronized Method
public synchronized void Method() {
// method code
}
Synchronized Block
public void method() {
synchronized (object) {
// synchronized code
}
}
object: The object on which to synchronize. This is typically the current instance (this) or a specific
object.
2. AtomicInteger :
A [Link] class provides operations on underlying int value that
can be read and written atomically, and also contains advanced atomic operations. AtomicInteger
supports atomic operations on underlying int variable. It have get and set methods that work like
reads and writes on volatile variables. That is, a set has a happens-before relationship with any
subsequent get on the same variable. The atomic compareAndSet method also has these memory
consistency features.

JM-8 Page 8
Volatile Keyword vs. Other Types of Keywords in Java
Volatile vs. Atomic
Marking a variable as volatile means declaring that multiple threads will be accessing this variable. This
makes the value of the variable visible to all threads. On the other hand, atomicity refers to an operation
being indivisible. The atomic keyword hides a process from other threads until it’s been completed,
making it appear as if it’s been accomplished in one step and preventing other threads from interfering
in the process.

JM-8 Page 9
in the process.

Volatile vs. Synchronized


Synchronization is an approach that allows only one thread at a time to access a specific section of code.
This means that multiple threads cannot alter the block of code, or method, simultaneously. In this way,
the synchronized keyword still supports visibility, but it also upholds atomicity by preventing other
threads from interfering with a thread executing a task. This stands in contrast to the volatile keyword,
which is only concerned with visibility.

Volatile vs. Transient


Both the volatile and transient keywords involve values, but they focus on different processes. The
volatile keyword alerts users that a value can be changed by multiple threads simultaneously.
Meanwhile, the transient keyword lets a program know to skip over a variable during serialization — the
process of transforming an object’s state into a byte stream. The program then knows not to save the
value of the variable.

Volatile vs. Static


The static keyword ensures that there is only ever one copy of a variable, regardless of how many
objects of the class are generated. On the other hand, the volatile keyword enables a variable to be
accessed by multiple threads at the same time, and each object created gets its own copy of the
variable. This means that the static keyword operates on the class level while the volatile keyword
operates on the level of instances or objects.

Limitations of the Volatile Keyword


- Lack of Atomicity
The volatile keyword’s inability to guarantee atomicity can become a larger issue during compound
actions. While the volatile keyword can make sure individual actions are visible to all threads, it doesn’t
guarantee atomicity for the entire compound operation. This can lead two threads executing the same
compound action on the same variable at the same time to produce varying results.
- Potential for Race Conditions
The absence of atomicity also means other threads can interfere in a process if a variable is volatile,
creating a race condition. A race condition is a situation where two threads simultaneously access the
same data, leading to an unpredictable result that depends on the order in which the threads perform
their actions.
- Complications With Arrays
Arrays present another situation where the volatile keyword is ineffective. Marking an array as volatile
only applies to their references and doesn’t carry over to their fields. As a result, an array’s value in one
thread may still not be visible in other threads.
- Lower Computing Performance
When dealing with the volatile keyword, a computer must read volatile variables from a computer’s
main memory instead of its CPU cache. This is a more demanding process that can slow down the
computer and decrease its overall performance.
Non-access modifiers:
Non-access modifiers in Java provide information about the characteristics of a class, method, or
variable to the JVM. There are seven non-access modifiers, including:
final
static
abstract
synchronized
volatile
transient
native

JM-8 Page 10
Thread Local
05 May 2025 10:10

Thread-Local Use cases :


- Per thread instances for memory efficiency and thread-safety
Create instances for threads specific rather than declaring it globally

- Web server Requests

JM-8 Page 11
- Web server Requests
Per Thread Context (Thread-safety + perf) - ThreadLocal

ConcurrentHashMap can be used for this problem

JM-8 Page 12
After all the operations we need to clean the resources

JM-8 Page 13
JM-8 Page 14
Parallelism
05 May 2025 10:21

Parallelism is about doing lot of things at once


Parallelism is related to an application where tasks are divided into smaller sub-tasks that are processed
seemingly simultaneously or parallel. It is used to increase the throughput and computational speed of
the system by using multiple processors. It enables single sequential CPUs to do lot of things
“seemingly” simultaneously.

Parallelism leads to overlapping of central processing units and input-output tasks in one process with
the central processing unit and input-output tasks of another process. Whereas in concurrency the
speed is increased by overlapping the input-output activities of one process with CPU process of another
process.

JM-8 Page 15
Concurrency :
Concurrency is about dealing with lot of things at once
Concurrency is applied when we have shared resource to be accessed or updated
Multiple tasks need to coordinate
Concurrency relates to an application that is processing more than one task at the same time.
Concurrency is an approach that is used for decreasing the response time of the system by using the
single processing unit. Concurrency creates the illusion of parallelism, however actually the chunks of a
task aren’t parallelly processed, but inside the application, there are more than one task is being
processed at a time. It doesn’t fully end one task before it begins ensuing.
Concurrency is achieved through the interleaving operation of processes on the central processing
unit(CPU) or in other words by the context switching. that’s rationale it’s like parallel processing. It
increases the amount of work finished at a time.

JM-8 Page 16
Interleaving of thread

JM-8 Page 17
JM-8 Page 18
Java Memory model
05 May 2025 10:43

Out of order execution:


Performance driven changes done by Compiler, JVM or CPU.
Field Visibility :
In presence of multiple threads i.e, Concurrency

Java Memory model :


JMM is a specification which guarantees visibility of fields (happens before) amidst reordering of
instructions.
It makes sure that all the rules are followed by all the JVM and result returns same irrespective of JDK
Happens Before
To solve this problem, we need to enforce a "Happens-Before" relationship between the write
to data and the write to dataLoaded. We can do this using synchronized or volatile keyword.

JM-8 Page 19
This concept is applicable to
Synchronized
Locks
Concurrent collections
Thread operations (Join, start)
Final fields (special behavior)

JM-8 Page 20
Java ExecutorService
05 May 2025 11:01

Java executor framework ([Link]), released with the JDK 5, is used to run the
Runnable objects without creating new threads every time and mostly re-using the already created
threads. We all know that there are two ways to create a thread in Java. If you want to read more about
their comparison, read how to create threads in Java.
The [Link] provide factory methods that are used to create ThreadPools of
worker threads. Thread pools overcome this issue by keeping the threads alive and reusing them. Any
excess tasks flowing in that the threads in the pool can’t handle are held in a Queue. Once any of the
threads get free, they pick up the next task from this queue. This task queue is essentially unbounded
for the out-of-the-box executors provided by the JDK.
Some types of Java Executors are listed below:
Executor 1: SingleThreadExecutor
A thread pool of a single thread can be obtained by calling the static newSingleThreadExecutor() method
of the Executors class. It is used to execute tasks sequentially.
Syntax:
ExecutorService executor = [Link]();
Executor 2: FixedThreadPool(n)
As the name indicates, it is a thread pool of a fixed number of threads. The tasks submitted to the
executor are executed by the n threads, and if there are more task, they are stored on a
LinkedBlockingQueue. It uses Blocking Queue.
Syntax:
ExecutorService fixedPool = [Link](2);
Executor 3: CachedThreadPool
Creates a thread pool that creates new threads as needed, but will reuse previously constructed threads
when they are available. Calls to execute will reuse previously constructed threads if available. If no
existing thread is available, a new thread will be created and added to the pool. It uses a
SynchronousQueue queue.
ExecutorService executorService = [Link]();
Task Queue can contain one task at max. If all threads are busy a new thread is created and task is
assigned to that thread. If a thread is idle for more than 60 seconds, it's killed.
Executor 4: ScheduledExecutor
Scheduled executors are based on the interface ScheduledExecutorService which extends the
ExecutorService interface. This executor is used when we have a task that needs to be run at regular
intervals or if we wish to delay a certain task.
ScheduledExecutorService scheduledExecService = [Link](1);
The tasks can be scheduled using either of the two methods:
scheduleAtFixedRate: This executes tasks at fixed intervals, regardless of task completion time. If a task’s
execution exceeds the interval, tasks will queue.
scheduleWithFixedDelay: This will start the delay countdown only after the current task completes.
Syntax:
[Link]
(Runnable command, long initialDelay, long period, TimeUnit unit)

JM-8 Page 21
Future Object
The result of the task submitted for execution to an executor can be accessed using the
[Link]. The future object returned by the executor. Future can be thought of as a promise
made to the caller by the executor. The future interface is mainly used to get the results of Callable
results. whenever the task execution is completed, it is set in this Future object by the executor.
Syntax:
Future<String> result = [Link](callableTask);

JM-8 Page 22
Pool Size:

If you want run() to return any value then we need to use the Callable Interface which is of Generic type

JM-8 Page 23
[Link]() return the Future values which leads to the dark mode. Future will empty until the
thread pool completes its execution. Future is a blocking operation. If there is no value in Future and u
called the get() then it makes the main thread into blocked and whole process gets blocked until it gets
the value from the thread pool

JM-8 Page 24
Synchronized Collections
12 May 2025 20:14

Most of the Java Collections are not thread safe


Ways to make collections thread safe
- Use [Link]() method
- Use the concurrent collections which are synchronized
Downsides of using the [Link]() approach
- Coarse grained locking
- Limited functionality
- No fail Fast Iterators
- Performance Overhead

JM-8 Page 25
ACID
20 May 2025 10:26

Common ACID-Related Problems in Practice


Dirty Reads (Violation of Isolation): Reading uncommitted data from another transaction.
Lost Updates: Two transactions overwrite each other's updates.
Non-repeatable Reads: Same query gives different results within a transaction.
Phantom Reads: Rows added/removed by another transaction are visible during iteration.
Crash Recovery Failures (Violation of Durability): Changes are lost after system failure if not properly
logged.

JM-8 Page 26

You might also like