1000 Java Qns
1000 Java Qns
JDK stands for Java Development Kit. It contains the tools and libraries for development of Java programs. It
also contains compilers and debuggers needed to compile Java program,
JRE stands for Java Runtime Environment. This is included in JDK. JRE provides libraries and JVM that is
required to run a Java program.
Java byte code can run on any supported platform in same way. Where as other languages require libraries
compiled for a specific platform to run.
6. Why people say that Java is 'write once and run anywhere' language?
You can write Java code on Windows and compile it in Windows platform. The class and jar files that you get
from Windows platform can run as it is on Unix environment. So it is a truly platform independent language.
Behind all this portability is Java byte code. Byte code generated by Java compiler can be interpreted by any
JVM. So it becomes much easier to write programs in Java and expect those to run on any platform.
Java compiler javac compiles java code and JVM java runs that code.
Bootstrap ClassLoader: This is the first ClassLoader. It loads classes from rt.jar file.
Extension ClassLoader: It loads class files from jre/lib/ext location.
Application ClassLoader: This ClassLoader depends on CLASSPATH to find the location of class files. If you
specify your jars in CLASSPATH, then this ClassLoader will load them.
9. Can we write main method as public void static instead of public static void?
No, you cannot write it like this. Any method has to first specify the modifiers and then the return value. The
order of modifiers can change.
We can write static public void main() instead of public static void main().
10. In Java, if we do not specify any value for local variables, then what will be the default value of the local
variables?
Java does not initialize local variables with any default value. So these variables will be just null by default.
11. Let say, we run a java class without passing any arguments. What will be the value of String array of
arguments in Main method?
By default, the value of String array of arguments is empty in Java. It is not null.
12. What is the difference between byte and char data types in Java?
Both byte and char are numeric data types in Java. They are used to represent numbers in a specific range.
Major difference between them is that a byte can store raw binary data where as a char stores characters or text
data.
OOPS
14. What is the difference between Object Oriented Programming language and Object Based
Programming language?
Object Oriented Programming languages like Java and C++ follow concepts of OOPS like- Encapsulation,
Abstraction, Polymorphism and Inheritance etc.
15. In Java what is the default value of an object reference defined as an instance variable in an Object?
All the instance variable object references in Java are null.
By default, Java provides a default constructor for every object. If we overload a constructor then we have to
implement default constructor.
Java specification says that it will provide a default constructor if there is no overloaded constructor in a class.
But it does not say anything about the scenario in which we write an overloaded constructor in a class.
We need at least one constructor to create an object, that’s why Java provides a default constructor.
When we have overloaded constructor, then Java assumes that we want some custom treatment in our code. Due
to which it does not provide default constructor. But it needs default constructor as per the specification. So it
gives error.
If we set a method as abstract it means that it has no body and it should be implemented in a child class. But the
constructor is called implicitly when the new keyword is used. Therefore it needs a body.
If we set a method as static it means that it belongs to the class, but not a particular object. The constructor is
always called to initialize an object. Therefore, there is no use of marking constructor static.
Inheritance
21. What is the purpose of ‘this’ keyword in java?
In Java, ‘this’ keyword refers to current instance of the object.
The issue with Multiple Inheritance is that both the parent classes may have different implementation for the same
method. So they have different ways of doing the same thing. Now which implementation should the child class
choose?
This leads to ambiguity in Multiple Inheritance. This is the main reason for Java not supporting Multiple
Inheritance in implementation.
Lets say you have a class TV and another class AtomBomb. Both have method switchOn() but only TV has
switchOff() method. If your class inherits from both these classes then you have an issue that you can switchOn()
both parents, but switchOff will only switchOff() TV.
E.g. A Library has students. If a Library is destroyed, Students still exist. So Library and Student are related by
Aggregation. A Library has Books. If Library is destroyed, the Books are also destroyed. Books of a Library
cannot exist without the Library. So Book and Library are related by Composition.
In case an object reference points to null object, and we try to access a method or member variable on it, then we
get NullPointerException.
By using ‘super’ we can call a method of parent class from the method of a child class.
We can also call the constructor of a parent class from the constructor of a child class by using ‘super’ keyword.
No, Java does not allow using both super() and this() in same constructor. As per Java specification, super() or
this() must be the first statement in a constructor.
One disadvantage of cloning is that the return type is an Object. It has to be explicitly cast to actual type.
Static
This variable is loaded in memory only once at the time of class loading. So it saves memory, since it is not
defined per object in Java.
If we want tighter control on scope, then variables should be created at the object creation level.
Also defining static variables is not a good practice because they go against the principles of Object Oriented
Programming.
Also a static method can access and modify static data members. This also helps in keeping the behavior as well
as state at the class level.
As such it is a known as convention to mark main method static in Java. But if we remove the static, then there
will be ambiguity. Java process may not know which method of a class to call to start the program.
So this convention helps in Java process to identify the starting code for a program in class that is passed as an
argument to java process.
Sometimes, we can also replace static block with a static method of class.
7. What happens when static modifier is not mentioned in the signature of main method?
As per Java specification, main method has to be marked as static. It needs only one argument that is an array of
String.
A program can compile with a non-static method. But on execution it will give NoSuchMethodError.
8. What is the difference between static method and instance method in Java?
Often, there is a need to define a behaviour for a class that is not dependent on member variables of an object.
Such behaviour is captured in a static method. If there is a behaviour dependent upon the member variables of an
object, then we do not mark it static, it remains as instance method.
To call as static method, we do not need to create an object. We just call it with class name. But to call an instance
method, we need to create/get an object first.
Instance member variables cannot be accessed by a static method. But an instance method can call both instance
variables and static variables.
4. Why it is not possible to do method overloading by changing return type of method in java?
If we change the return type of overloaded methods then it will lead to ambiguous behavior. How will clients
know which method will return what type. Due to this different return type are not allowed in overloaded methods.
10. What is the difference between method overloading and method overriding in Java?
Differences between method overloading and overriding are:
Let say class B is child of class A. There is a get() method in class A as well as class B. get() method of class A
can return an instance of A, and get() method of class B return an instance of B. Here class B overrides get()
method, but the return type is different.
Before Java 5, any method that overrides the method of parent class would have same return type.
From Java 5 onwards, a child class can override a method of parent class and the child class method can return
an object that is child of object return by parent class method.
Polymorphism
So at compile time it is not known which method will be called at run time.
Abstraction
1. What is Abstraction in Object Oriented programming?
Abstraction is the process of hiding certain implementation details of an object and showing only essential
features of the object to outside world.
Abstraction process identifies commonalities and hides the complexity of implementation. It helps us in focusing
on the interface that we share with the outside world.
An abstract class has to be extended in Java and its abstract methods have to be implemented by a child class.
Also Java does not allow new instance of Abstract class.
4. Is it allowed to mark a method abstract method without marking the class abstract?
No. Java specification says that if there is at least one abstract method in a class, the class has to be marked
abstract.
An abstract method has to be overridden by a child class. And a final method cannot be overridden. Therefore a
method can be either abstract or final in Java.
Annotations are more powerful than a Marker interface. They allow programmers to pass more sophisticated
information to classes that "consume" it.
13. What is the difference between abstract class and interface in Java?
Differences between Abstract class and Interface are as follows:
An abstract class can have implemented methods with body (non-abstract methods). Interface has only abstract
methods. From Java 8 onwards, interface can have static/default methods in implemented form.
An abstract class can have instance member variables. An interface cannot have instance variables. It can only
have constants.
An abstract class can have a constructor. Interface cannot have constructor. It has to be implemented by another
class.
A class can extend only one abstract class. A class can implement more than one interface.
14. Does Java allow us to use private and protected modifiers for variables in interfaces?
No. All the variables in an interface are implicitly public.
Final
1. How can you change the value of a final variable in Java?
Java does not allow changing the value of a final variable. Once the value is set, it cannot be changed.
A blank final static variable can be initialized in the static block of class.
Package
1. What is the purpose of package in Java?
A package is used to encapsulate a group of classes, interfaces and sub-packages. Often, it is a hierarchical
structure of storing information. It is easier to organize the related classes and subpackages in this manner.
A Package also provides access protection for classes and interfaces. A package also helps in removing naming
collision.
2. What is java.lang package?
In Java, java.lang package contains the classes that are fundamental to the design of Java programming language.
The most important class in this package is Object class.
It also contains wrapper classes like- Integer, Boolean, Character etc. It provides Math class for mathematical
operations.
If you have two classes with same name, then you may get name collision on importing the class erroneously.
7. What is the difference between import static com.test.Fooclass and import com.test.Fooclass?
First import is a static import and the second import is normal import of a class. First import allows us to import
static members of class.
Internationalization
1. What is Locale in Java?
A Locale object represents a specific geographical, political, or cultural region. It is used to locale-sensitive
operations in Java.
It helps is following the local conventions of a country, native or region. These conventions can be for formatting
the dates, money, numbers etc.
Serialization
Communication: It is used for transmitting an object over network between two machines.
Persistence: We can store the object’s state in a database and retrieve it from database later on.
Caching: Serialization can be used for caching to improve performance. We may need 10 minutes to build an
object, but it may take just 10 seconds to de-serialize the object.
Cross JVM Synchronization: It can be used in same way across multiple JVM that follow different architecture.
3. What is Deserialization?
Deserialization is the process of reconstructing the object from the serialized state. It is the reverse process of
serialization.
Deserialization is to convert a stream of bytes back into a copy of the original object.
During serialization process the transient variables are not considered part of the persistent state of an object.
To solve this issue, we can mark the member variable XYZ as Transient in class ABC. This will allow us to
serialize the class
ABC.
A class implements methods writeExternal() and readExternal() to store and restore the object.
When we implement Serializable interface, the class is serialized automatically by default. We can override
writeObject() and readObject()methods to control more complex object Serialization process.
In case of Externalizable, we use readExternal() and writeExternal() methods to give control to class for class's
serialization process.
Reflection
1. What is Reflection in Java?
Reflection is Java language's ability to inspect and dynamically call classes, methods, attributes etc. at Runtime.
It helps in examining or modifying the Runtime behavior of a class at Runtime.
Reflection allows you to write programs that do not have to "know" everything at compile time. It makes programs
more dynamic, since they can be tied together at runtime.
Many modern frameworks like Spring etc. use Reflection. Some modern languages like Python etc. also use
Reflection.
3. How can we access private method of a class from outside the class?
We can use Reflection to access private method of a class from outside the class. IN Java, we use
getDeclaredMethod() to get instance of a private method. Then we mark this method accessible and finally invoke
it.
In following sample code, we are accessing private method message() of class Foo by Reflection.
FileName: FooMethodCall.java import java.lang.reflect.Method; public class FooMethodCall{ public static void
main(String[] args)throws Exception{
Class c = Class.forName("Foo");
Object o= c.newInstance();
Method m =c.getDeclaredMethod("message", null);m.setAccessible(true);
m.invoke(o, null);
}
}
Garbage Collection
1. What is Garbage Collection in Java?
Java has an internal mechanism called Garbage collection to reclaim the memory of unused projects at run time.
If an Object is not Garbage Collected, then this method may not be called.
Strong Reference
Soft Reference
Weak Reference
Phantom Reference
Runtime.maxMemory() - This method returns the value of maximum memory that JVM can use.
Inner Classes
1. What is a Nested class?
In Java, a Nested class is a class declared inside another class. We can have more than one class declared inside
a file.
Logical Grouping: We can logically group classes in one place. If one class is useful to only one other class, then
we put smaller class within the larger class and keep them in one file. This kind of nesting "helper classes" in a
top level class makes the package more streamlined.
Encapsulation: Nested classes increase encapsulation. Let say there are two top-level classes, Foo and Bar. Bar
needs access to private members of Foo. We can hide class Bar within class Foo. In this way, private members
of Foo can be accessed by class Bar. So class Foo remains encapsulated. Also, class Bar remains hidden from the
outside world.
Code Clarity: Nested classed make the code more readable and well organized. Only Top-level classes are
exposed. The helper classes are kept hidden and closer the code where it is used by a Top-level class.
4. What is the difference between a Nested class and an Inner class in Java?
An Inner class in Java is non-static class. It is a type of Nested class that is defined in another class but not
qualified with a Static modifier. A Nested class is also a class can be Static Nested class or a non-Static Inner
class.
An Inner class has access to other members of the enclosing class, even if they are declared private. A Static
Nested class can not access the other members of the enclosing class.
6. How can we access the non-final local variable, inside a Local Inner class?
Java allows a Local Inner class to access only Constant local members. So we have to make the non-final local
variable as final constant to access it inside a Local Inner class.
// Client Code
Abc.registerCallback(new Abc.Xyz() {
public void callback() {...}
});
Any code that cannot access Abc can not access interface Xyz also.
So the purpose of declaring an Inner interface is to restrict its access from outside world.
String
An Immutable object cannot be modified or changed in Java. String is an Immutable class in Java.
Once a String object is created, it cannot be changed. When we assign the String to a new value, a new object is
created.
2. Why a String object is considered immutable in java?
Java language uses String for a variety of purposes. For this it has marked String Immutable.
Let say there are 2 String variables A and B that reference to a String object “TestData”. All these variables refer
to same String literal. If one reference variable A changes the value of the String literal from “TestData” to
“RealData”, then it will affect the other variable as well. Due to which String is considered Immutable. In this
case, if one variable A changes the value to “RealData”, then a new String literal with “RealData” is created and
A will point to new String literal. While B will keep pointing to “TestData”
The above code creates only one object. Since there is only one String Literal “HelloWorld” created, all the
references point to same object.
The above code creates two objects. One object is created in String constant pool and the other is created on the
heap in non-pool area.
It provides the advantage of making String processing efficient in Time as well as Space complexity. But it
introduces extra time in creation of String.
Java provides a default implementation for toString() method. But we can override this method to return the
format that we want to print.
11. Arrange the three classes String, StringBuffer and StringBuilder in the order of efficiency for String
processing operations?
StringBuilder is the most efficient class. It does not have the overhead of Synchronization. StringBuffer is a
Synchronized class. It has better performance than String but it is slower than StringBuilder. String is the slowest
for any String processing operations, since it is leads to creation of new String literal with each modification.
Exception Handling
1. What is Exception Handling in Java?
Java provides Exception Handling mechanism to handle Runtime errors that occur in JVM. There are checked
exceptions in a program that we expect to occur in certain situations.
Exception handling mechanism catches these checked exceptions and takes relevant actions.
Checked Exceptions are checked at compile time in Java. Unchecked Exceptions happen at Runtime, so they are
not checked at compile time.
IO Exception, SQL Exception etc. are examples of Checked Exceptions. Null Pointer Exception, Arithmetic
Exception etc. are examples of Unchecked Exceptions.
3. What is the base class for Error and Exception classes in Java?
Error as well as Exception class is derived from Throwable class in Java.
We use throw to explicitly throw an exception. We usedthrows to declare an exception in method definition.
We cannot propagate checked exceptions with throw only. But checked exceptions can be propagated with throws
keyword.
Call to throw occurs within a method. throws is just used with method signature.
We can throw only one exception at a time. But we can mention as many exceptions in throws clause.
In Exception Propagation, uncaught exceptions are propagated in the call stack until stack becomes empty. This
propagation is called Exception Propagation.
Let say an exception propagates from one method to another method. A() calls B(), which calls C(), which calls
D(). And if D() throws an exception, the exception will propagate from D to C to B to A, unless one of the
methods catches the exception.
12. When we override a method in a Child class, can we throw an additional Exception that is not thrown
by the Parent class method?
Yes, Java allows us to throw additional Exception in a child class, but the additional exception should be an
unchecked exception (RuntimeException).
Java Collection
1. What is the difference between Collection and Collections Framework in Java?
In Java, a Collection is an object that contains multiple elements of same type in a single unit. These multiple
elements can be accessed through one Collection object.
In Java Collections Framework is a library that provides common architecture for creating, updating and accessing
different types of collections. In Collections framework there are common methods that are frequently used by
developers for working on a Collection object.
Reusability: Java Collections Framework provides common classes and utility methods than can be used with
different types of collections. This promotes the reusability of the code. A developer does not have to re-invent
the wheel by writing the same method again.
Quality: Using Java Collection Framework improves the program quality, since the code is already tested and
used by thousands of developers.
Speed: Most of programmers report that their development speed increased since they can focus on core logic
and use the generic collections provided by Java framework.
Maintenance: Since most of the Java Collections framework code is open source and API documents is widely
available, it is easy to maintain the code written with the help of Java Collections framework. One developer can
easily pick the code of previous developer.
But the Collection interface extends Iterable interface. Due to this some people consider Iterable interface as the
root interface.
Iterable interface is present in java.lang package but Collection interface is present in java.util package. Oracle
Java API docs mention that Collection interface is a member of the Java Collections framework.
Whereas, Iterable interface is not stated as a part of Java Collections framework in Java docs.
Collection defines methods that are used for data structures that contain the objects. Collections defines the
methods that are used for operations like access, find etc. on a Collection.
E.g.
ListIterator<Integer> iter = myList.iterator(); while(iter.hasNext()) { itr.remove();
}
An iterator is first created to traverse the list. But at the same time the list is changed by remove() method.
In Java, it is not allowed for a thread to modify a collection while another thread is iterating it. ListIterator provides
the capability of removing an object during traversal.
7. How will you convert a List into an array of integers like- int[]?
We can use ArrayUtils class in Apache Commons Lang library.
int[] intArray = new int[myList.size()]; for (int i=0; i < myList.size(); i++) {
intArray [i] = myList.get(i);
}
8. How will you convert an array of primitive integers int[] to a List collection?
We can use ArrayUtils in Apache Commons Lang library for this purpose.
The other option would be to use a for loop and explicitly adding integers to a List.
int[]intArray = {10,20,30};
List<Integer> intList = new ArrayList<Integer>();
for (int i: intArray) {
intList.add(i);
}
In this example we filter any names that are less than 5 characters long.
In this case we put a list into a HashSet. Internally hashCode() method is used to identify duplicate elements.
The trick in this question is to use a collection that does not allow duplicate elements. So we use a Set for this
purpose.
In Java, there are many ways to maintain a Collection with elements in sorted order.
Some collections like TreeSet store elements in the natural ordering. In case of natural ordering we have to
implement Comparable interface for comparing the elements.
Another option is to use the utility method Collections.sort() to sort a List. This sorting gives nlog(n) order of
performance. But if we have to use this method multiple times then it will be costly on performance.
Another option is to use a PriorityQueue that provides an ordered queue. The main difference between
PriorityQueue and
Collections.sort() is that PriorityQueue maintains a queue in Order all the time, but we can only retrieve head
element from queue. We cannot access the elements of PriorityQueue in Random order.
We can use TreeSet to maintain sorted order of elements in collection if there are no duplicate elements in
collection.
What are the differences between the two data structures: a Vector and an ArrayList?
An ArrayList is a newer class than a Vector. A Vector is considered a legacy class in Java. The differences are:
Synchronization: Vector is synchronized, but the ArrayList is not synchronized. So an ArrayList has faster
operations than a Vector.
Data Growth: Internally both an ArrayList and Vector use an array to store data. When an ArrayList is almost
full it increases its size by 50% of the array size. Whereas a
Vector increases it by doubling the underlying array size.
ArrayList is more popular than LinkedList in Java due to its ease of use and random access to elements feature.
But LinkedList is better in the scenario when we do not need random access to elements or there are a lot of
insertion, deletion of elements.
What are the differences between a List and Set collection in Java?
Order: List collection is an ordered sequence of elements. A Set is just a distinct collection of elements that is
unordered.
Positional Access: When we use a List, we can specify where exactly we want to insert an element. In a Set there
is no order, so we can insert element anywhere without worrying about order.
Duplicate: In a List we can store duplicate elements. A Set can hold only unique elements.
What are the differences between a HashSet and TreeSet collection in Java?
Ordering: In a HashSet elements are stored in a random order. In a TreeSet, elements are stored according to
natural ordering.
Null Value Element: We can store null value object in a HashSet. A TreeSet does not allow to add a null value
object.
Performance: HashSet performs basic operations like add(), remove(), contains(), size() etc in a constant size
time. A TreeSet performs these operations at the order of log(n) time.
Speed: A HashSet is better than a TreeSet in performance for most of operations like add(), remove(), contains(),
size() etc .
Internal Structure: a HashMap in Java internally backs a HashSet. A NavigableMap backs a TreeSet internally.
Features: A TreeSet has more features compared to a HashSet. It has methods like pollFirst(), pollLast(), first(),
last(), ceiling(), lower() etc.
Element Comparison: A HashSet uses equals() method for comparison. A TreeSet uses compareTo() method for
comparison to maintain ordering of elements.
In Java, how will you decide when to use a List, Set or a Map collection?
If we want a Collection that does not store duplicate values, then we use a Set based collection.
If we want to frequently access elements operations based on an index value then we use a List based collection.
E.g. ArrayList
If we want to maintain the insertion order of elements in a collection then we use a List based collection.
For fast search operation based on a key, value pair, we use a HashMap based collection.
If we want to maintain the elements in a sorted order, then we use a TreeSet based collection.
Synchronization: HashMap is not a synchronized collection. If it is used in multi-thread environment, it may not
provide thread safety. A Hashtable is a synchronized collection. Not more than one thread can access a Hashtable
at a given moment of time. The thread that works on Hashtable acquires a lock on it and it makes other threads
wait till its work is completed.
Null values: A HashMap allows only one null key and any number of null values. A Hashtable does not allow
null keys and null values.
Ordering: A HashMap implementation by LinkedHashMap maintains the insertion order of elements. A TreeMap
sorts the mappings based on the ascending order of keys. On the other hand, a Hashtable does not provide
guarantee of any kind of order of elements. It does not maintain the mappings of key values in any specific order.
Legacy: Hashtable was not the initial part of collection framework in Java. It has been made a collection
framework member, after being retrofitted to implement the Map interface. A HashMap implements Map
interface and is a part of collection framework since the beginning.
Iterator: The Iterator of HashMap is a fail-fast and it throws ConcurrentModificationException if any other Thread
modifies the map by inserting or removing any element except iterator’s own remove() method.
Enumerator of the Hashtable is not fail-fast.
Order: A HashMap does not maintain any order of its keys. In a HashMap there is no guarantee that the element
inserted first will be retrieved first.
In a TreeMap elements are stored according to natural ordering of elements. A TreeMap uses compareTo()
method to store elements in a natural order.
Internal Implementation: A HashMap uses Hashing internally. A TreeMap internally uses Red-Black tree
implementation.
Parent Interfaces: A HashMap implements Map interface. TreeMap implements NavigableMap interface.
Null values: A HashMap can store one null key and multiple null values. A TreeMap can not contain null key but
it may contain multiple null values.
Performance: A HashMap gives constant time performance for operations like get() and put(). A TreeMap gives
order of log(n) time performance for get() and put() methods.
Comparison: A HashMap uses equals() method to compare keys. A TreeMap uses compareTo() method for
maintaining natural ordering.
Features: A TreeMap has more features than a HashMap. It has methods like pollFirstEntry() , pollLastEntry() ,
tailMap() , firstKey() , lastKey() etc. that are not provided by a HashMap.
Type: Comparable<T> is an interface in Java where T is the type of objects that this object may be compared to.
Comparator<T> is also an interface where T is the type of objects that may be compared by this comparator.
Sorting: In Comparable, we can only create one sort sequence. In Comparator we can create multiple sort
sequences.
Method Used: Comparator<T> interface in Java has method public int compare (Object o1, Object o2) that returns
a negative integer, zero, or a positive integer when the object o1 is less than, equal to, or greater than the object
o2. A Comparable<T> interface has method public int compareTo(Object o) that returns a negative integer, zero,
or a positive integer when this object is less than, equal to, or greater than the object o.
Objects for Comparison: The Comparator compares two objects given to it as input. Comparable interface
compares "this" reference with the object given as input.
Package location: Comparable interface in Java is defined in java.lang package. Comparator interface in Java is
defined in java.util package.
A Properties file in Java is a list of key-value pairs that can be parsed by java.util.Properties class.
Properties files are used for many purposes in all kinds of Java applications. Some of the uses are to store
configuration, initial data, application options etc.
When we change the value of a key in a properties file, there is no need to recompile the Java application. So it
provides benefit of changing values at runtime.
The equals() method in Object class is used to check whether two objects are same or not. If we want a custom
implementation we can override this method.
For example, a Person class has first name, last name and age. If we want two Person objects to be equal based
on name and age, then we can override equals() method to compare the first name, last name and age of Person
objects.
Generally in HashMap implementation, if we want to use an object as key, then we override equals() method.
Object class in Java has hashCode() method. This method returns a hash code value, which is an integer.
The hashCode() is a native method and its implementation is not pure Java.
Java doesn't generate hashCode(). However, Object generates a HashCode based on the memory address of the
instance of the object.
Yes. A collection is a group of elements put together in an order or based on a property. Often the type of element
can vary. But the properties and behavior of a Collection remains same. Therefore it is good to create a Collection
with Generics so that it is type-safe and it can be used with wide variety of elements.
What is the difference between Collections.emptyList() and creating new instance of Collection?
In both the approaches, we get an empty list. But Collections.emptyList() returns an Immutable list. We cannot
add new elements to an Immutable empty list.
Collections.emptyList() works like Singleton pattern. It does not create a new instance of List. It reuses an existing
empty list instance.
Therefore, Collections.emptylist() gives better performance if we need to get an emptyList multiple times.
How will you copy elements from a Source List to another list?
Collections.copy() does not reallocate the capacity of destination List if it does not have enough space to contain
all elements of source List. It throws IndexOutOfBoundsException.
The benefit of Collection.copy() is that it guarantees that the copy will happen in linear time. It is also good for
the scenario when we want to reuse an array instead of allocating more memory in the constructor of ArrayList.
One limitation of Collections.copy() is that it can accept only List as source and destination parameters.
What are the Java Collection classes that implement List interface?
What are the Java Collection classes that implement Set interface?
AbstractSet
ConcurrentSkipListSet
CopyOnWriteArraySet
EnumSet
HashSet
JobStateReasons
LinkedHashSet
TreeSet
Iterator and ListIterator are two interfaces in Java to traverse data structures. The differences between these two
are:
ListIterator can be used to traverse only a List. But Iterator can be used to traverse List, Set, and Queue etc.
An Iterator traverses the elements in one direction only. It just goes. ListIterator can traverse the elements in two
directions i.e. backward as well as forward directions.
Iterator cannot provide us index of an element in the Data Structure. ListIterator provides us methods like
nextIndex() and previousIndex() to get the index of an element during traversal.
Iterator does not allow us to add an element to collection while traversing it. It throws
ConcurrentModificationException. ListIterator allows use to add an element at any point of time while traversing
a list.
An existing element’s value cannot be replaced by using Iterator. ListIterator provides the method set(e) to replace
the value of last element returned by next() or previous() methods.
Both Iterator and Enumeration are interfaces in Java to access Data Structures. The main differences between
these are:
Enumeration does not provide remove() method. So we cannot remove any element during traversal. Iterator
provides remove() method.
Iterator is a fail-fast interface, it gives ConcurrentModificationException if any thread tries to modify an element
in the collection being iterated. Enumeration is not fail-fast.
Data Structure: An ArrayList is an indexed based dynamic array. A LinkedList is a Doubly Linked List data
structure.
Insertion: It is easier to insert new elements in a LinkedList, since there is no need to resize an array.
Insertion in ArrayList is O(n), since it may require resizing of array and copying its contents to new array.
Remove elements: LinkedList has better performance in removal of elements than ArrayList.
Memory Usage: LinkedList uses more memory than ArrayList, since it has to maintain links for next and
previous nodes as well.
Access: LinkedList is slower in accessing an element, since we have to traverse the list one by one to access the
right location.
Duplicate Elements: A Set does not allow inserting duplicate elements. A Map does not allow using duplicate
keys, but it allows inserting duplicate values for unique keys.
Null values: A Set allows inserting maximum one null value. In a Map we can have single null key at most and
any number of null values.
Ordering: A Set does not maintain any order of elements. Some of sub-classes of a Set can sort the elements in
an order like LinkedHashSet. A Map does not maintain any order of its elements. Some of its sub-classes like
TreeMap store elements of the map in ascending order of keys.
The Dictionary class in Java is used to store key-value pairs. Any non-null object can be used for key or value.
But we cannot insert a null key or null object in Dictionary.
A HashMap in Java has default initial capacity 16 and the load factor is 0.75f (i.e. 75% of current map size). The
load factor of a HashMap is the level at which its capacity should be doubled.
For example, in a HashMap of capacity 16 and load factor .75. The capacity will become 32 when the HashMap
is 75% full. Therefore, after storing the 12th key– value pair (16 * .75 = 12) into HashMap, its capacity becomes
32.
Storage: A HashSet is used to store distinct objects. A HashMap is used for storing key & value pairs, so that
these can be retrieved by key later on.
Duplicate Elements: A HashSet does not allow storing duplicate elements. A HashMap also does not allow
duplicate keys. But we can store duplicate values in a HashMap.
Null Elements: In a HashSet we can store a single null value. In a HashMap we can store single null key, but any
number of null values.
Element Type: A HashSet contains only values of objects as its elements. Whereas a HashMap contains
entries(key value pairs).
Iteration: By using an Iterator we can iterate a HashSet. But a HashMap has to be converted into Set for iteration.
As the name suggests, HashSet and HashMap are Hashing based collections. Similarities between HashSet and
HashMap are:
Thread Safety: Both HashMap and HashSet are not synchronized collections. Therefore they are not good for
thread-safe operations. To make these thread-safe we need to explicitly use synchronized versions.
Order of Elements: None of these classes guarantee the order of elements. These are unordered collections.
Internal Implementation: A HashMap backs up a HashSet internally. So HashSet uses a HashMap for
performing its operations.
Performance: Both of these collections provide constant time performance for basic operations such as insertion
and removal of elements.
For example, a Person class has first name, last name and age. If we want two Person objects to be equal based
on name and age, then we can override equals() method to compare the first name, last name and age of Person
objects.
Generally in HashMap implementation, if we want to use an object as key, then we override equals() method.
Sometimes we need to make collections Thread-safe for use in Multi-threading environment. In Java, Collections
class provides useful static methods to make a List, Set or Map as synchronized collections. Some of these
methods are:
static <K,V>
SortedMap<K,V> synchronizedSortedMap(SortedMap<K,V> m) Returns a synchronized (thread-safe) sorted
map backed by the specified sorted map.
In a Hashing scenario, at times two different objects may have same HashCode but they may not be equal.
Therefore, Java will face issue while storing the two different objects with same HashCode in a HashMap. This
kind of situation is Hash Collision.
There are different techniques of resolving or avoiding Hash Collision. But in HashMap, Java simply replaces
the Object at old Key with new Object in case of Hash Collision.
Queue is a FIFO data structure. FIFO stands for First In First Out. It means the element added first will be removed
first from the queue. A real world example of Queue is a line for buying tickets at a station. The person entering
first in the Queue is served first.
Stack is a LIFO data structure. LIFO stands for Last In First Out. The element that is added last is removed first
from the collection. In a Stack elements are added or removed from the top of stack.
A real world example of Stack is back button in browser. We can go back one by one only and it works in the
reverse order of adding webpages to history.
Iterator interface in Java is based on Iterator design pattern. By using an Iterator one can traverse a container of
objects and can also access the objects in the container. A container of objects is a Collection class in Java.
Version: Enumeration interface is in Java since JDK 1.0. Iterator interface was introduced in Java 1.2.
Method names: Names of methods in Iterator interface are hasNext(), next(), remove(). Names of methods in
Enumeration interface are hasMoreElements(), nextElement().
Legacy Interface: Enumeration is considered as a legacy interface. It is used to traverse legacy classes like
Vector, Stack and HashTable. Iterator is a newer interface that is used to traverse almost all of the classes in Java
Collections framework.
Safety: Since Iterator is fail-fast and does not allow modification of a collection by other threads, it is considered
safer than Enumeration.
What is the design pattern used in the implementation of Enumeration in Java?
Enumeration is based on Iterator design pattern. Iterator design pattern provides a common interface with methods
to traverse the collection of objects. It hides the underlying implementation details of the collection.
If we want to use an object as a key in a HashMap in Java, then we have to make sure that it has the implementation
of equals() and hashCode() methods.
In Collections class, Java provides a method reverse(List list) that can be used to reverse a List.
E.g.
Collections.reverse(myList);
Java provides Arrays class in java.util package. Arrays class has a method asList() that accepts an Array as input
and returns a List as output.
What is the difference between peek(), poll() and remove() methods of Queue interface in java?
In a Java Queue, poll() and remove() methods can be used for removing the head object of Queue. The main
difference arises in the case when Queue is empty().
If Queue is empty then poll() method returns null value. If Queue is empty then remove() method throws
NoSuchElementException.
In a Java Queue, peek() method retrieves the head of Queue but it does not remove it. If queue is empty then
peek() method returns null value.
Size: Array in Java is fixed in size. We cannot change the size of array after creating it. ArrayList is dynamic in
size. When we add elements to an ArrayList, its capacity increases automatically.
Performance: In Java Array and ArrayList give different performance for different operations.
add() or get(): Adding an element to or retrieving an element from an array or ArrayList object has similar
performance. These are constant time operations.
resize(): Automatic resize of ArrayList slows down the performance. ArrayList is internally backed by an Array.
In resize() a temporary array is used to copy elements from old array to new array.
Primitives: Array can contain both primitive data types as well as objects. But ArrayList cannot contain primitive
data types. It contains only objects.
Iterator: In an ArrayList we use an Iterator object to traverse the elements. We use for loop for iterating elements
in an array.
Type Safety: Java helps in ensuring Type Safety of elements in an ArrayList by using Generics. An Array can
contain objects of same type of class. If we try to store a different data type object in an Array then it throws
ArrayStoreException.
Length: Size of ArrayList can be obtained by using size() method. Every array object has length variable that is
same as the length/size of the array.
Adding elements: In an ArrayList we can use add() method to add objects. In an Array assignment operator is
used for adding elements.
How will you insert, delete and retrieve elements from a HashMap collection in Java?
Delete: We use remove() method to delete key-value pair from the HashMap.
Value remove(Object key)
What is the increasing order of performance for following collection classes in Java?
Hashtable has the worst performance and HashMap has the best performance.
A Map is a collection objects. But Map interface is not compatible with Collection interface in Java.
A Map requires key as well as a value. So it requires two parameters to add an element to a HashMap.
But Collection interface provides add(Object o) method with only one parameter.
Map collection has to provide methods like valueSet, keySet etc. These methods are specific to Map collection.
Where as methods in Collection interface can be reused by a List, Set, Queue etc.
There are mainly two ways to iterate the elements of list in Java:
Iterator: We can get an Iterator for list and use it to iterate the objects of the list.
For-each loop: We can use for-each loop to traverse all the elements of a list.
In CopyOnWriteArrayList, all mutative operations (add, set etc.) are implemented by making a fresh copy of the
underlying array.
Remove() method in HashMap uses logic similar to the one used in get() method. First we locate the correct
bucket in HashMap for an entry. Then within that bucket we remove the element e. It is similar to removing a
node from a single-linked list.
If e is the first element in the bucket we set the corresponding element of Hash to e.next. Else we set the next field
of the element just before e to e.next.
BlockingQueue supports operations that wait for the queue to become non-empty when retrieving an element.
Also it supports the operations that wait for space to become available in the queue while storing an element.
It is a NavigableMap. The map sorts the keys in natural order or it can use a Comparator supplied at the creation
time.
Fail-fast iterator throws ConcurrentModificationException. But Fail-safe iterator does not throw this exception.
Fail-fast iterator does not clone the original collection. Fail-safe iterator creates a copy of the original collection
of objects.
A Fail-fast iterator tries to immediately throw Exception when it encounters failure. A Fail-safe Iterator works on
a copy of collection instead of original collection.
ConcurrentHashMap extends AbstractMap in Java. It was introduced in Java 1.5. It provides concurrency in a
collection based on a HashMap.
Internally there is a Hashtable backing a ConcurrentHashMap. This Hashtable supports the concurrent methods
for retrieval of data as well as updates on ConcurrentHashMap.
It also supports a set of sequential and bulk operations. These operations accept parallelismThreshold argument.
The problem arises when HashMap treats both outputs same instead of different. It will overwrite the most recent
key-value pair with the previous key-value pair.
So it is important to implement hashCode() and equals() methods correctly for an efficient HashMap collection.
Single enum type: All the elements in an EnumSet must come from a single enum type when the set is created.
Iterator: The iterator of EnumSet traverses the elements in their natural order. (It is the order in which the enum
constants are declared).
Null: In an EnumSet, null elements are not permitted. If we try to insert a null element it throws
NullPointerException.
Thread-safe: EnumSet is not a synchronized collection. For use in multi-threading scenarios, EnumSet should
be synchronized.
Bit flags: EnumSet is a very good alternative to int based “bit flags” implementation.
Java 1.5 has provided new package java.util.concurrent. This package contains thread-safe collection classed.
These collection classes can be modified while iterating. The iterator of these classes is fail-safe.
Java provides an easy method in java.utils.Collections class to create a ThreadSafe collection from a regular
collection.
IndentityHashMap in Java implements Map interface. But it is not a general purpose implementation. It violates
the general contract of Map interface by a different implementation of equals() method.
In an IdentityHashMap, two keys k1 and k2 are equal if and only if (k1==k2). (In a normal Map implementation
(like HashMap) two keys k1 and k2 are considered equal if and only if (k1==null ?
k2==null : k1.equals(k2)).)
It implements the Map interface with a hash table, using referenceequality in place of object-equality when
comparing keys (and values).
The node table should not considered distinct objects as equal even if they happen to be equal.
Proxy objects: Another use of this class is to maintain proxy objects. A debugging program has to maintain a
proxy object for each object in the program being debugged.
IdentityHashMap class has one tuning parameter for performance improvement: expectedMaxSize.
This parameter is the maximum number of key-value mappings that the map is expected to hold.
We can use this parameter is used to determine the number of buckets initially in the hash table. The precise
relationship between the expected maximum size and the number of buckets is unspecified.
If the number of key-value mappings exceeds the expected maximum size, the number of buckets is increased.
Increasing the number of buckets is also known as rehashing. Rehashing may be fairly expensive. So it is better
to create identity hash maps with a sufficiently large expected maximum size.
But iteration over a Map collection requires time proportional to the number of buckets in the hash table. So
iteration may take extra time due to large number of buckets.
Therefore the value of expectedMaxSize should be set in consideration with both of these aspects.
Is IdentityHashMap threadsafe?
The implementation of IdentityHashMap is not thread-safe, since its methods are not synchronized.
The iterators returned by the iterator method of IdentityHashMap are fail-fast. But the fail-fast behavior of an
iterator cannot be guaranteed.
It is not a synchronized class. We can make a WeakHashMap thread safe by using Collections.synchronizedMap()
method.
The presence of a mapping for a given key does not prevent the key from being discarded by the garbage collector.
In Java, there are useful methods to make a Collection class read Only. We can make the Collection read Only
by using one of the following methods:
Collections.unmodifiableMap(Map m)
Collections.unmodifiableList(List l)
Collections.unmodifiableSet(Set s)
Collections.unmodifiableCollection(Collection c)
In a Java collection UnsupportedOperationException is thrown when the requested operation is not supported by
the collection.
If there is an optional add() or remove() methods in a read only collection, then this exception can be thrown.
Let say there is a Customer class. We add objects of Customer class to an ArrayList. How can we sort the
Customer objects in ArrayList by using customer firstName attribute of Customer class?
There are two ways to handle this scenario. We can use these options:
Comparable: Implement the Comparable interface for Customer class and compare customer objects by firstName
attribute.
Comparator: Implement Comparator for comparing two Customer objects on the basis of firstName attribute.
Then use this comparator object in sort method of Collections class.
In Java 1.5 many Concurrent collection classes were added in SDK. These are ConcurrentHashMap,
CopyOnWriteArrayList,
BlockingQueue etc.
Java also provides utility methods to get a synchronized copy of collection like ArrayList, HashMap etc. by using
Collections.synchronizedList(), Collections.synchronizedMap() methods.
The main difference is in performance. Concurrent collection classes have better performance than synchronized
collection classes because they lock only a portion of the class to achieve concurrency and thread-safety.
ConcurrentHashMap is more suited for scenarios where we have multiple reader threads and one writer thread.
In this case map is locked only during the write operation.
If we have an equal number of reader and writer threads then ConcurrentHashMap performance is similar to a
Hashtable or a synchronized HashMap.
myMap = Collections.emptyMap();
Any map: For all other scenarios, we can use following code by using new method:
222.What is the difference between remove() method of Collection and remove() method of Iterator?
List interface also provides remove(int index) method to remove an object at a specific index.
These methods are used to remove an entry from Collection, while no thread is iterating over it.
When we are iterating over a Collection, then we have to remove() method of Iterator. This method removes
current element from Iterator’s point of view. If we use remove(0 method of Collection or List, then we will get
ConcurrentModificationException.
Therefore, it is recommended to use remove() method of Iterator during the traversal of a Collection by an Iterator.
Between an Array and ArrayList, which one is the preferred collection for storing objects?
An ArrayList is backed up by array internally. There are many usability advantages of using an ArrayList over
an array in Java.
Array has a fixed length at the time of creation. Once it is created we cannot change its length.
ArrayList is dynamic in size. Once it reaches a threshold, it automatically allocates a new array and copies
contents of old array to new array.
Also ArrayList provides support of Generics. But Array does not support Generics.
E.g. If we store an Integer object in a String array at Runtime it will throw ArrayStoreException. Whereas, if we
use ArrayList then as compile time we will get the error. This helps in preventing errors from happening at
runtime.
If we know the size in advance and do not need re-sizing the collection then Array should be used in place of an
ArrayList.
But it requires careful observation, since locking behavior of Hashtable is different than that of
ConcurrentHashmap.
A Hashtable locks whole Map instead of a portion of Map. Compound operations like if(Hashtable.get(key) ==
null) put(key, value) work in Hashtable but not in ConcurrentHashMap.
In CopyOnWriteList, concurrency is achieved by copying ArrayList over each write and replace with original
instead of locking.
It is a thread-safe list.
It is different from a Vector in terms of Concurrency. CopyOnWriteArrayList provides better Concurrency by
reducing contention among readers and writers.
Why ListIterator has add() method but Iterator does not have?
ListIterator can iterate in the both directions of a Collection. It maintains two pointer for previous and next
element. In ListIterator we can use add() method to add an element into the list immediately before the element
returned by next() method.
So a subsequent call to next() method will not be affected. And the call to previous() method will return the newly
added element.
In Iterator we can only traverse in one direction. So there is no purpose of add() method there.
How can we create a Map with reverse view and lookup in Java?
In a Map we can lookup for a value by using a distinct key. In a Map with reverse view and lookup, even the
values are distinct. So there is one to one mapping between keys and values and vice version.
If we enable this constraint on a Map then we can look up a key by its value. Such data structure is called bi-
directional map.
But Apache Common Collections and Guava libraries provide implementation of bidirectional map. It is called
BidiMap and BiMap. Both of these data structure enforce the constraint of one to one mapping between keys and
values.
Therefore, when a thread is copying the map, another thread can modify it.
In Java an array has to know the type information of its elements at runtime.
This information is used at runtime to throw ArrayStoreException if data type of an element to be inserted does
not match the type of Array.
In case of Generics, the type information of a collection is erased at runtime by Type Erasure. Due to this array
cannot use generics as elements.
A PriorityQueue is data structure based on Queue. Unlike Queue, the elements on PriorityQueue are not returned
in FIFO order.
A PriorityQueue maintains the natural order of its elements or it uses a Comparator provided at initialization.
PriorityQueue does not allow null values. We cannot add any object that does not provide natural ordering to
PriorityQueue.
What are the important points to remember while using Java Collections Framework?
Some of the important points to remember while using Java Collections Framework are:
Interfaces: For Collections, we should write code with generic interfaces instead of concrete implementation.
Due to this we maintain the flexibility of changing the implementation at a later point of time.
Generics: We should use Generics for type-safety and to avoid ClassCastException at runtime.
Collections: It is recommended to use Collections utility class for algorithms and various other common methods
for Collections.
Right Type: We have to choose the right type of Java collection based on our need. If size is fixed, we can use
Array over ArrayList. If we do not want duplicate elements we use Set.
If we need the ability to iterate the elements of a Map in the order of insertion then we use a TreeMap.
Initial Size: In some collection classes we can specify the initial size/capacity. Therefore we should have an
estimate of number of elements in a Collection before deciding the right collection type. We can use it to avoid
rehashing or resizing.
Map: We should use immutable classes provided by Java as key elements in a Map.
How can we pass a Collection as an argument to a method and ensure that method will not be able to
modify it?
To ensure that a method is not able to modify a Collection passed as an argument, we have to make the Collection
read only.
This will make sure that any operation to change the collection will throw UnsupportedOperationException.
A HashMap in Java stores both key and value objects, in a bucket. It is stored as an Entry object that implements
Map.Entry interface.
The key object used in a HashMap has to provide implementation for hashCode() and equals() methods.
When put() method is used to store a key-value pair, the HashMap implementation calls hashCode() method on
Key object to calculate a hash that is used to find a bucket where Entry object will be stored.
When get() method is used to retrieve a value stored against a key object, we first calculate a hash of Key object.
Then we use this hash to find the bucket in which that particular key is stored.
Once Key object’s location is found, it may happen that more than one Key is stored in same location. So now
we use equals() method to find the exact Key object. Once the exact Key object is found we use it to get Value
object.
Internally, a HashSet uses a HashMap to store the elements and to maintain the uniqueness of elements.
As the name suggests, NavigableMap provides the capability to navigate the keys of a Map in Java. A
NavigableMap extends SortedMap interface.
Some of the interesting methods of a NavigableMap are descendingKeySet(), descendingMap(), headMap() and
tailMap().
The descendingKeySet() method of NavigableMap returns a NavigableSet in which the elements are stored in
reversed order as compared to the original key set.
The returned view is internally represented by the original KeySet of NavigableMap. Therefore any changes to
the descending set also get reflected in the original set.
But it is not recommended to remove elements directly from the key set. We should use the Map.remove() method.
The descendingMap() method of NavigableMap returns a NavigableMap which is an inverse view of the original
Map. The order of the elements in this view are in reverse order of the elements in original map. Any changes to
this view are also reflected in the original map.
Methods like lowerEntry, floorEntry, ceilingEntry, and higherEntry return Map.Entry objects associated with
keys respectively less than, less than or equal, greater than or equal, and greater than a given key.
Methods like lowerKey, floorKey, ceilingKey, and higherKey return only the associated keys. All of these
methods are designed for locating, not traversing entries.
What is the difference between headMap(), tailMap() and subMap() methods of NavigableMap?
//this headmap2 will contain elements "1", "2", and "3" because
"inclusive"=true
NavigableMap headmap2 = original.headMap("3", true);
The tailMap() method works similar to headMap() method, but it returns all elements that are higher than the
given input element.
The subMap() method accepts two parameters demarcating the boundaries of the view map to return.
All the three methods return a subset of the original map in a view form.
We can use Collections.sort method to sort the elements of a List in natural order. To use this method, we have
to make sure that element objects implement compareTo() method.
We can also use a Comparator to define the natural ordering for elements of a List. Then we can use this Custom
Comparator in sort method of Collections class.
From Java 8 onwards it is a very easy to get a Stream from a List. We can just use stream() method to get a stream
from a list of elements.
Yes, we can create a Map from the elements of a Stream. We can use map() method to get a Map.
E.g. items.stream()
.map( item -> item.toLowerCase() )
In this example we are creating a map with each item object mapped to its LowerCase equivalent.
ArrayDeque: It is a resizable array implementation of Deque. The capacity of ArrayDeque can increase based
on the need of the program. It is not thread safe implementation. Also the iterator on ArrayDeque is failfast.
LinkedList: This is another popular implementation of Deque interface in Java. It is also not synchronized, so it
is not thread-safe. It mainly provides functionality of a doubly linked list.Multi-threading
A thread in Java is a lightweight process that runs within another process or thread.
It is an independent path of execution in an application. JVM gives each thread its own method-call stack.
When we start JVM, Java starts one thread. This thread calls the main method of the class passed in argument to
java call.
Scheduler in Java schedules different threads based on the priority of a thread. It is also known as pre-emptive
scheduling.
The thread with higher priority gets preference in execution over a thread with lower priority.
In Java, a new thread gets the same priority as the priority of the parent thread that creates it.
What are the three different priorities that can be set on a Thread in Java?
Default priority of a thread is 5 NORM_PRIORITY. The value of MIN_PRIORITY is 1 and the value of
MAX_PRIORITY is 10.
In Java, Thread Scheduler controls thread scheduling. But we can use join() method on a thread to make current
thread to wait for another thread to finish.
When we use join(), the current thread stops executing. It wait for the thread on which join() is called to finish.
This makes sure that current thread will continue only after the thread it joined finished running. Consider
following example:
The main difference between wait() and sleep() is that wait is an Object level method, whereas sleep() is a static
method in Thread class. A waiting thread can be woken up by another thread by calling notify() on the monitor
which is being waited on. But a sleeping thread cannot be woken up.
A wait() and notify() has to happen within the same block that is synchronized on the monitor object.
When we call wait() the current thread releases the monitor and goes to waiting state. Then another thread calls
notify() to wake it up.
In case of sleep() current thread does not release the monitor or locks. It just sleeps for some pre-defined time
period.
Yes. We can call run() method of a thread. But it does not work as a separate thread. It will just work as a normal
object in main thread and there will not be context switching between the threads.
Java provides support for Multithreading. In a Multithreading environment, one process can execute multiple
threads in parallel at the same time.
In Java, you can create process and then create multiple threads from that process. Each process can execute in
parallel to perform independent tasks.
Java provides methods like- start(), notify(), wait(), sleep() etc. to maintain a multi-threading environment.
What are the advantages of Multithreading?
In Java, a thread is a lightweight process that runs within another process or thread. It is an independent path of
execution in an application. Each thread runs in a separate stack frame.
By default Java starts one thread when the main method of a class is called.
In Java, every Thread has a priority. This priority is specified as an integer value. The priority value is used in
scheduling to pick up the thread with higher priority for execution. The threads with higher priority get more
preference in execution than the threads with lower priority.
The task scheduler schedules the higher priority threads first, followed by the lower priority threads.
What are the differences between Pre-emptive Scheduling Scheduler and Time Slicing Scheduler?
In Pre-emptive scheduling, the highest priority task will keep getting time to execute until it goes to waiting state
or dead state or a task with higher priority comes into queue for scheduling.
In Time slicing scheduling, every task gets a predefined slice of time for execution, and then it goes to the pool
of tasks ready for execution. The scheduler picks up the next task for execution, based on priority and various
other factors.
Yes. We can call run() method of a thread. But it does not work as a separate thread. It will just work as a normal
object in main thread and there will not be context-switching between the threads.
How will you make a user thread into daemon thread if it has already started?
No. We cannot make a user thread to daemon thread once it has already started.
No. We can call start() method only once on a thread in Java. If we call it twice, it will give us exception.
We can interrupt a thread if we want to wake it up from the sleep or wait state.
Yes. We can use synchronized block to lock an object. The locked object is inaccessible to any other thread. Only
the thread that has locked it can access it.
How notify() method is different from notifyAll() method?
In Java, notify() method is used to unblock a specific thread that is in waiting stated. Whereas, notifyAll() method
is used to unblock all the threads that are in waiting state.
A daemon thread in Java is a low priority thread that does not prevent the JVM from exiting when the program
finishes. The thread keeps running. Garbage Collection is an example of daemon thread.
How can we make a regular thread Daemon thread in Java?
We can call setDaemon(boolean) method to change a thread to daemon thread before the thread starts.
How will you make a user thread into daemon thread if it has already started?
No. We cannot make a user thread to daemon thread once it has already started. If we do it by calling setDaemon(),
it will throw
IllegalThreadStateException
No. We can call start() method only once on a thread in Java. If we call it twice, it will give us exception.
The shutdown hook is a thread that is invoked implicitly by JVM just before the shut down. It can be used to
clean up unused resources etc.
It is a feature in Java that helps in controlling the access of multiple threads to a shared resource.
Synchronized block has many uses in Java multi-threading environment. Some of the uses are:
A Deadlock is a situation in which two or more threads are waiting on each other to release a resource. Each
thread is waiting for a resource that is held by the other waiting thread.
At times there is a circular wait when more than two threads are waiting on each other’s resources.
Concurrency is the ability of a program to execute several programs simultaneously. This is achieved by
distributing computations over multiple CPU cores of a machine or even over different machines within the same
network.
It can increase the speed of execution of the overall program in multi-processor or multi-core system.
The main difference is that a thread runs in a shared memory space, where as a process runs in its own memory
space.
A process runs the execution in an environment provided by the operating system. A process has its own set of
private resources (e.g. memory, open files, etc.).
A thread lives within a process and shares the resources likememory, open files etc. with the other threads of the
same process.
This ability to share resources between different threads makes thread more suitable for tasks where performance
is a significant factor.
In Java, a process refers to the running of Java Virtual Machine (JVM). But a thread lives within a JVM and it
can be created or stopped by the Java application at runtime.
What is a Scheduler?
A scheduler is a program that is the implementation of a scheduling algorithm to manage access of processes and
threads to limited resource like CPU or an I/O channel.
The goal of most scheduling algorithms is to provide load balancing for the available processes/threads and to
guarantee that each process/thread will get a reasonable time frame to access the requested resource exclusively.
In a JVM, each Java program is executed within the main process that starts with java.exe. Therefore each Java
application has at least one thread.
Waiting: A thread waiting indefinitely for another thread to perform a particular action is in Waiting state.
Timed_waiting: A thread waiting for another thread to perform an action for up to a specified waiting time is in
Timed_waiting state.
The priority of a thread in Java can be set by using setPriority(int priority) method.
The JDK class java.lang.ThreadGroup provides methods to handle a whole group of Threads.
With the help of these methods we can interrupt all threads of a group or set the maximum priority of all threads
of a group.
The stop() method in Thread class is a deprecated method. Its use is not recommended.
When we call stop() method, the thread unlocks all monitors that it has acquired. If any locked object was in an
inconsistent state, this state gets visible to all other threads.
It can cause unexpected behavior when other threads work on this inconsistent object.
Extend Thread class: We can extend java.lang.Thread class and implement run() method. On calling start()
method it will start a new thread.
Implement Runnable interface: We can implement java.lang.Runnable interface and pass the implemented
object to the constructor of java.lang.Thread class. On calling start() it will start a new thread.
We can create a volatile reference pointing to the current thread. This reference can be set to null by other threads
to flag that the current thread should stop execution.
In following example threadStopper is the volatile reference that can be set as null in stopThread() method by
other threads.
Busy waiting is also known as busy-looping or spinning. It is a multi-threading technique in which a process
repeatedly checks if a condition is true.
For example, a process can keep checking if any keyboard input is available.
In general, busy waiting is considered as Anti-pattern that wastes processor time, so it should be avoided.
// Busy waiting
while (timeToStop > currentTime) {
currentTime = System.currentTimeMillis();
}
}
});
There is a simple way to prevent busy-waiting in Java. We can just put the current thread to sleep for given
amount of time.
It can be done by calling sleep() method of java.lang.Thread class. We can pass the number of milliseconds to
sleep() method as an argument.
Java does not guarantee that Thread.sleep() will cause the thread to sleep for exactly N number of milliseconds.
Sometime the thread can sleep for than N number of milliseconds.
In real-time processing we need precise time period for which a thread should run or sleep.
Therefore the invocation of Thread.sleep() method is not recommended for use in real-time processing.
Can we wake up a thread that has been put to sleep by using Thread.sleep() method?
We can use interrupt() method of java.lang.Thread class to interrupt a thread that is in sleep state. It will get
InterruptedException to wake up from the sleep.
Sample code is as follows:
Thread.sleep(10000);
SOP(“Interrupting myThread");
myThread.interrupt();
}
}
What are the two ways to check if a Thread has been interrupted?
In Java, a Thread can call Thread.interrupted() method to check if it has been interrupted or not.
The other option is to call isInterrupted() method of Thread class to check if it has been interrupted or not.
How can we make sure that Parent thread waits for termination of Child thread?
We can use join() method for this purpose. On calling join() method, current thread waits for the child thread to
which it joins to finish.
In Java we can get InterruptedException from sleep() or join() methods. Throwing InterruptedException is way
to inform that another thread has interrupted this thread.
In general, the purpose of Interrupt is to ask current thread to stop its current execution and finish unexpectedly.
Therefore ignoring this exception by catching it and only logging it to the console or some log file is not the
recommended approach.
The run() method of the Runnable interface does not allow that throwing any exceptions. So we cannot re-throw
InterruptedException.
Therefore the correct way to handle this exception is that run() method should check and handle this exception
by itself and take appropriate action.
When we mark a method as synchronized and then call this method, then this method will first acquire the intrinsic
lock of the object in which that method is mentioned.
In case the synchronized method throws an exception, the intrinsic lock will be released.
The reasoning behind this is that, in this case, only the constructing thread would have access to the object being
constructed.
No. Java does not allow primitive values to be used for intrinsic locks.
Yes. An intrinsic lock can be accessed by the same thread multiple times. So an Intrinsic lock is re-entrant.
If it is not allowed then the code that acquires a lock would have to avoid acquiring the lock that it has already
acquired.
An atomic operation is an operation that completes in a single step relative to other threads.
No. The statement i++ is not an Atomic operation. It has more than one operation.
First JVM loads the current value of i in memory. Then it increments it. Finally it stores the new value back into
variable i.
The current thread that executes this operation may be interrupted between any of the above-mentioned three
steps. Therefore it is not an atomic operation.
Java language provides some basic Atomic operations. These operations can be used to make sure that concurrent
threads always see the same value.
Read operations on reference variables and primitive variables (except long and double)
Write operations on reference variables and primitive variables (except long and double)
The above-mentioned code is for creating a Singleton class. But this code is not thread-safe.
In this we check the value of instance second time in the synchronized block. But the JIT compiler can rearrange
the Bytecode in such a way that the reference to SingletonDoubleCheck instance will be set before the execution
of constructor.
Due to this the method getInstance() will return an object that may not have been initialized properly.
We can use the keyword volatile for instance to make this threadsafe code.
Any variables that is marked as volatile will be visible to other threads only after the completion of the constructor
of the object.
Mutual exclusion: There has to be a resource that can be accessed by only one thread at any point of time.
Resource holding: One thread locks one resource and holds it, and at the same time it tries to acquire lock on
another mutually exclusive resource.
No preemption: There is no pre-emption mechanism by which resource held by a thread can be freed after a
specific period of time.
Circular wait: There can be a scenario in which two or more threads lock one resource each and they wait for
each other’s resource to get free. This causes circular wait among threads for same set of resources.
To prevent a Deadlock from occurring at least one requirement for a deadlock has to be removed:
Mutual exclusion: We can use optimistic locking to prevent mutual exclusion among resources.
Resource holding: A thread has to release all its exclusive locks if it does not succeed in acquiring all exclusive
locks for resources required.
No preemption: We can use timeout period for an exclusive lock to get free after a given amount of time.
Circular wait: We can check and ensure that circular wait does not occur, when all exclusive locks have been
acquired by all the threads in the same sequence.
We can use ThreadMXBean.findDeadlockedThreads() method to detect deadlocks in Java program. This bean
comes with JDK:
Livelock is a scenario in which two or more block each other by responding to an action caused by another thread.
In a Livelock scenario, two more threads change their state in such a way that it prevents progress on their regular
work.
E.g. Consider scenario in which two threads try to acquire two locks. They release a lock that they have acquired,
when they cannot acquire the second lock.
In a Livelock situation, both threads concurrently try to acquire the locks. Only one thread would succeed, the
second thread may succeed in acquiring the second lock.
Now both threads hold two different locks. And both threads want to have both locks. So they release their lock
and try again from the beginning. This situation keeps repeating multiple times..
In a priority based scheduling, Threads with lower priority get lesser time for execution than higher priority
threads.
If a lower priority thread performs a long running computation, it may happen that this thread does not get enough
time to finish its computations just in time. In such a scenario, the tread with lower priority would starve. It will
remain away from the threads with higher priority.
It is not defined for synchronization that which thread will enter a synchronized block. It may happen that if many
threads are waiting for the entry to a synchronized block, some threads may have to wait longer than other threads.
Hence these threads with lower priority will not get enough time to finish their work in time.
A race condition is an unwanted situation in which a program attempts to perform two or more operations at the
same time, but because of the logic of the program, the operations have to be performed in proper sequence to
run the program correctly.
Most of the time race condition occurs in “check then act” scenario. Both threads check and act on same value.
But one of the threads acts in between check and act. See this example to understand race condition.
if (x == 3) // Check
{
y = x * 5; // Act
In Java there is a class ReentrantLock that is used for implementing Fair lock. This class accepts an optional
parameter fairness. When fairness is set to true, the RenentrantLock will give access to the longest waiting thread.
The most popular use of Fair lock is in avoiding thread starvation. Since longest waiting threads are always given
priority in case of contention, no thread can starve.
Downside of Fair lock is the low throughput of the program. Since low priority or slow threads are getting locks
multiple time, it leads to slower execution of a program.
The only exception to a Fair lock is tryLock() method of ReentrantLock. This method does not honor the value
of fairness parameter.
Which two methods of Object class can be used to implement a Producer Consumer scenario?
In a Producer Consumer scenario, one thread is a Producer and another thread is a Consumer.
For this scenario to start working, a Consumer has to know when the Producer has produced. In Object class,
there is a wait() method. A Consumer calls wait method to wait on Producer. The Producer used notify() method
of Object class to inform Consumer that it has produced.
In this way the processor time between produce and consume operations is freed due to the use of wait() and
notify() methods.
If multiple threads are waiting on an object’s monitor, JVM awakens one of them. As per Java specification the
choice of this thread is arbitrary and it is at the discretion of the implementation. So there is no guarantee of rule
that a specific thread will be awakened by JVM on notify() method call.
Check if following code is threadsafe for retrieving an integer value from a Queue?
public Integer getNextInt() { Integer retVal = null; synchronized (queue) { try { while (queue.isEmpty()) {
queue.wait();
}
} catch (InterruptedException e) { e.printStackTrace();
}
}
synchronized (queue) { retVal = queue.poll(); if (retVal == null) {
System.err.println("retVal is null");
throw new IllegalStateException(); }
}
return retVal;
}
}
In the above code Queue is used as object monitor to handle concurrency issues. But it may not behave correctly
in a multithreading scenario.
There are two separate synchronized blocks in above code. In case two threads are woken up simultaneously by
another thread, both threads will enter one after in the second synchronized block.
Only one of the two threads will get new value from the queue and make it empty. The second thread will poll
on an empty queue and it will not get any non-null return value.
In Java, Thread class has a static method holdsLock(Object objToCheck) to check whether thread has a lock on
objToLock object.
This method will return true if current thread holds the lock on the objToLock object that was passed as an
argument to this method.
The yield() method of Thread class is used to give a hint to scheduler that the current thread wants to free the
processor.
The scheduler can either use this hint or just ignore this hint. Since the scheduler behavior is not guaranteed, it
may happen that the current thread again gets the processor time.
It can be used for debugging or testing purposes. But there is rarely any concrete use of this method.
What is an important point to consider while passing an object from one thread to another thread?
This is a multi-threading scenario. In a multi-threading scenario, the most important point is to check whether
two threads can update same object at the same time.
If it is possible for two threads to update the same object at the same time, it can cause issues like race condition.
So it is recommended to make the object Immutable. This will help in avoiding any concurrency issues on this
object.
As per Java specification, following are the rules for creating an Immutable object:
Do not provide "setter" methods that modify fields or objects referred to by fields.
Do not allow subclasses to override methods. The simplest way to do this is to declare the class as final. A more
sophisticated approach is to make the constructor private and construct instances in factory methods.
If the instance fields include references to mutable objects, do not allow those objects to be changed.
Do not share references to the mutable objects. Never store references to external, mutable objects passed to the
constructor; if necessary, create copies, and store references to the copies. Similarly, create copies of your internal
mutable objects when necessary to avoid returning the originals in your methods.
ThreadLocal class provides thread-local variables. Each thread accesses only its own local variables. It has its
own copy of the variable.
By using ThreadLocal, if thread X stores a variable with value x and another thread Y stores same variable with
the value y, then X
gets x from its ThreadLocal instance and Y gets y from its ThreadLocal instance.
Typically, ThreadLocal instances are private static fields that are associated with the state of a thread.
One use case is to transport security or login information within an instance of ThreadLocal so that every method
can access it.
Another use case is to transport transaction information across an application, without using the method-to-
method communication.
In an environment with more than one CPU, we can parallelize the computation tasks on multiple CPUs. This
leads to parallel processing of a bigger task that takes lesser time due to multiple threads dividing the work among
themselves.
One example is that if we have to process 1000 data files and calculate the sum of numbers in each file. If each
file takes 5 minutes, then 1000 files will take 5000 minutes for processing.
But by using multi-threading we can process these files in 10 parallel threads. So each thread will take 100 files
each. Since now work is happening in 10 parallel threads, the time taken will be around 500 minutes.
Scalability is the capability of a program to handle growing amount of work or its potential to be enlarged in order
to accommodate growth.
A program is considered scalable, if it is suitable to handle a large amount of input data or a large number of users
or a large number of nodes.
When we say a program does not scale, it means that program fails on increasing the size of task.
How will you calculate the maximum speed up of an application by using multiple processors?
Amdahl’s law gives the theoretical speedup in latency of the execution of a task at fixed workload.
It gives the formula to compute the theoretical maximum speed up that can be achieved by providing multiple
processors to an application.
When n converges against infinity, the term (1-B)/n converges against zero. Therefore, the formula can be reduced
in this special case to 1/B.
In general, the theoretical maximum speedup behaves in inverse proportion to the fraction that has to be executed
serially. This means the lower this fraction is, the more theoretical speedup can be achieved.
Lock contention is the situation when one thread is waiting for a lock/object that being held by another thread.
The waiting thread cannot use this object until the other thread releases the lock on that object.
Ideally locks reduce the thread contention. Without locks, multiple threads can operate on same object and cause
undesirable behavior. If locking is implemented correctly it reduces the occurrence of contention between
multiple threads.
synchronized (map) {
Random r = new Random();
Integer value = Integer.valueOf(42); String key = r.nextString(5);
map.put(key, value);
}
The code uses Random() to get a random string and it also used Integer to convert 42 in an object. Since these
lines of code are specific to this thread, these can be moved out of Synchronization block.
Lock splitting is a technique to reduce Lock contention in multithreading. It is applicable in scenario when one
lock is used to synchronize access to different aspects of the same application.
Sometimes we put one lock to protect the whole array. There can be multiple threads trying to get the lock for
same array. This single lock on array can cause Lock contention among threads. To resolve this we can give one
lock to each element of the array. Or we can use modulus function to assign different locks to a small group of
array elements. In this way we can reduced the chance of Lock contention. This is Lock splitting technique.
ReadWriteLock uses two locks. One lock for read-only operations, another lock for write operations.
Its implementation is based on the premise that concurrent threads do not need a lock when they want to read a
value while no other thread is trying to write.
In this implementation, read-only lock can be obtained by multiple threads. And the implementation guarantees
that all read operation will see only the latest updated value as soon as the write lock is released.
In Lock splitting we use different locks for different parts of the application. In Lock striping we use multiple
locks to protect different parts of the same data structure.
ConcurrentHashMap class of Java internally uses different buckets to store its values. Each bucket is chosen
based on the value of key. ConcurrentHashMap uses different locks to guard different buckets. When one thread
that tries to access a hash bucket, it can acquire the lock for that bucket. While another thread can simultaneously
acquire lock for another bucket and access it. In a synchronized version of HashMap, the whole map is has one
lock.
Lock striping technique gives better performance than Synchronizing the whole data structure.
In a CAS operation, the processor provides a separate instruction that can update the value of a register only if
the provided value is equal to the current value.
Let say thread T1 can update a value by passing its current value and the new value to be updated to the CAS
operation. In case another thread T2 has updated the current value of previous thread, the previous thread T1’s
current value is not equal to the current value of T2. Hence the update operation fails.
In this case, thread T1 will read the current value again and try to update it.
Java classes like AtomicInteger or AtomicBoolean internally use CAS operations to support multi-threading.
By using Object pools in an application we limit the number of new objects to be created for a class. In a single
thread operation, it can improve the performance by reusing an already created object from a pool.
In a multi-threading application an object pool has to provide synchronized access to multiple threads. Due to this
only one thread can access the pool at a time. Also there is additional cost due to Lock contention on pool. These
additional costs can outweigh the cost saved by reuse of an object from the pool.
Therefore using an Object pool may not always improve the performance in a multi-threading application.
How can techniques used for performance improvement in a single thread application may degrade the
performance in a multi-threading application?
In a single thread applications we can use Object pool for performance optimization. Where as in multi-threading
environment, it may not be a good idea to use an Object pool. Increased overhead of synchronization and lock
contention can degrade the performance gained by using Object pool in a multi-threading application.
Another example is the implementation in which a List keeps a separate variable to hold the number of elements.
This technique is useful in single thread application where size() method can return the value from this variable,
without the need to count all the elements of list.
But in a multi-threading application, this separate variable can rather degrade the performance. This variable has
to be access controlled by a lock since multiple concurrent threads can insert an element in a list. The additional
cost of lock on this variable can outweigh the benefit gained by it in a multi-threading application.
Executor interface has only execute(Runnable) method. The implementing class of this interface has to execute
the given Runnable instance passed to execute() method at some time in the future.
ExecutorService interface extends Executor interface. It provides additional methods like- invokeAny(),
invokeAll(), shutdown(), awaitTermination(). These method provide the ability to shutdown the thread so that
further requests can be rejected. Also it provides ability to invoke a collection of Callable tasks.
What will happen on calling submit() method of an ExecutorService instance whose queue is already full?
What is a ScheduledExecutorService?
ScheduledExecutorService interface extends the interface ExecutorService. It provides various schedule()
methods that can be used to submit new tasks to be executed at a given point of time.
One of the schedule() method provides the ability to schedule a oneshot task that can be executed after given
delay.
Another version of schedule() method provides the ability to execute ScheduleFuture after a given amount of
delay.
In addition there are scheduleAtFixedRate() and scheduleWithFixedDelay() methods that can execute an action
at a periodic interval of time.
Runnable interface defines run() method that does not return any value.
Callable interface allows call() method to return a value to its caller. A Callable interface can also throw an
exception in case of an error. Also Callable is a newer addition to Java since version 1.5.
Therefore Future interface provides isDone() method to check if the asynchronous computation has finished or
not.
We can also check if the task was cancelled by calling isCancelled() method.
In a multi-threading it is not advisable to use regular HashMap. We can use ConcurrentHashMap class in multi-
threading applications.
It also provides synchronizedList(List) and synchronizedMap(Map) methods that can be used to convert a List or
Map to a synchronized instance.
Semaphore class in Java is used to implement a counting semaphore. It is used to restrict the number of threads
that can access a physical or logical resource.
We can also use it to control how many threads can access the critical section of a program or a resource
concurrently.
The first argument in Semaphore constructor is the total number of permits available. Each invocation of acquire()
method tries to obtain one of the available permits.
The acquire() method is used to acquire a permit from the semaphore. If we pass number of permits required to
acquire() method, then it blocks the thread until that number of permits are available.
Once a thread has finished its work, we can use release() method to release the permits.
CountDownLatch class helps in implementing synchronization in Java. It is used to implement the scenarios in
which one or more threads have to wait until other threads have reached the same state such that all thread can
start.
There is a synchronized counter that is decremented until it reaches the value zero. Once it reaches zero, it means
that all waiting threads can proceed now.
It is a versatile tool that can be used for other Synchronization scenarios as well. It can also work as on/off latch
or gate. All threads invoking await() method wait at the gate until it is opened by a thread invoking countdown()
method.
CountDownLatch is used in simple use cases where a simple start stop is required. A CyclicBarrier is useful in
complex scenarios where more coordination is required. E.g. MapReduce algorithm implementation.
CyclicBarrier resets the internal value to the initial value once the value reaches zero. CyclicBarrier can be used
to implement the scenarios in which threads have to wait for each other multiple times.
ForkJoinPool class is in the center of Fork/Join framework. It is a thread pool that can execute instances of
ForkJoinTask.
ForkJoinTask class provides the fork() and join() methods. The fork() method is used to start the asynchronous
execution of a task. The join() method is used to await the result of the computation.
RecursiveAction class has compute() method that does not have to return a value.
RecursiveAction can be used when the action has to directly operate on a Data structure. It does not need to return
any computed value.
In Java 8, Collections provide parallelStream() method to create a stream that can be processed by a Thread pool.
We can also call the intermediate method parallel() on a given stream to convert it into a sequential stream of
parallel tasks.
A parallel stream in Java 8 has a much higher overhead compared to a sequential one.
When there are a large number of items to process and the processing of each item takes time and is parallelizable.
When there is a performance problem in the sequential processing. When current implementation is not already
running in a multithread environment. If there is already a multi-threading environment, adding parallel stream
can degrade the performance.
Local variables stored in Stack of one Thread are not visible to another Thread.
Where as, Heap is a common memory area in JVM. Heap is shared by all threads. All objects are created inside
heap.
To improve performance thread can cache the values from heap into their stack. This can create problem if the
same variable is modified by more than one thread.
In such a scenario we should used volatile keyword to mark a variable volatile. For a volatile variable the thread
always reads the value from main memory.
The steps to take Thread dump of Java process depends on the operating system.
On taking Thread dump, Java writes the state of all threads in log files or standard error console.
We can press Ctrl + Break key together to take thread dump in Windows.
We can execute kill -3 command for taking Thread dump on Linux. Another option to take Thread dump is jstack
tool. We can pass process id of java process to this tool for taking Thread dump.
This is the simple one, -Xss parameter is used to control stack size of Thread in Java. You can see this list of JVM
options to learn more about this parameter.
If we set it as 1 MB, then every thread will get 1MB of stack size.
There are two threads T1 and T2? How will you ensure that these threads run in sequence T1, T2 in Java?
One of the simplest way for sequencing is join() method of Thread class.
We can call join() method to start a thread when another thread has finished.
We start with the last thread to execute first. And make this thread join on the next thread.
In this case we start thread T2 first. And then call T1.join() so that thread T2 waits for thread T1 to finish
execution.
Java 8
Lambda Expression
Stream API
Date and Time API
Functional Interface
Interface Default and Static Methods
Optional
Base64 Encoding and Decoding
Nashorn JavaScript Engine
Collections API Enhancements
Concurrency Enhancements
Fork/Join Framework Enhancements
Spliterator
Internal Iteration
Type Annotations and Repeatable Annotations
Method Parameter Reflection
JVM Parameter Changes
Lambda expression is an anonymous function. It is like a method that does not need any access modifiers, name
or return value declaration. It accepts a set of input parameters and returns result.
Lambda expression can be passed as a parameter in a method. So we can treat code in Lambda expression as data.
This piece of code can be passed to other objects and methods.
Parameter list: A Lambda expression can have zero or more parameters. Parameter list is optional to Lambda.
Lambda arrow operator: “->” is known as Lambda arrow operator. It separates the list of parameters and the body
of Lambda.
Lambda expression body: The piece of code that we want to execute is written in Lambda expression body.
E.g. In following example:
Parameter list = e
Arrow = ->
Body = System.out.println( e )
( e -> System.out.println( e ) );
The main theme of Java 8 is support for functional programming. With increase in Database size and growth of
multi-code CPU servers, there is need for Java to support such large-scale systems.
With new features of Java 8, it is possible to create functional programs to interact efficiently with Big Data
systems. Support for Streams is very helpful in this regard.
Lambda expressions are very useful for cloud computing where we can pass code as data and run the same code
on multiple servers.
Optional is a best practice that is borrowed from Google Guava library for handling the exceptional cases. This
has made programs more robust with support for edge cases.
We can pass a lambda expression as an object to a method. This reduces the overhead involved in passing an
anonymous class.
We can also pass a method as a parameter to another method using lambda expressions.
A Functional interface in Java is an interface that has exactly one abstract method.
It can have default methods with implementation. A default method is not abstract.
In Java 8, java.lang.Runnable and java.util.concurrent.Callable are two very popular Functional interfaces.
A Functional interface is also known as Single Abstract Method Interface, since it has exactly one abstract
method.
To define a Functional interface in Java 8, we can create an Interface with exactly one abstract method.
The only exception to this rule is that if we override java.lang.Object class’s method as an abstract method, then
it does not count as an abstract method.
Functional Interfaces are mainly used in Lambda expressions, Method reference and constructor references.
In functional programming, code can be treated as data. For this purpose Lambda expressions are introduced.
They can be used to pass a block of code to another method or object.
Functional Interface serves as a data type for Lambda expressions. Since a Functional interface contains only one
abstract method, the implementation of that method becomes the code that gets passed as an argument to another
method.
Is it mandatory to use @FunctionalInterface annotation to define a Functional interface in Java 8?
But, if we mark an interface with @FunctionalInterface annotation then Java Compiler will give us error in case
we define more than one abstract method inside that interface.
What are the differences between Collection and Stream API in Java 8?
Version: Collection API is in use since Java 1.2. Stream API is recent addition to Java in version 8.
Usage: Collection API is used for storing data in different kinds of data structures. Stream API is used for
computation of data on a large set of Objects.
Finite: With Collection API we can store a finite number of elements in a data structure. With Stream API, we
can handle streams of data that can contain infinite number of elements.
Eager vs. Lazy: Collection API constructs objects in an eager manner. Stream API creates objects in a lazy
manner.
Multiple consumption: Most of the Collection APIs support iteration and consumption of elements multiple times.
With Stream API we can consume or iterate elements only once.
It helps in using data in a declarative way. We can make use of Database functions like Max, Min etc., without
running a full iteration.
It makes good use of multi-core architectures without worrying about multi-threading code.
We can create a pipeline of data operations with Java Stream that can run in a sequence or in parallel.
It provides support for group by, order by etc. operations.
It supports writing for code in Functional programming style.
It provides parallel processing of data.
Main differences between Intermediate and Terminal Stream operations are as follows:
Evaluation: Intermediate operations are not evaluated until we chain it with a Terminal Operation of Stream.
Terminal Operations can be independently evaluated.
Output: The output of Intermediate Operations is another Stream. The output of Terminal Operations is not a
Stream.
Lazy: Intermediate Operations are evaluated in lazy manner. Terminal Operations are evaluated in eager manner.
Chaining: We can chain multiple Intermediate Operations in a Stream. Terminal Operations cannot be chained
multiple times.
Multiple: There can be multiple Intermediate operations in a Stream operation. There can be only one Terminal
operation in Stream processing statement.
A Spliterator is a special type of Iterator to traverse and partition the elements of a source in Java. A source can
be a collection, an IO channel or a generator function.
Spliterator can be used with Streams in Java 8. Where as, Iterator is just used with Collection.
Spliterator uses Internal Iteration to iterate Streams. Iterator uses External Iteration to iterate Collections.
Spliterator can iterate Streams in Parallel as well as Sequential manner. Iterator only iterates in Sequential manner.
Spliterator can traverse elements individually as well as in bulk. Iterator only iterates elements individually.
A Java compiler can see each method’s invocation and it declaration to determine what are type arguments
required for invocation.
By Type Inference, Java can determine the types of the arguments as well as the type of the result being returned.
Type inference algorithm also tries to find the most specific type that can work with all types of arguments.
Yes, Java 7 supports Type Inference. In Java 8, Oracle has enhanced the Type Inference concept. Now it can be
used to define Lambda expressions, functions and Method references.
In an Iterator, the fundamental question is that which party controls the iteration. Is it Iterator or the Collection
on which iterator runs.
When a Collection controls the iterator, then it is called External Iteration. When the Iterator controls the iteration
then it is called Internal Iteration.
In case of Internal Iteration, the client hands over an operation to Iterator and the Iterator applies the operation to
all the elements in aggregate.
Internal Iteration is easier to implement, since the Iterator does not have to store the state of the collection.
What are the main differences between Internal and External Iterator?
An Internal Iterator controls the iteration itself. In an External Iterator collection controls the iteration.
Internal Iterator can iterate elements in individually as well as in
Bulk (like forEach). External iterator iterates element one by one.
Internal Iterator does not have to iterate elements only sequentially. External Iterator always iterates sequentially.
Internal Iterator supports declarative programming style that goes well with functional programming. External
Iterator follows imperative style OOPS programming.
Some people consider Internal Iterator code more readable than that of External Iterator.
What are the main advantages of Internal Iterator over External Iterator in Java 8?
We need Internal Iterator in applications that require high performance, parallel processing, fast iteration and bulk
operations support.
Also in Internal Iteration applications, we do not have much control over iteration. The other features like parallel
processing etc. become more important.
Internal Iteration has many advantages over External Iteration. But it has one big disadvantage. Since Java API
is responsible for iterating in Internal iterator, developer does not get any control over iteration.
Java 8 has introduced the flexibility of providing implementation of a method in an interface. There are two
options for that:
In Java 8, we can provide implementation of a method in an Interface and mark this method with Default keyword.
In this way, this implementation of the method becomes default behavior for any class implementing the interface.
Let say there is an interface Car that is implemented by BMW, Chevrolet and Toyota classes. Now a Car needs
to add capability for flying. It will require change in Car interface. Some of the car classes that do not have flying
capability may fail. Therefore a Default Implementation of flying methods is added in Car interface so that cars
with no flying capability can continue to implement the original Car interface.
A Static method in an Interface is utility or helper method. This is not an object level instance method. Some of
the uses of Static method in an Interface are:
Single Class: There is no need to create a separate Utils class for storing utility or helper methods. We can keep
these methods in same interface.
Encapsulation: With Static methods, complete behavior of a Class is encapsulated in same class. There is no need
to maintain multiple classes.
Extension: It is easier to extend a Class/API. If we extend a collection ArrayList, we get all the methods. We need
not extend Collections class also.
What are the core ideas behind the Date/Time API of Java 8?
There are three core ideas behind the Date/Time API of Java 8:
Immutable-value classes: The new API avoids threadsafety and concurrency issues by ensuring that all the core
classes are immutable and represent well-defined values.
Domain-driven design: The new API is modeled on precise domain with classes that represent different use cases
for Date and Time.
The emphasis on domain-driven design offers benefits like clarity and understandability.
Separation of chronologies: The new API allows people to work with different calendar systems. It supports the
needs of users in different areas of the world likes Japan or Thailand that don’t follow ISO-8601.
What are the advantages of new Date and Time API in Java 8 over old Date API?
Some of the advantages of Java 8 Date Time API over existing Date API are:
Concurrency: Existing Date Time classes (such as java.util.Date and SimpleDateFormatter) are not thread-safe.
This does not work well in concurrent applications. In new Date Time API, developer does not have to deal with
concurrency issues while writing datehandling code.
Better Design: Date/Time classes prior to Java 8 have poor API design. For example, years in java.util.Date start
at 1900, months start at 1, and days start at 0. It is not very intuitive. Java 8 Date Time API handles it very well.
What are the main differences between legacy Date/Time API in Java and Date/Time API of Java 8?
Main difference between legacy Date/Time API and Java 8 Date/Time API are:
In Java8, we have a new class Duration that provides the utility of computing duration between two dates.
We can call the static method Duration.between(date1, date2) to get the time period in hours, mins, days etc.
between date1 and date2.
What is the new method family introduced in Java 8 for processing of Arrays on multi core machines?
Java 8 has enhanced the Arrays class with methods that can run efficiently on multi core machines.
This parallel set of methods provides parallel processing of Arrays that can run Java code very fast on a multi
core machine.
In Multiple Inheritance if a class extends more than one classes with two different implementation of same method
then it causes Diamond problem.
Consider following example to see problem and solution for Diamond problem in Java 8:
In the above code, class ChildClass gives compile time error. Java Compiler cannot decide which display method
should it invoke in ChildClass.
The method invocation at BaseOne.super.display(); solves the Diamond problem as it resolves the confusion for
compiler.
What are the differences between Predicate, Supplier and Consumer in Java 8?
The subtle difference between Predicate, Supplier and Consumer in Java 8 is as follows:
Predicate is an anonymous function that accepts one argument and returns a result.
Supplier is an anonymous function that accepts no argument and returns a result.
Consumer is an anonymous function that accepts one argument and returns no result.
Is it possible to have default method definition in an interface without marking it with default keyword?
No, we have to always mark a default method in interface with default keyword.
If we create a method with implementation in an interface, but do not mark it as default, then we will get compile
time error.
Can we create a class that implements two Interfaces with default methods of same name and signature?
No, it is not allowed to create a class that implements interfaces with same name default methods.
In Multiple Inheritance a class can inherit behavior from more than one parent classes.
Prior to Java 8, a class can implement multiple interfaces but extend only one class.
In Java 8, we can have method implementation within an interface. So an interface behaves like an Abstract class.
Now if we implement more than one interface with method implementation in a class, it means we are inheriting
behavior from multiple abstract classes. That is how we get Multiple Inheritance in Java 8.
In case we create a class that extends a base class and implements an interface. If both base class and
interface have a default method with same name and arguments, then
which definition will be picked by
JVM?
If we create same method and define it in a class , in its parent class and in an interface implemented by
the class, then definition will be invoked if we access it using the reference of Interface and the object of
class?
No, a static method of interface has to be invoked by using the name of the interface.
How can you get the name of Parameter in Java by using reflection?
Java 8 has introduced a method Parameter.getName() to get the name of a parameter by using reflection.
Before using this feature, we need to turn on this feature in Java compiler.
To turn on this feature, just run javac with –parameters argument.
To verify the availability of this feature, we can use Parameter. isNamePresent() method.
Optional is a container object that may have a null or non-null value. If it has a value then isPresent() method
returns true.
It a value is present, we can call get() method to get the value. Else we will get nothing.
Which method in Optional provides the fallback mechanism in case of null value?
In case, an Optional has null value, we can use orElseGet() method as fallback mechanism. If we implement
orElseGet() method, it will be invoked when the value of Optional is null.
In Java 8 we can use Clock class to get the current time. Instead of using old method System.currentTimeMillis(),
we can create a Clock object and call millis() method to get the current time in milliseconds.
We can also call instant() method on Clock object to get the current time in a readable format.
Java 8 comes with a new command line tool jdeps that can help in analyzing the package-level and class-level
dependencies.
We can pass a jar file name or a class name as an argument to this tool. It will list all the dependencies of that jar
or class.
What are the new JVM arguments introduced by Java 8?
In Java 8, PermGen space of ClassLoader is removed. It has been replaced with MetaSpace.
The JVM options -XX:PermSize and –XX:MaxPermSize are replaced by -XX:MetaSpaceSize and -
XX:MaxMetaspaceSize respectively in Java 8.
@FunctionalInterface: This annotation is used to mark an interface as Functional Interface. As mentioned earlier,
A FunctionalInterface can be used for lambda expressions.
@Repeatable: This annotation is used for marking another annotation. It indicates that the marked annotation can
be applied multiple times on a type.
StringJoiner is a new class in Java 8 that can be used to create a String. It can construct a sequence of characters
separated by a delimiter. It can also optionally add a prefix and suffix to this sequence. We can use this sequence
to get a String.
E.g.
The String "[One:Two:Three]" may be constructed as follows:
A lambda is like a method reference. It does not have a type of its own.
The target type of a lambda expression represents a type to which the expression can be converted.
The lambda expression must have same parameter type as the parameter in the function of the interface. It must
also return a type compatible with the return type of function.
What are the main differences between an interface with default method and an abstract class in Java 8?
An interface with a default method appears same as an Abstract class in Java. But there are subtle differences
between two.
Instance variable: An interface cannot have instance variables. An abstract class can have instance variables.
Constructor: An interface cannot have a constructor. An abstract class can have constructor.
Concrete Method: An interface cannot have concrete methods other than default method. An abstract class is
allowed to define concrete methods with implementation.
Lambda: An interface with exactly one default method can be used for lambda expression. An abstract class
cannot be used for lambda expression.
When we add two integral variables e.g. variables of type byte, short, or int in Java, then they are first promoted
to int type, and then addition happens.
The += operator implicitly casts the result of addition into the type of variable used to hold the result.
What happens when you put return statement or System.exit () on try or catch block? Will finally block execute?
It is a popular tricky Java interview question. Most of the programmers think that no matter what the finally block
will always execute. This question challenges that concept by putting a return statement in the try or catch block
or calling System.exit() from try or catch block.
You can answer by saying that finally block executes even if we put a return statement in the try block or catch
block. But finally block does not execute if you call System.exit() from try or catch block.
What does the expression 1.0 / 0.0 return? Will there be any compilation error?
Double class is the source of many tricky interview questions. You may know about the double primitive type
and Double class. But while doing floating point arithmetic some people don't pay enough attention to
Double.INFINITY, NaN, and -0.0. There are rules that govern the floating point arithmetic calculations involving
Double.
The answer to this question is that 1.0 / 0.0 will compile successfully. And it will not throw ArithmeticException.
It will just return Double.INFINITY.
.
Can we use multiple main methods in multiple classes?
Yes. When we start an application in Java, we just mention the class name to be run to java command. The JVM
looks for the main method only in the class whose name is passed to java command. Therefore, there is no conflict
amongst the multiple classes having main method.
The question is tricky but the answer is very simple. You cannot override a private or static method in Java. If we
create a similar method with same return type and same method arguments in child class, then it will hide the
superclass method. This is known as method hiding.
Also, you cannot override a private method in sub class because Private method is not visible even in a subclass.
Therefore, what you can do is to create another private method with the same name in the child class.
So in both the cases, it is not method overriding. It is either method hiding or a new method.
What happens when you put a key object in a HashMap that is already present?
In a HashMap there are buckets in which objects are stored. Key objects with same HashCode go to same bucket.
If you put the same key again in a HashMap, then it will replace the old mapping because HashMap doesn't allow
duplicate keys. The same key will have same HashCode as previous key object. Due to same HashCode, it will
be stored at the same position in the bucket.
How can you make sure that N threads can access N resources without deadlock?
This question checks your knowledge of writing multi-threading code. If you have experience with deadlock and
race conditions, you can easily answer this.
The answer is that by resource ordering you can prevent deadlock. If in our program we always acquire resources
in a particular order and release resources in the reverse order, then we can prevent the deadlock.
So a thread waiting for same resource can not get into deadlock while the other thread is trying to get it and
holding the resource required by first thread. If both of them release the resources in right order, one of them can
acquire it to finish the work.
How can you determine if JVM is 32-bit or 64-bit from Java Program?
We can find JVM bit size 32 bit or 64 bit by running java command from the command prompt.
Sun has a Java System property to determine the bit size of the JVM: 32 or 64:
What is the right data type to represent Money (like Dollar/Pound) in Java?
To represent money you need decimal points in the numbers like $1.99.
BigDecimal class provides good methods to represent Money. Using BigDecimal, we can do the calculation with
decimal points and correct rounding. But using BigDecimal is a little bit high on memory usage.
We can also use double with predefined precision. But calculation on double can give erroneous results.
But in Java 8, the default method breaks the rule of multiple inheritances behavior.
No, ++ operator is not a thread safe operation. It involves multiple instructions like- reading a value, incrementing
it and storing it back into memory. These instructions can overlap between multiple threads. So it can cause issues
in multi-threading.
How can you access a nonstatic variable from the static context?
We cannot access a non-static variable from the static context in Java. If you write a code like that, then you will
get compile time error. It is one of the most common problems for beginner Java programmers, when they try to
access instance variable inside the main method in a class.
Since main method is static in Java, and instance variables are nonstatic, we cannot access instance variable inside
main. The solution is to create an instance of the object and then access the instance variables.
Let say there is a method that throws NullPointerException in the superclass. Can we override it with a
method that throws RuntimeException?
This question is checking your understanding of the concepts of method overloading and overriding in Java.
We can throw superclass of RuntimeException in an overridden method, but we cannot do the same if it is a
checked Exception.
We can mark an array volatile in Java. But it makes only the reference to array volatile, not the whole array.
If one thread changes the reference variable to point to another array, then it will provide a volatile guarantee.
But if multiple threads are changing individual array elements, they won't be having same reference due to the
reference itself being volatile.
Thread-local variable is a variable restricted to a specific thread. It is like thread's own copy of variable that is not
shared among multiple threads.
Java provides ThreadLocal class to support thread-local variables. To achieve thread-safety, you can use it. To
avoid any memory leak, it is always good to remove a thread-local variable, once its work is done.
sleep() is actually meant for short pause because it doesn't release lock.
wait() is meant for conditional wait and it can release a lock that can be acquired by another thread to change the
condition on which it is waiting.
Can you create an Immutable object that contains a mutable object?
We should not share the reference of the mutable object, since it is inside an immutable object. Instead, we can
return a copy of it to other methods.
You can convert an Array of bytes to String object by using the String constructor that accepts byte[]. We need
to make sure that right character encoding is used. Else we may get different results after conversion.
We can reuse CyclicBarrier even if it is broken, but we cannot reuse CountDownLatch in Java.
StringBuilder was introduced in Java 5. The main difference between both of them is that StringBuffer methods
e.g. length(), capacity(), append() are synchronized. But corresponding methods in StringBuilder are not
synchronized.
Due to this difference, concatenation of String using StringBuilder is faster than StringBuffer. Now it is
considered bad practice to use StringBuffer, because, in most of the scenarios, we perform string concatenation
in the same thread.
It is a very basic trick question. clone() method is defined in Object class. Cloneable is a marker interface that
doesn't contain any method.
In Linux/Unix, just use kill -3 PID, where PID is the process id of Java process. It will give the thread dump of
Java process.
In Windows, press Ctrl + Break. This will instruct JVM to print thread dump in standard out or err. It can also go
to console or log file depending upon your application configuration.
Can you cast an int variable into a byte variable? What happens if the value of int is larger than byte?
An int is 32 bit in Java. But a byte is just 8 bit in Java. We can cast an int to byte. But we will lose higher 24 bits
of int while casting. Because a byte can hold only first 8 bits of int. Remaining 24 bits (32-8 = 24) will be lost.
In Java, can we store a double value in a long variable without explicit casting?
No, we cannot store a double value into a long variable without casting it to long. The range of double is more
than that of long. So we need to type cast.
To answer this question, just remember which one is bigger between double and long in Java.
The answer is false because floating point numbers can not be represented exactly in Java, so 5*0.1 is not same
as 0.5.
An Integer object takes more memory than an int in Java. An Integer is an object and it stores meta-data overhead
about the object. An int is a primitive type so its takes less memory and there is no metadata overhead.
Yes. From Java 7 onwards, String can be used in switch case statement. This gives convenience to programmer.
But internally hash code of String is used for the switch statement.
Yes. You can have multiple methods with name main in the same class. But there should be only one main method
with the signature public static void main(String[] args). JVM looks for main with this signature only. Other
methods with name main in same class are just ignored.
When creating an abstract class, is it a good idea to call abstract methods inside its constructor?
No, we should avoid calling abstract methods in the constructor of an abstract class. Because, it can restrict how
these abstract methods can be implemented by child classes.
Many IDE give “Overridable method call in constructor” warning for such implementation.
This is a problem of object initialization order. The superclass constructor will run before the child class
constructor. It means child class is not yet initialized. But due to presence of overridden method in superclass,
the overridden method of subclass is called when the subclass is not fully initialized.
When we call one constructor from another constructor of the same class, then it is known as constructor chaining
in Java. When you have multiple overloaded constructors in a class, you can do constructor chaining.
How can we find the memory usage of JVM from Java code?
We can use memory management related methods provided in java.lang.Runtime class to get the free memory,
total memory and maximum heap memory in Java.
By using these methods, you can find out how much of the heap is used and how much heap space still remains.
The x.equals(y) expression is used for logical mapping and it is expected from an object to override this method
to provide logical equality.
Eg. A Book object may be logically equal to another copy of same Book, but it is a different object which will be
false while doing x == y.
How can you guarantee that the garbage collection takes place?
No. We cannot guarantee the garbage collection in Java. Java documentation explicitly says that
GarbageCollection is not guaranteed.
You can call System.gc() to request garbage collection, however, that's what it is - a request. It is upto GC's
discretion to run.
What is the relation between x.hashCode() method and x.equals(y) method of Object class?
It is used in hashCode based collection classes like Hashtable, HashMap, LinkedHashMap etc.
As per Java specification, two objects which are equal to each other using equals() method must have same hash
code.
Therefore, two objects with same hashCode may or may not be equal to each other. But two equal objects should
have same hash code.
A compile time constant is public static final variable. The public modifier is optional here. At compile time, they
are replaced with actual values because compiler knows their value up-front and it also knows that it cannot be
changed during run-time. So they are constants.
The main difference between fail-fast and fail-safe iterators is whether or not the collection can be modified while
it is being iterated.
Fail-safe iterators allow modification of collection in an iteration task. But fail-fast iterators do not allow any
modification to collection during iteration.
During iteration, fail-fast iterators fail as soon as they realize that the collection has been modified. Modification
can be addition, removal or update of a member. And it will throw a
ConcurrentModificationException.
Eg. ArrayList, HashSet, and HashMap are fail-fast.
Fail-safe iterators operate on a copy of the collection. Therefore they do not throw an exception if the collection
is modified during iteration.
Eg. ConcurrentHashMap, CopyOnWriteArrayList are fail-safe.
You have a character array and a String. Which one is more secure to store sensitive data (like password,
date of birth, etc.)?
In Java, String is immutable and it is stored in the String pool. Once a String is created, it stays in the pool in
memory until it is garbage collected. You have no control on garbage collection. Therefore, anyone having access
to a memory dump can potentially extract the sensitive data and use it.
Whereas, if you use a mutable object like a character array, to store the value, you can set it to blank once you
are done with it. Once it is made blank it cannot be used by anyone else.
The volatile keyword guarantees global ordering on reads and writes to a variable. This implies that every thread
accessing a volatile field will read the variable’s current value instead of using a cached value.
By marking the variable volatile, the value of a variable is never cached thread-locally. All reads and writes will
go straight to main memory of Java.
What is the difference between poll() and remove() methods of Queue in Java?
It is a basic question to know the understanding of Queue data structure. Both poll() and remove() methods remove
and return the head of the Queue.
When Queue is empty, poll() method fails and it returns null, but remove() method fails and throws Exception.
Java Documentation says “When a thread is about to terminate due to an uncaught exception the Java Virtual
Machine will query the thread for
its UncaughtExceptionHandler usingThread.getUncaughtExceptionHa will invoke the handler's
uncaughtException method, passing the thread and the exception as arguments.”
How do you decide which type of Inner Class – Static or Non-Static to use in Java?
An inner class has full access to the fields and methods of the enclosing class. This is convenient for event
handlers, but comes at a cost. Every instance of an inner class retains and requires a reference to its enclosing
class.
Due to this cost, there are many situations where static nested classes are preferred over inner classes. When
instances of the nested class outlive instances of the enclosing class, the nested class should be static to prevent
memory leaks.
At times, due to their “hidden” reference to enclosing class, Inner classes are harder to construct via reflection.
When the JVM is started, three types of class loaders are used:
Bootstrap Classloader: It loads core java API file rt.jar classesfrom folder.
Extension Classloader: It loads jar files from lib/ext folder.
System/Application Classloader: It loads jar files from path specified in the CLASSPATH environment variable.
Classes may be loaded from the local file system, a remote file system, or even the web.
HashSet is better than TressSet in almost every way. It gives O(1) for add(), remove() and contains() operations.
Whereas, TressSet gives O(log(N)) for these operations.
Still, TreeSet is useful when you wish to maintain order over the inserted elements or query for a range of elements
within the set.
We should use TreeSet when we want to maintain order. Or when there are enough read operations to offset the
increased cost of write operations.
Java 8 has introduced Method references. It allows constructors and methods to be used as lambdas.
The main uses of Method reference are to improve code organization, clarity and terseness.
Do you think Java Enums are more powerful than integer constants?
Yes. Java Enums provide many features that integer constants cannot. Enums can be considered as final classes
with a fixed number of instances. Enums can implement interfaces but cannot extend another class.
While implementing the strategy pattern, we can use this feature of Enums. Especially, when the number of
strategies is fixed.
You can also attach meta-data to enum values in Java. Also enum values are typesafe, where as integer constants
are not.
In Java, a static initializer can run code during the initial loading of a class and it guarantees that this code will
only run once. Also the static code will finish running before a class can be accessed in any way.
Initializing static members from constructors is more work. You have to make sure that every constructor does
this. You need to maintain a flag to mark the static work when it is done. You may have to think about
synchronization or races conditions for work in static block not initialized from static context.
Your client is complaining that your code is throwing NoClassDefFoundError or NoSuchMethodError,
even though you are able to compile your code without error and method exists in your code. What could
be the reason behind this?
Sometimes we upgrade our libraries even with same method name. But we forget to let the client know about the
new version. Due this different in version, we get NoClassDefFoundError or NoSuchMethodError at runtime
when one library was not compatible with such an upgrade.
Java build tools and IDEs can also produce dependency reports that tell you which libraries depend on that JAR.
Mostly, identifying and upgrading the library that depends on the older JAR resolve the issue.
A numeric String can only contain digits i.e. 0 to 9. It can also contain + and - sign at start of the String. We can
create a regular expression for these two rules. One simple example is as follows:
What is the difference between the expressions String s = "Temporary" and String s = new
String("Temporary ")? Which one is better and more efficient?
In general, String s = " Temporary " is more efficient to use than String s = new String("Temporary ").
In case of String s = " Temporary ", a String with the value “Temporary” is created in String pool. If another
String with the same value is created (e.g., String s2 = " Temporary "), it will reference the same object in the
String pool.
But, when you use String s = new String("Temporary "), Java creates a String with the value “Temporary” in the
String pool. Also, that String object is then passed to the constructor of the String Object i.e. new
String("Temporary "). And this call creates another String object (not in the String pool) with that value.
Therefore, each such call creates an additional String object. E.g. String s2 = new String("Temporary ") creates
an extra String object, rather than just reusing the same String object from the String pool.
In Java, can two equal objects have the different hash code?
No. It is not possible for two equal objects to have different hashcode. But two objects with same hashcode may
or may not be equal.
Since array doesn't implement toString() method by itself, just passing an array to System.out.println() will not
print its contents. But we can use Arrays.toString() to print each element of an array.
Between two types of dependency injections, constructor injection and setter dependency injection, which
one is better?
Constructor injection guarantees that a class will be initialized with all its dependencies during creation. But setter
injection provides flexibility to set an optional dependency.
If we are using an XML file to describe dependencies, the setter injection is more readable.
In general, it is a good practice to use constructor injection for mandatory dependencies and use setter injection
for optional dependencies.
In Java, Document Object Model (DOM) parser loads the whole XML into memory and creates a tree based on
DOM model. This helps it in quickly locating the nodes, and making a change in the structure of XML.
On the other hand, Simple API for XML (SAX) parser is an event based parser. It doesn't load the whole XML
into memory. Due to this reason DOM is faster than SAX but require more memory and is not suitable to parse
large XML files.
Between Enumeration and Iterator, which one has better performance in Java?
Enumeration interface is a read-only interface. It has better performance than Iterator. It is almost twice as fast as
compared to an Iterator. It also uses very less memory. Also Enumeration does not have remove() method.
On the other hand, Iterator interface is safer than Enumeration, since it can check whether a collection is modified
or not during iteration. If a collection is altered while an Iterator is iterating, then it throws
ConcurrentModificationException.
Whenever an object is passed by value, it means that a copy of the object is passed. Even if changes are made to
that object, it doesn’t affect the original value.
Whenever an object is passed by reference, it means that the actual object is not passed, rather a reference of the
object is passed. Therefore, any changes made by an external method, are also reflected in the actual object and
its reference.
The other way is to use a Sorted collection like TreeSet or TreeMap that stores the information in a sorted order
and then you can convert it to a List.
Why Collection interface doesn’t extend Cloneable and Serializable interfaces?
Collection interface just specifies groups of objects known as elements. Each concrete implementation of a
Collection can choose its own way of how to maintain and order its elements.
Some collections may allow duplicate keys, while other collections may not.
A lot of collection implementations have clone method. But many do not. It is not worthwhile to include it in all,
since Collection is an abstract representation. What matters is the concrete implementation.
Cloning and serialization come into picture while doing concrete implementation. Therefore, the concrete
implementations of collections should decide how they can be cloned or serialized.
A process may contain multiple threads. A Thread is also called as a lightweight process.
What are the benefits of using an unordered array over an ordered array?
In an ordered array the search time has time complexity of O(log n).
Whereas, in an unordered array, search time complexity is O (n).
In an ordered array, the insert operation has a time complexity of O(n). Whereas, the insertion operation for an
unordered array takes constant time of O(1).
Therefore, when we have more writes than reads, it is preferable to use an unordered array.
A HashSet is Implemented using a HashTable. Therefore, its elements are stored in a random order. The add(),
remove(), and contains() methods of a HashSet have constant time complexity O(1).
A TreeSet is implemented using a tree data structure. The elements in a TreeSet are sorted in a natural order.
Therefore, add(), remove(), and contains() methods have time complexity of O(logn).
So from performance perspective, HashSet has better performance than TreeSet. But if you want to store elements
in a natural sorting order, then TreeSet is a better collection.
JVM instructs the Garbage Collector to call the finalize method, just before releasing an object from the memory.
A programmer can implement finalize() method to explicitly release the resources held by the object. This will
help in better memory management and avoid any memory leaks.
When would you use Serial Garabage collector or Throughput Garbage collector in Java?
The Serial Garbage collector is used for small applications that require heap memory upto 100 MB.
The Throughput Garbage collector is used in medium to large size Java applications.
In Java, if you set an object reference to null, will the Garbage Collector immediately free the memory held
by that object?
No. JVM decides to run the Garbage Collector whenever it is low on memory. When Garbage Collector runs, it
looks for objects that are available for garbage collection and then frees the memory associated with this object.
So just setting an Object reference null makes it eligible for Garbage Collection, but it does not immediately free
the memory.
How can you make an Object eligible for Garbage collection in Java?
To make an Object eligible for Garbage collection, just make sure that it is unreachable to the program in which
it is currently defined / created / used. You can set the object reference to null and make sure no other object
refers it. Once the object cannot be reached, Garbage Collection can clean it during the next run.
When do you use Exception or Error in Java? What is the difference between these two?
Throwable class is the superclass of Exception and Error classes in Java.
When you want to catch the exceptional conditions that your program can create or encounter, then use the
Exception class or subclass of Exception.
When you come across situations that are unexpected then use Error class in Java. Also recovering from Error is
not possible in most of cases. So it is better to terminate the program.
PreparedStatements are precompiled statements for database queries. Due to this their performance is much better.
Also, we can reuse PreparedStatement objects with different input values to the same query.
When we want to raise an exception in our code, we use the throw keyword with the name of the exception to be
raised.
Where as, throws keyword is used in method declaration. Throws keyword tells us the Exception that can be
thrown by this method. Any caller of this method should be prepared to expect this Exception.
Another minor difference is that throw is used only with one exception, but throws can be used with comma-
separated list of multiple exceptions.
What happens to the Exception object after the exception handling is done?
Once the exception handling is complete, the Exception object is not reachable. Then it is garbage collected in
the next run of Garbage Collector.
How do you find which client machine is sending request to your servlet in Java?
We can use the ServletRequest class to find the IP address or host name of the client machine.
There are methods getRemoteAddr() to get the IP address of the client machine and getRemoteHost() to get the
host name of the client machine.
Both Cookie and Session are used during communication between Client and Server. The Client can disable a
Cookie. Due to which the Web server cannot send a cookie. But a client cannot disable a session. So a Session
always works irrespective of any setting at the client side.
Also a Session can store any Java object. But the Cookie can only store small information in a String object.
Which protocol does Browser and Servlet use to communicate with each other?
HTTP protocol. The Browser and Servlet communicate with each other by using the HTTP protocol.
There are many network communication protocols on the Internet. But HTTP is the most popular among them.
HTTP Tunneling is a technique in which HTTP or HTTPS protocol encapsulated the communication done by
any other type of protocol. The masking of other protocol requests as HTTP requests is known as HTTP
Tunneling.
Since JSP pages are dynamically compiled into servlets, the programmers can easily make updates to the
presentation layer code.
Also JSP pages provide flexibility to combine static templates like HTML or XML snippets.
In addition, programmers can make logic changes at the class level, without editing the JSP pages that use the
class logic.
Yes. You can create a class and store it in a file with name .java. You can try it yourself, by creating, compiling
and running such a file. It will run correctly.
To implement, Servlet Chaining, there has to be more than one servlet. The output of one servlet has to be sent
to a second servlet. The output of the second servlet can be sent to a third servlet, and so on. In this way, a chain
of servlets is formed to complete a task.
The last servlet in the chain will be responsible for sending final response to client.
public class A {
A a = new A();
}
No, this class cannot be instantiated, since it will result in recursively calling its constructor.
Java supports Method overloading but does not support operator overloading. It would make the design more
complex by adding operator loading. Also it will make more complex compiler.
One more reason is that, it will reduce the performance of JVM by operator overloading, since JCM has to do
extra work to find the real meaning of overloaded operators at run time.
Since String objects are cached in a String pool, it makes sense to make the String immutable. The cached String
literals are shared between multiple clients. And there is a possibility that one client's action may affect another
client’s access to String pool.
String is also used as a parameter in many Java classes. Eg. You can pass hostname, port number as String while
opening a network connection. If any one can modify your copy of the String, it can change the hostname. Due
to this reason, it makes sense to make String final as soon as it is created.
When you use sendRedirect method, it creates a new request. When you use the forward method, it just forwards
a request to a new target.
In case of sendRedirect, the previous request scope objects are not available, because it creates a new request.
In case of forward method, the previous request scope objects are available after forwarding.
Also the sendRedirect method is considered slower than the forward method.
How do you fix your Serializable class, if it contains a member that is not serializable?
If you want to make a class Serializable, but find that this class contains members that are not Serializable, then
you have to mark those members as transient. This will ensure that this member is not persisted to a stream of
bytes during Serialization.
During the run time the behavior of an Object can change based on its run time state. Due to this run time
polymorphism is introduced in Java. If you override a method in a child class, then you are providing run time
polymorphism. Nothing will happen at the compile time. But at the run time, JVM decides which method will be
called based on the class of the Object.
What are the rules of method overloading and method overriding in Java?
When we want to overload a method, we need to make sure that the method name remains same. But method
signature can vary in the number or datatype of arguments or in the order of arguments.
When we want to override a method, we ensure that the method is not throwing checked exceptions that are new
or higher than those declared by the overridden method. Also we make sure that the method name, arguments
and return type remain the same.
A Class is a template or a blue print of an Object to be created. An Object is an instance of a Class. A Class
defines the methods and member variables. But an Object populates the values of the member variables.
Therefore a class is a blueprint that you use to create objects. An object is an instance of a class – it is a concrete
'thing' that you made using a specific class.
Most of the OOPS concepts are valid only when an Object is created.
Yes. An abstract class can extend another abstract class. It does not need to define the methods of parent abstract
class. Only the last non-abstract class has to define the abstract methods of a parent abstract class.
When we want to cast a Super class to Sub class, we use Downcasting. It is also known as narrowing.
At times, Downcasting can throw the ClassCastException if it fails the type check.
As the name suggests, a package contains a collection of classes. It helps in setting the category of a file. Like-
whether it is a Data Access Object (DAO) or an API.
Also we can introduce access restriction by using package and the right modifiers on a class and its methods.
Information hiding is OOPS concept. In Java you can use encapsulation to do Information hiding. An object can
use the access modifiers like-public, private, protected to hide its internal details from another object. This helps
in decoupling the internal logic of an object from outside world.
By using Information hiding, an object can change its internal implementation without impacting the outside
calling client’s code.
In Java all the interaction takes place between Object instances. To create an Object instance, JVM needs a
constructor. Java does not enforce the rule on a programmer to define a default constructor for every class.
Whenever an object has to be created and programmer has not provided a constructor, Java uses default
constructor to create the object. Default constructor also initializes member variables with their default values.
We use super keyword to access the methods of the super class from child class.
Most of the modern technologies, websites and browsers support these Unicode characters.
Yes. Java allows to override an overloaded method, if that method is not a static or final method.
Java provides the command line parameters to set the heap size for
JVM.
You can specify the values in –Xms and –Xmx parameters. These parameters stand for initial and maximum heap
size of JVM.
In general, Java provides a default constructor with each class. But there are certain cases when we want to define
our own version of default constructor.
When we want to construct an object with default values, we create our default constructor.
At times, we can mark the default constructor private. So that any other class cannot create an instance of our
class. This technique is generally used in Singleton design pattern.
To make an object immutable follow these two rules. One, do not use any setter methods that can change the
fields of your class. Two, make the fields final. By following these rules, the member variables cannot be changed
after initialization. This will ensure that member variables of an Object do not change. And thus the Object will
be considered Immutable.
How can you prevent SQL Injection in Java Code?
In Java, you can use PreparedStatement to prevent SQL injection. In a PreparedStatement you can pass the
precompiled SQL queries with pre-defined parameters. This helps in checking the type of parameters to SQL
queries. So it protects your code from SQL injection attacks.
Any object that we want to use as key for HashMap or in any other hash based collection data structure e.g.
Hashtable, or ConcurrentHashMap must implement equals() and hashCode() method.
The Key object should be immutable so that hashCode() method always return the same value for that object.
The Hashcode returned by hashCode() method depends on values of member variables of an object. If an object
is mutable, then the member variables can change. Once the member variables change, the Hashcode changes. If
the same object returns different hash code at different times, then it is not reliable to be used in the HashMap.
Let say, when you insert the object, the Hashcode is X, the HashMap will store it in bucket X. But when you
search for it the Hashcode is Y, then HashMap will look for the object in bucket Y. So you are not getting what
you stored.
Although, the compiler does not enforce this rule, a good programmer always remembers this rule.
There are many ways to share same object between multiple threads. You can use a BlockingQueue to pass an
object from one thread to another thread.
You can also use Exchanger class for this purpose. An Exchanger is a bidirectional form of a SynchronousQueue
in Java. You can use it to swap the objects as well.
If we suspect that our application is stuck due to a Deadlock, then we just take a thread dump by using the
command specific to environment in which your application is running. Eg. In Linux you can use command kill
-3.
In case of deadlock, you will see in thread dump the current status and stack trace of threads in the JVM, and one
or more of them will be stuck with message deadlock.
Also you can do this programmatically by using the ThreadMXBean class that ships with the JDK.
If you don't need programmatic detection you can do this via JConsole. On the thread tab there is a "detect
deadlock" button.
Mixed Questions
Java has concept of Wrapper classes to allow primitive types to be accessed as objects. Primitive types like
boolean, int, double, float etc. have corresponding Wrappers classes – Boolean, Integer, Double, Float etc.
Java 5.0 has launched the concept of Autoboxing and Unboxing in Java for Wrapper classes.
E.g.
The native keyword is used for applying to a method to indicate that the method is implemented in native code
using JNI(Java Native Interface).
Therefore, native methods allow Java Developer to directly access platform specific APIs.
System.class is a final class provided by java.lang package. It contains several useful class fields and methods.
Object Cloning. A Shallow Copy just copies the values of references in a Class.
What is the difference between Shallow Copy and Deep Copy in Java?
A Shallow copy just copies the values of the references in the class. A Deep copy copies the values of the objects
as well.
A Singleton class in Java has maximum one instance of the class present in JVM, all the time. The constructor of
this class is written in such a way that it never creates more than one object of same class.
A static class in Java has only static methods. It is a container of functions. It is created based on procedural
programming design.
Singleton class is a pattern in Object Oriented Design. A Singleton class has only one instance of an object in
JVM. This pattern is implemented in such a way that there is always only one instance of that class present in
JVM.
JSP
Request
Response
Application
Exception
Page
Config
Session
We can extend JSP code by using Tag libraries and Custom actions.
We use Errorpage attribute in JSP to catch runtime exceptions. This attribute forwards user request to the error
page automatically.
How will you prevent multiple submits of a page that come by clicking refresh button multiple times?
We can use Post Redirect Get (PRG) pattern to solve the issue of multiple submission of same data. It works as
follows:
First time when a user submits a form to server by POST or GET method, then we update the state in application
database.
Then we send a redirect response to send reply to client.
Then we load a view by using GET command. There is no data is sent in this. Since this a new JSP page, it is safe
from multiple submits. The code that processes the request is idempotent. So it does not do same action twice for
same request.
We can also add <%@page isThreadSafe=”false” %> directive in JSP page to make it thread safe.
We can use include directive of JSP to include a Static page in JSP. In this approach, we use translation phase to
include a static page. We have to specify the URL of the resource to be included as file attribute in this directive.
jspInit(): This method is invoked when the JSP is called for the first time. We can do initial setup for servicing a
request in this method.
jspDestroy(): Once we remove a JSP from the container, we call this method. It is used for cleanup of resources
like Database connections etc.
Performance: JSP provides very good performance due to their design of using same code to service multiple
requests.
Fast: Since JSP is pre-compiled, server can serve the pages very fast.
Extendable: JSP is based on Java Servlets. This helps in extending JSP architecture with other Java technologies
like JDBC, JMS, JNDI etc.
Design: It is easier to design user interface with JSP, since it is very close to HTML. UI designers can create a
JSP with mock data and developers can later provide implementation of dynamic data.
In JSP we can write Java code seamlessly. It allows for writing code that can interact with the rest of the
application.
Javascript code is mostly executed at client side. This limits the tasks that can be done in Javascript code. We
cannot connect to database server from Javascript at the client side.
Compilation: When a request is made for a JSP, the corresponding JSP is converted into Servlet and compiled.
If there is already a compiled form of JSP and there is not change in JSP page since last compilation, this stage
does not do anything.
Initialization: In this stage, jspInit() method is called to initialize any data or code that will be later used multiple
times in _jspService() method.
Service: In this stage, with each request to JSP, _jspService() method is called to service the request. This is the
core logic of JSP that generates response for request.
Destroy: In this stage, JSP is removed from the container/server. Just before removal, this stage performs the
cleanup of any resources held by JSP.
A JSP expression is an element of a JSP page that is used to evaluate a Java expression and convert into a String.
This String is replaced into the locations wherever the expression occurs in JSP page.
Page: This directive is used for page related attributes. It can be put anywhere in the JSP page. But by convention
we put it on the top of the page.
E.g.
<%@ page attribute="value" %>
Taglib: We can create custom tags in JSP and use these by taglib directive in a JSP page.
E.g.
<%@ taglib uri=“abc.html” prefix=“tag_prefix” >
Include: We use include directive to read a file and merge its content with the JSP page. This is done during
compilation stage.
Session attribute in JSP is used for HTTP session mechanism. If we do not want to use HTTP session in JSP, then
we set this attribute to false. If it is set to true, we can use built in session object in JSP.
What are the different scopes of a JSP object?
A JSP object, implicit or explicit, can have one of the following scopes:
Page: In this scope, the object is accessible from the page where it was created. Important point here is that when
a user refreshes the page, the objects of this scope also get created again.
Request: In request scope, the object is accessible to the HTTP request that created this object.
Session: In this scope, the object is available throughout the same HTTP session.
Application: This is the widest scope. The object is available throughout the application in which JSP was
created.
In JSP, pageContext is an implicit object. This is used for storing and accessing all the page scope objects of JSP.
We use jsp:useBean to invoke the methods of a Java Bean class. The Java Bean class has some data and
setter/getters to access the data.
With this tag, container will try to locate the bean. If bean is not already loaded then it will create an instance of
a bean and load it. Later this bean can be used in expressions or JSP code.
Some of the main differences between include Directive and include Action are as follows:
Include directive is called at translation phase to include content in JSP. Include Action is executed during runtime
of JSP.
It is not possible to pass parameters to include directive. Include action can accept parameters by jsp:param tag.
Include directive is just copying of content from another file to JSP code and then it goes through compilation.
Include action will dynamically process the resource being called and then include it in the JSP page.
How will you use other Java files of your application in JSP code?
We can use import tag to import a Java file in JSP code. Once a file is imported, it can be used by JSP code. It is
a very convenient method to use Java classes in JSP code.
For better organization of Java code, we should create a package of classes that we are planning to use in JSP
code.
How will you use an existing class and extend it to use in the JSP?
We can use extends attribute in include tag to use an existing class and extend it in the current JSP.
E.g. <%@ include page extends=“parent_class” %>
All the code that we write in a JSP goes into _jspService method during translation phase. We cannot override
this method. Where as other lifecycle methods jspInit() and jspDestroy() can be overridden.
It appears that container uses _ symbol to distinguish the method that cannot be overridden by client code.
At times we want to create a UI framework with custom tags. In such a scenario, taglib is a very good feature of
JSP. With taglib we can create tags that can provide custom features.
Taglib is also a nice way to communicate with UI designers who can use custom tags in the html without going
into the details of how the code is implemented.
Another benefit of taglib is reusability of the code. This promotes writing code only once and using is multiple
times.
JSTL stands for JavaServer Pages Standard Tag Library. In JSTL, we have a collection of JSP tags that can be
used in different scenarios. There are following main groups of tags in JSTL:
Core tags
SQL tags
Formatting tags
XML tags
JSTL Functions
How will you pass information from one JSP to another JSP?
We can pass information from one JSP to another by using implicit objects. If different JSP are called in same
session, we can use session object to pass information from one JSP to another.
If we want to pass information from one JSP to another JSP included in the main JSP, then we can use jsp:param
to pass this information.
JSP allows running Java code from a .jsp file. We can call a stored procedure by using JDBC code.
If we are using Spring framework, then we can use JdbcTemplate class to invoke stored procedure from a JSP.
No, JSP specification does not allow overriding of _jspService method in JSP. We can override other methods
like jspInit() and jspDestroy().
What is a directive in JSP?
JSP directive is a mechanism to pass message to JSP container. JSP directive does not produce an output to the
page. But it communicates with JSP container.
E.g. <%@include ..%> directive is used for telling JSP container to include the content of another file during
translation of JSP.
There can be zero or more attributes in a directive to pass additional information to JSP container.
Some of the important directives in JSP are: page, include and taglib.
We can use different mechanisms to implement Session tracking JSP. Some these mechanisms are as follows:
Cookies: We can use cookie to set session information and pass it to web client. In subsequent requests we can
use the information in cookie to track session.
Hidden Form Field: We can send session id in a hidden field in HTML form. By using this we can track session.
Session object: We can use the built in session object to track session in JSP.
Like- www.abcserver.com?sessionid=1234
Another option in debugging is to link JSP container with an IDE. Once we link IDE debugger to JSP Engine, we
can use standard operations of debugging like breakpoint, step through etc.
To implement an error-handling page in JSP, we first create a JSP with error page handling information. In most
of the cases we gracefully handle error by giving a user-friendly message like
“Sorry! There is system error. Please try again by refreshing page.”
In this error page, we show user-friendly message to user, but we also log important information like stack trace
to our application log file.
We have to add parameter isErrorPage=true in page directive of this page. This tells to JSP container that this is
our error page.
<%@page isErrorPage=”true” %>
Now we can use this error page in other JSP where we want to handle error. In case of an error or exception, these
JSP will direct it to errorPage.
In general, JSP is used to pass HTML data to web browser. If we want to send data in XML format, we can easily
do it by setting contentType=”text/xml” in page directive.
What happens when we request for a JSP page from web browser?
When a user calls JSP page from web browser, the request first comes to web server. Web server checks for .jsp
extension of page and passes the request to JSP container like Tomcat.
The JSP container checks whether it has precompiled JSP class or not. If this is the first time this JSP is called,
then JSP container will translate JSP into a servlet and compiles it.
After compiling, JSP code if loaded in memory and JSP container will call jspInit() method and _jspService()
methods.
The _jspService() method will create the output that will be sent by JSP container to client browser.
We can use setIntHeader() method to set the refresh frequency with which we want to auto-refresh a JSP page.
We can send key “Refresh” with the time in seconds for auto refresh of the JSP page.
E.g. response.setIntHeader(“Refresh”,10)
Every HTTP request comes back with a status code from the server. The important status codes in HTTP are as
follows:
In HTTP header, Accept attribute is used to specify the MIME types that a HTTP client or browser can handle.
MIME type is the identifier for specifying the type of file/data that we are planning to pass over the internet.
We use Expression in a JSP to return a value and display it at a specific location. It is generally used for
dynamically print information like- time, counter etc in a HTML code.
Scriptlet is for writing Java code in a JSP. We can define variable, methods etc in a Scriptlet. A Scriptlet can
handle much more complex code and can be also reused.
setMaxAge(): we can set the maximum age of a cookie. After this time period, Cookie will expire and will be
deleted.
Header: We can also set the expiry time in header of response. Respone.setHeader(). This will also expire the
cookie after specified time period.
First we create a Cookie object. We set the name and value of the cookie to be created.
We set the expiry time of the Cookie by setting the maximum age. We can use setMaxAge() method for this.
Finally, we can send the cookie in a HTTP Response by sending it in HTTP header. In this way cookie goes to
client browser and gets stored there till the maximum age is not achieved.
Once a Cookie is set in the client browser, we can call getCookies() method to get the list of all the cookies set in
Client. We iterate through the list of all the cookies and get the value of the cookie that was set in earlier request.
In this way we can use Cookie to set some information at client side and retrieve its value.
A Session is always stored at the Server side. In JSP, session is a built-in object in JSP container.
We can use both the methods for Session tracking. But Cookie method needs permission from user for storing
cookie at the client location.
We can write output in JSP in such a way that it becomes a comment in HTML code. This comment will not be
visible in the web browser. But when we view page source to see HTML, we can see output comment.
How will you prevent caching of HTML output by web browser in JSP?
We can use set the header in response object for Cache-Control to specify no caching.
How will you redirect request to another page in browser in JSP code?
We can use sendRedirect() method in JSP to redirect the request to another location or page.
In this case the request will not come back to server. It will redirect in the browser itself.
Both forward and sendRedirect are mechanisms of sending a client to another page. The main difference between
these two are as follows:
In forward, the processing takes place at server side. In case of sendRedirect() the processing takes place the client
side.
In forward, the request is transferred to another resource within same server. In case of sendRedirect the request
can be transferred to resource on some other server.
In forward only one request call is consumed. In case of sendRedirect two request response calls are created and
consumed.
We use init-param to specify the parameters that are specific to a servlet or jsp. This information is confined to
the scope of that JSP.
We use context-param to specify the parameters for overall application scope. This information does not change
easily. It can be used by all the JSP/Servlet in that Container.
We use RequestDispatcher interface to forward requests to other resources like HTML, JSP etc.
We have to first get the RequestDispatcher object from the container and then we can call include or forward
method on this object.
There is a built-in request object in a JSP that provides methods to read Form data. Some of the methods are as
follows::
getParameterNames(): This method returns the list of all the parameters in the Form.
getParameter(): We call this method to get the value of parameter set in the Form. It returns null if the parameter
is not found.
getParameterMap(): This method returns the map of all the Parameters in Form.
We can define filters in JSP to intercept requests from a client or to change response from a server.
Filter is a Java class that is defined in the deployment descriptor of web.xml of an application. The JSP container
reads filter from web.xml and applies a filter as per the URL pattern associated with the filter.
JSP Engine loads all the filters in when we start the server.
How can you upload a large file in JSP?
To upload a file by JSP we can use <input type=”file”> in the Form data being passed from HTML.
Once the request is received, we can implement the logic to read mulitpart data in doPost() method of JSP. There
are methods in JSP framework to read large files via this method.
To initialize multiple JSP objects, we have to specify same Servlet object multiple times in web.xml.
This indicates to JSP container to initialize separate JSP/Servlet object for each element. Each of the Servlet
instance will have its own ServletConfig object and parameters
Strategy pattern is very useful for implementing a family of algorithms. It is a behavioral design pattern.
With Strategy pattern we can select the algorithm at runtime. We can use it to select the sorting strategy for data.
We can use it to save files in different formats like- .txt, .csv, .jpg etc.
In Strategy pattern we create an abstraction, which is an interface through which clients interact with our system.
Behind the abstraction we create multiple implementation of same interface with different algorithms.
For a client, at runtime we can vary the algorithm based on the type of request we have received.
So we use Strategy pattern to hide the algorithm implementation details from client.
In Observer design pattern, there is a Subject that maintains the list of Observers that are waiting for any update
on the Subject. Once there is an update in Subject it notifies all the observers for the change.
E.g. In real life, students are waiting for the result of their test. Here students are the observers and test is the
subject. Once the result of test is known, testing organization notifies all the students about their result.
The most popular use of Observer pattern is in Model View Controller (MVC) architectural pattern.
Main issue with Observer pattern is that it can cause memory leaks. The subject holds a strong reference to
observers. If observers are not de-registered in time, it can lead to memory leak.
java.util.Observer, java.util.Observable
javax.servlet.http.HttpSessionAttributeListener
javax.servlet.http.HttpSessionBindingListener
javax.faces.event.PhaseListener
How Strategy design pattern is different from State design pattern in Java?
State design pattern is a behavioral design pattern that is use for defining the state machine for an object. Each
state of an object is defined in a child class of State class. When different actions are taken on an Object, it can
change its state.
Strategy pattern is also a behavioral pattern, but it is mainly used for defining multiple algorithms. With same
action of a client, the algorithm to be used can change.
Some people consider State pattern similar to Strategy pattern, since an Object changes its Strategy with different
method invocations. But the main difference is that in State pattern internal state of an Object is one of the
determining factors for selecting the Strategy for change of state.
Where as in Strategy pattern, client can pass some external parameter in input during method invocation that
determines the strategy to be used at run time.
Therefore State pattern is based on the Object’s internal state, where as Strategy pattern is based on Client’s
invocation.
State pattern is very useful in increasing the maintainability of the code in a large code-base.
Some people call Decorator pattern as Wrapper pattern as well. It is used to add the behavior to an object, without
changing the behavior of other objects of same class.
One of the very good uses of Decorator pattern is in java.io package. We can have a FileInputStream to handle a
File. To add Buffering behavior we can decorate FileInputStream with BufferedInputStream. To add the gzip
behavior BufferedInputStream we can decorate it with GzipInputStream. To add serialization behavior to
GzipInputStream, we can decorate it with ObjectInputStream.
E.g.
Open a FileInputStream:
Add Gzip:
Add Serialization:
So with each step we have decorated the FileInputStream with additional behavior
Some of the good scenarios where Composite design pattern can be used are as follows:
Tree Structure: The most common use of Composite design pattern is Tree structure. If you want to represent data
in a Tree data structure, Composite pattern can be used.
E.g. In an Organization, to a Manager has Employees. But Manager is also an Employee. If we start from CEO
level, there is one big tree for the whole organization structure. Under that big tree there are many sub-trees. This
can be easily represented with Composite design pattern.
Recursion: Another use of Composite design pattern is Recursion. If we have a Recursion based algorithm, we
need data to be passed to algorithm in a data structure that treats individual objects and compositions at each level
of recursion uniformly.
E.g. To implement a recursive Polynomial Solving algorithm, we can use Composite design pattern to store the
intermediate results.
Graphics: Another good use of Composite design pattern is in Graphics. We can group shapes inside a composite
and make higher-level groups of smaller groups of shapes to complete the graphics to be displayed on screen.
Yes. Singleton is one of the most popular design patterns in enterprise level Java applications. Almost in every
project we see some implementation of Singleton.
With Singleton pattern we can be sure that there is only one instance of a class at any time in the application.
This helps in storing properties that have to be used in the application in a unique location.
What are the main uses of Singleton design pattern in Java project?
Some of the main uses of Singleton design pattern in Java are as follows:
Runtime: In JDK, java.lang.Runtime is a singleton-based class. There is only one instance of Runtime in an
application. This is the only class that interfaces with the environment/machine in which Java process is running.
Enum: In Java, enum construct is also based on Singleton pattern. Enum values can be accessed globally in same
way by all classes.
Properties: In an application it makes sense to keep only one copy of the properties that all classes can access.
This can be achieved by making properties class Singleton so that every class gets same copy of properties.
Spring: In Spring framework, all the beans are by default Singleton per container. So there is only one instance
of bean in a Spring IoC container. But Spring also provides options to make the scope of a bean prototype in a
container.
Runtime is the class that acts as an interface with the environment in which Java process is running. Runtime
contains methods that can interact with the environment.
Like- totalmemory() method gives the total memory in JVM. maxMemory() method gives the maximum memory
that JVM can use.
There is an exit() method to exit the Java process. We do not want multiple objects in JVM to have exit() method.
Similarly there is gc() method that can run the Garbage Collector. With only one copy of gc() method, we can
ensure that no other object can run the Garbage Collector when one instance of GC is already running.
Due to all these reasons there is only one copy of Runtime in Java. To ensure single copy of Runtime, it is
implemented as a Singleton in Java.
In Java there are many options to implement a thread-safe Singleton pattern. Some of these are as follows:
1. Double Checked Locking: This is the most popular method to implement Singleton in Java. It is based on Lazy
Initialization. In this we first check the criteria for locking before acquiring a lock to create an object. In Java we
use it with volatile keyword.
Sample code:
}
2. Bill Pugh Singleton: We can also use the method by Bill Pugh for implementing Singleton in Java. In this we
use an Inner Static class to create the Singleton instance.
Sample code:
// Private constructor
private SingletonBillPugh(){}
When first time SingletonBillPugh is loaded in memory, InnerSingleton is not loaded. Only when getInstance()
method is called, InnerSingleton class is loaded and an Instance is created.
3. Enum: We can also use Java enum to create thread-safe implementation. Java enum values are accessible
globally so these can be used as a Singleton.
Sample Code:
INSTANCE;
In JDK there are many places where Singleton design pattern is used. Some of these are as follows:
1. java.lang.Runtime.getRuntime(): This method gives Runtime class that has only one instance in a JVM.
It is a behavioral design pattern. We can use it to create an outline for an algorithm or a complex operation. We
first create the skeleton of a program. Then we delegate the steps of the operation to subclasses. The subclasses
can redefine the inner implementation of each step.
E.g. While designing a Game in Java, we can implement it as an algorithm with Template Method pattern. Each
step in the game can be deferred to subclasses responsible for handling that step.
Let say we implement Monopoly game in Java. We can create methods like initializeGame(), makeMove(),
endGame() etc. Each of these methods can be handled in subclasses in an independent manner.
We can use same algorithm for Chess game with same set of abstract methods. The subclass for Chess game can
provide the concrete implementation of methods like initializeGame(), makeMove(), endGame() etc.
Template Method pattern is very useful in providing customizable class to users. We can create the core class
with a high level implementation. And our users can customize our core class in their custom subclasses.
In JDK there are many places where Template method design pattern is used. Some of these are as follows:
javax.servlet.http.HttpServlet: In the HttpServlet class all the doGet(), doPost() etc. methods send a HTTP 405
"Method Not Allowed" error to the response. This error response is like a Template that can be further customized
for each of these methods.
In java.io package there are Stream and Writer classes like java.io.InputStream, java.io.OutputStream,
java.io.Reader and java.io.Writer that provide non-abstract methods. These methods are implementation of
Template method design pattern.
Can you tell some examples of Factory Method design pattern implementation in Java?
Factory Method pattern is a creational design pattern. A Factory is an object that is used to create more objects.
In general, a Factory object has methods that can be used to create a type of objects. Some people call it Factory
Method design pattern as well.
Java.lang.Class.forName()
java.net.URLStreamHandlerFactory.createURLStreamHand
java.util.Calendar.getInstance()
java.util.ResourceBundle.getBundle()
java.text.NumberFormat.getInstance()
java.nio.charset.Charset.forName()
java.util.EnumSet.of()
javax.xml.bind.JAXBContext.createMarshaller()
What is the benefit we get by using static factory method to create object?
By using Static Factory Method we encapsulate the creation process of an object. We can use new() to create an
Object from its constructor. Instead we use static method of a Factory to create the object. One main advantage
of using Factory is that Factory can choose the correct implementation at runtime and create the right object. The
caller of method can specify the desired behavior.
E.g. If we have a ShapeFactory with createShape(String type) method. Client can call
ShapeFactory.createShape(“Circle”) to get a circular shape. ShapeFactory.createShape(“Square”) will return
square shape. In this way, ShapeFactory knows how to create different shapes based on the input by caller.
Another use of Factory is in providing access to limited resources to a large set of users.
E.g. In ConnectionPool, we can limit the total number of connections that can be created as well as we can hide
the implementation details of creating connection. Here ConnectionPool is the factory. Clients call static method
ConnectionPool.getConnection().
In JDK there are many places where Builder design pattern is used.
Some of these are as follows:
java.nio.IntBuffer.put(): Invocation of put() method return IntBuffer. Also there are many variants of this method
to build the IntBuffer.
java.lang.Appendable
In JDK there are many places where Abstract Factory design pattern is used. Some of these are as follows:
javax.xml.xpath.XPathFactory.newInstance()
javax.xml.parsers.DocumentBuilderFactory.newInstance()
javax.xml.transform.TransformerFactory.newInstance()
In JDK there are many places where Decorator design pattern is used. Some of these are as follows:
In java.io package many classes use Decorator pattern. Subclasses of java.io.InputStream, OutputStream, Reader
and Writer have a constructor that can take the instance of same type and decorate it with additional behavior.
In java.util.Collections, there are methods like checkedCollection(), checkedList(), checkedMap(),
synchronizedList(), synchronizedMap(), synchronizedSet(), unmodifiableSet(), unmodifiableMap() and
unmodifiableList() methods that can decorate an object and return the same type.
Proxy design pattern provides an extra level of indirection for providing access to another object. It can also
protect a real object from any extra level of complexity.
In JDK there are many places where Proxy design pattern is used.
Some of these are as follows:
java.lang.reflect.Proxy
java.rmi.*
javax.inject.Inject
javax.ejb.EJB
javax.persistence.PersistenceContext
In JDK there are many places where Chain of Responsibility design pattern is used. Some of these are as follows:
java.util.logging.Logger.log(): In this case Logger class provides multiple variations of log() method that can take
the responsibility of logging from client in different scenarios. The client has to just call the appropriate log()
method and Logger will take care of these commands.
javax.servlet.Filter.doFilter(): In the Filter class, the Container calls the doFilter method when a request/response
pair is passed through the chain. With filter the request reaches to the appropriate resource at the end of the chain.
We can pass FilterChain in doFilter() method to allow the Filter to pass on the request and response to the next
level in the chain.
Command design pattern is a behavioral design pattern. We use it to encapsulate all the information required to
trigger an event. Some of the main uses of Command pattern are:
Graphic User Interface (GUI): In GUI and menu items, we use command pattern. By clicking a button we can
read the current information of GUI and take an action.
Macro Recording: If each of user action is implemented as a separate Command, we can record all the user actions
in a Macro as a series of Commands. We can use this series to implement the “Playback” feature. In this way,
Macro can keep on doing same set of actions with each replay.
Multi-step Undo: When each step is recorded as a Command, we can use it to implement Undo feature in which
each step can by undo. It is used in text editors like
MS-Word.
Networking: We can also send a complete Command over the network to a remote machine where all the actions
encapsulated within a Command are executed.
Progress Bar: We can implement an installation routine as a series of Commands. Each Command provides the
estimate time. When we execute the installation routine, with each command we can display the progress bar.
Wizard: In a wizard flow we can implement steps as Commands. Each step may have complex task that is just
implemented within one command.
Transactions: In a transactional behavior code there are multiple tasks/updates. When all the tasks are done then
only transaction is committed. Else we have to rollback the transaction. In such a scenario each step is
implemented as separate Command.
In JDK there are many places where Command design pattern is used. Some of these are as follows:
Interpreter design pattern is used to evaluate sentences in a language. E.g. In SQL we can use it to evaluate a
query by evaluating each keyword like SELECT, FROM, WHERE clause.
In an Interpreter implementation there is a class for each keyword/symbol. A sentence is just a composite of these
keywords. But the sentence is represented by Syntax tree that can be interpreted.
In JDK there are many places where Interpreter design pattern is used. Some of these are as follows:
java.util.Pattern
java.text.Normalizer
By using Mediator pattern we can decouple the multiple objects that interact with each other. With a Mediator
object we can create many-to-many relationships in multiple objects.
In JDK there are many places where Mediator design pattern is used. Some of these are as follows:
java.util.Timer: schedule() methods in Timer class act as Mediator between the clients and the TimerTask to be
scheduled.
java.util.concurrent.ScheduledExecutorService: Here also schedule() method and its variants are Mediator
pattern implementations.
In JDK there are many places where Strategy design pattern is used.
Some of these are as follows:
java.util.Comparator: In a Comparator we can use compare() method to change the strategy used by
Collections.sort() method.
javax.servlet.http.HttpServlet: In a HttpServlet class service() and doGet(), doPost() etc. methods take
HttpServletRequest and HttpServletResponse and the implementor of Servlet processes it based on the strategy
it selects.
By using Visitor design pattern we can add new virtual methods to existing classes without modifying their core
structure.
In JDK there are many places where Visitor design pattern is used.
Some of these are as follows:
javax.lang.model.element.AnnotationValue and
AnnotationValueVisitor
java.nio.file.FileVisitor and SimpleFileVisitor
javax.faces.component.visit.VisitContext and
VisitCallback
Decorator provides an enhanced interface after decorating it with additional features. Proxy provides same
interface since it is just acting as a proxy to another object.
Decorator is a type of Composite pattern with only one component. But each decorator can add additional
features. Since it is one component in Decorator, there is no object aggregation.
Proxy can also provide performance improvement by lazy loading. There is nothing like this available in
Decorator.
Decorator follows recursive composition. Proxy is just one object to another object access.
Decorator is mostly used for building a variety of objects. Proxy is mainly used for access to another
object.
What are the different scenarios to use Setter and Constructor based injection in Dependency Injection
(DI) design pattern?
We use Setter injection to provide optional dependencies of an object. Constructor injection is used to provide
mandatory dependency of an object.
In Spring IoC, Dependency Injection is heavily used. There we have to differentiate between the scenario suitable
for Setter based and Constructor based dependency injection.
What are the different scenarios for using Proxy design pattern?
Proxy design pattern can be used in a wide variety of scenario in Java. Some of these are as follows:
Virtual Proxy: This is a virtual object that acts as a proxy for objects that are very expensive to create. It is used
in Lazy Loading. When client makes the first request, the real object is created.
Remote Proxy: This is a local object that provides access to a remote object. It is generally used in Remote Method
Invocation (RMI) and Remote Procedure Call (RPC). It is also known as a Stub.
Protective Proxy: This is an object that control the access to a Master object. It can authenticate and authorize the
client for accessing the Master object. If client has right permissions, it allows client to access the main object.
Smart Proxy: It is an object that can add additional information to the main object. It can track the number of
other objects accessing the main object. It can track the different clients from where request is coming. It can
even deny access to an object if the number of requests is greater than a threshold.
What is the main difference between Adapter and Proxy design pattern?
Adapter pattern provides a different interface to an object. But the Proxy always provides same interface to the
object.
Adapter is like providing an interface suitable to client’s use. But Proxy is same interface that has additional
feature or check.
E.g. In electrical appliances we use Adapter to convert from one type of socket to another type of socket. In case
of proxy, we have a plug with built-in surge protector. The interface for plug and the original device remains
same.
If we have two classes with incompatible interfaces, we use Adapter pattern to make it work. We create an Adapter
object that can adapt the interface of one class to another class.
It is generally used for working with third party libraries. We create an Adapter class between third party code
and our class. In case of any change in third party code we have to just change the Adapter code. Rest of our code
can remain same and just take to Adapter.
In JDK there are many places where Adapter design pattern is used.
Some of these are as follows:
java.util.Collections.list(): This method can adapt any collection to provide List behavior.
javax.xml.bind.annotation.adapters.XmlAdapter.marshal()
What is the difference between Factory and Abstract Factory design pattern?
With Factory design pattern we can create concrete products of a type that Factory can manufacture. E.g. If it is
CarFactory, we can produce, Ford, Toyota, Honda, Maserati etc.
With Abstract Factory design pattern we create a concrete implementation of a Factory. E.g. DeviceFactory can
be Abstract and it can give us GoogleDeviceFactory, AppleDeviceFactory etc. With AppleDeviceFactory we will
get products like- iPhone, iPad, Mac etc. With GoogleDeviceFactory we will get products likeNexus phone,
Google Nexus tablet, Google ChromeBook etc.
So it is a subtle difference between Factory and Abstract Factory design pattern. One way to remember is that
within Abstract Factory pattern, Factory pattern is already implemented.
Open/closed design principle states “software entities (classes, modules, functions, etc.) should be open for
extension, but closed for modification”.
Open/closed principle term was originated by Bertrand Meyer in his book Object Oriented Software Construction.
As per this principle, if a module is available for extension then it is considered open. If a module is available for
use by other modules then it is considered closed.
Further Robert C. Martin has mentioned it as O in SOLID principles of Object Oriented design.
It is used in State and Strategy design patterns. Context class is closed for modification. But new functionality
can be added by writing new strategy code.
What is SOLID design principle?
This principle was mentioned by Robert C. Martin. These are considered five basic principles of Object Oriented
design.
If we follow these principles, then we can create a stable program that is easy to maintain and can be extended
over time.
Builder design pattern is a creational design pattern. We can use Builder pattern to create complex objects with
multiple options.
E.g. when we have to create a Meal in a restaurant we can use Builder pattern. We can keep adding options like-
Starter, Drink, Main Course, and Dessert etc. to create complete meal. When a user selects other options of Starter,
Drink Main Course, Dessert another type of meal is created.
Main feature of Builder pattern is step-by-step building of a complex object with multiple options.
What are the different categories of Design Patterns used in Object Oriented Design?
In Object Oriented design mainly three categories of design patterns are used. These categories are:
We can use Iterator design pattern to access the individual elements of a Collection. In case of an ordered
collection we can get Iterator that returns the elements in an order.
In Java there are many implementation of Iterator in Collections package. We have iterators like- Spliterator,
ListIterator etc. that implement Iterator pattern.
We can use Decorator design pattern to add new features to an existing object. With a Decorator we work on
same object and return the same object with more features. But the structure of the object remains same since all
the decorated versions of object implement same interface.
Which design pattern can be used when to decouple abstraction from the implementation?
We can use Bridge design pattern to detach the implementation from the abstraction.
Bridge is mainly used for separation of concern in design. We can create an implementation and store it in the
interface, which is an abstraction. Where as specific implementation of other features can be done in concrete
classes that implement the interface.
E.g. we have Shape interface. We want to make Square and Circle shapes. But further we want to make
RedSquare, BlackSquare shapes and GreenCircle, WhiteCircle shapes. In this case rather than creating one
hierarchy of all the shapes, we separate the Color concern from Shape hierarchy.
So we create two hierarchies. One is Shape to Square and Shape to Circle hierarchy. Another one is Color to Red,
Black, Green, White hierarchy. In this way we can create multiple types of shapes with multiple colors with
Bridge design pattern.
View: These are the UI components in your application. These are part of the view. Also any events on UI
components are part of view module.
Presenter: This is the bridge between Model and View to control the communication. Presenter can query the
model and return data to view to update it.
E.g. If we have a Model with large news article data, and view needs only headline, then presenter can query the
data from model and only give headline to view. In this way view remains very light in this design pattern.
How can we prevent users from creating more than one instance of singleton object by using clone()
method?
First we should not implement the Cloneable interface by the object that is a Singleton.
Second, if we have to implement Cloneable interface then we can throw exception in clone() method.
This will ensure that no one can use clone() method or Cloneable interface to create more than one instance of
Singleton object.
Interceptor design pattern is used for intercepting a request. Primary use of this pattern is in Security policy
implementation.
We can use this pattern to intercept the requests by a client to a resource. At the interception we can check for
authentication and authorization of client for the resource being accessed.
This pattern is also used in Spring framework in HandlerInterceptor and MVC interceptor.
Architectural patterns are used to define the architecture of a Software system. Some of the patterns are as follows:
MVC: Model View Controller. This pattern is extensively used in the architecture of Spring framework.
Publish-subscribe: This pattern is the basis of messaging architecture. In this case messages are published to a
Topic. And subscribers subscribe to the topic of their interests. Once the message is published to a topic in which
a Subscriber has an interest, the message is consumed by the relevant subscriber.
Service Locator: This design pattern is used in a service like JNDI to locate the available services. It uses as
central registry to maintain the list of services.
n-Tier: This is a generic design pattern to divide the architecture in multiple tiers. E.g. there is 3-tier architecture
with Presentation layer, Application layer and Data access layer. It is also called multi-layer design pattern.
Data Access Object (DAO): This pattern is used in providing access to database objects. The underlying principle
is that we can change the underlying database system, without changing the business logic. Since business logic
talks to DAO object, there is no impact of changing Database system on business logic.
Inversion of Control (IoC): This is the core of Dependency Injection in Spring framework. We use this design
pattern to increase the modularity of an application. We keep the objects loosely coupled with Dependency
Injection.
A Façade provides convenient methods for common tasks that are used more often.
A Façade can make the software library more readable.
A Façade can reduce the external dependencies on the working of inner code.
A Façade can act as a single well-designed API by wrapping a collection of poorly designed APIs.
A Façade pattern can be used when a System is very complex and difficult to use. It can simplify the usage of
complex system.
What is the difference between Builder design pattern and Factory design pattern?
Both Factory and Builder patterns are creational design patterns. They are similar in nature but Factory pattern is
a simplified generic version of Builder pattern.
We use Factory pattern to create different concrete subtypes of an Object. The client of a Factory may not know
the exact subtype. E.g. If we call createDrink() of a Factory, we may get Tea or Coffee drinks.
We can also use Builder pattern to create different concrete subtypes of an object. But in the Builder pattern the
composition of the object can be more complex. E.g. If we call createDrink() for Builder, we can getCappuccino
Coffee with Vanilla Cream and Sugar, or we can get Latte Coffee with Splenda and milk cream.
So a Builder can support creation of a large number of variants of an object. But a Factory can create a broader
range of known subtypes of an object.
Memento design pattern is used to implement rollback feature in an object. In a Memento pattern there are three
objects:
Caretaker: This is the object that can change the state of Originator. But it wants to have control over rolling
back the change.
Memento: This is the object that Caretaker gets from Originator, before making and change. If Caretaker wants
to Rollback the change it gives Memento back to Originator. Originator can use Memento to restore its own state
to the original state.
E.g. One good use of memento is in online Forms. If we want to show to user a form pre-populated with some
data, we keep this copy in memento. Now user can update the form. But at any time when user wants to reset the
form, we use memento to make the form in its original pre-populated state. If user wants to just save the form we
save the form and update the memento. Now onwards any new changes to the form can be rolled back to the last
saved Memento object.
What is an AntiPattern?
An AntiPattern is opposite of a Design Pattern. It is a common practice in an organization that is used to deal with
a recurring problem but it has more bad consequences than good ones.
Gold Plating: Keep on adding extra things on a working solution even though these extra things do not add any
additional value.
Spaghetti Code: Program that are written in a very complex way and are hard to understand due to misuse of data
structures.
Coding By Exception: Adding new code just to handle exception cases and corner case scenarios.
Copy Paste Programming: Just copying the same code multiple times rather than writing generic code that can be
parameterized.
DAO design pattern is used in the data persistent layer of a Java application. It mainly uses OOPS principle of
Encapsulation.
By using DAO pattern it makes the application loosely coupled and less dependent on actual database.
We can even implement some in-memory database like H2 with DAO to handle the unit-testing.
In short, DAO hides the underlying database implementation from the class that accesses the data via DAO object.
Recently we can combine DAO with Spring framework to inject any DB implementation.
Spring
Spring is development framework for Java programming. It is an open source development framework for
Enterprise Java.
The core features of Spring Framework can be used in developing a Java Enterprise application.
It has many extensions and jars for developing web applications on top of Java EE platform.
With Spring we can develop large-scale complex Java applications very easily. It is also based on good design
patterns like Dependency Injection, Aspect oriented programming for developing extensible feature rich software.
Lightweight Framework: Basic Spring framework is very small in size. It is easy to use and does not add a lot of
overhead on software. It just has 2 MB in basic version.
Container: Spring framework provides the basic container that creates and manages the life cycle of application
objects like Plain old Java objects (POJO). It also stores the configuration files of application objects to be created.
Dependency Injection (DI): Spring provided loose coupling is application by Dependency Injection. It uses
Inversion of Control technique by which objects specify their dependencies to Spring container instead of creating
new objects themselves.
Aspect Oriented Programming (AOP): Spring framework promotes and provides support for Aspect oriented
programming in Java. This helps in separating application business logic from system services that are common
across all the business logic. E.g. Logging can be a cross cutting concern in an Application.
Transaction Management: Spring provides a framework for transaction management. So a developer does not
have to implement it from scratch. Spring Transaction Management is so powerful that we can scale it from one
local transaction to global transactions in a cluster.
MVC Framework: For Web applications, Spring provides MVC framework. This framework is based on MVC
design pattern and has better features compared to other web frameworks.
Exception Handling: Spring also gives support for a common API to handle exceptions in various technologies
like- Hibernate, JDBC etc.
Core module
Bean module
Context module
Spring Expression Language module
As the name suggests, Spring Core Container is the core of Spring framework. It gives the basic functionality of
the Spring. All the parts of Spring Framework are built on top of Core Container.
Its main use is to provide Dependency Injection (DI) and Inversion of control (IOC) features.
Spring Test Module provides support for Unit testing as well as Integration testing of Spring components. It
allows using JUnit or TestNG testing frameworks. It also gives ability to mock objects to use the test code.
BeanFactory is the main class that helps in implementing Inversion of Control pattern in Spring. It is based on
the factory design pattern. It separates the configuration and dependencies of an application from the rest of
application code.
Implementations of BeanFactory like XmlBeanFactory class are used by applications built with Spring.
XMLBeanFactory is one of the most useful implementation of BeanFactory in Spring. This factory loads its beans
based on the definitions mentioned in an XML file.
Spring container reads bean configuration metadata from an XML file and creates a fully configured application
with the help of XMLBeanFactory class.
AOP module is also known as Aspect Oriented Programming module. Its uses are:
What are the benefits of JDBC abstraction layer module in Spring framework?
Spring provides JDBC abstraction layer module. Main benefits of this module are:
Spring supports Object Relational Mapping (ORM) by providing ORM Module. This module helps in integrating
with popular ORM framework like Hibernate, JDO, and iBATIS SQL Maps etc.
Transaction Management module of Spring framework supports all of these ORM frameworks as well as JDBC.
Spring provides support for developing web application by using Web module. This module is built on application
context module that provides context for web-based applications.
This module also supports web-oriented integration features liketransparently handling multipart requests for
uploading files, programmatically binding request parameters to business objects etc.
This module also supports integration with popular web frameworks like Jakarta Struts, JSF, and Tapestry etc.
Spring-webmvc module is also known as Web-servlet module. It is based on Web Model View Controller pattern.
Spring application can be configured by an XML file. This file contains information of classes and how these
classes are configured and introduced to each other.
Spring IoC container uses some kind of configuration metadata. This configuration metadata represents how an
application developer tells the Spring container to instantiate, configure, and assemble the objects in your
application. This configuration metadata is stored in Spring configuration file.
The other ways of specifying configuration metadata are Java based configuration and Annotation based
configuration.
Inversion of Control (IOC) principle is the base of Spring framework. It supports dependency injection in an
application. With Dependency Injection, a programmer has to write minimal code. It also makes easier to test an
application.
Most important benefit is that it leads to loose coupling within objects. With loose coupling it is easier to change
the application with new requirements.
IOC Container in Spring supports both the approaches. Eager instantiation as well as lazy loading of beans.
FileSystemXmlApplicationContext: If we want to load the definitions of beans from an XML file then
FileSystemXmlApplicationContext is used. The full path of XML bean configuration file is provided to the
constructor.
ClassPathXmlApplicationContext: To loads the definitions of beans from an XML file in the CLASSPATH, we
use ClassPathXmlApplicationContext. It is used for application context embedded in jars.
Spring documentation recommends using ApplicationContext in almost all the cases. ApplicationContext has all
the functionality of BeanFactory.
Dependency Injection is a software design pattern. It is used to implement Inversion of Control (IOC) in Spring
framework. As per this pattern, we do not create objects in an application by calling new. Rather, we describe
how an object should be created. In this way creation of an object is not tightly coupled with another object.
A container is responsible for creating and wiring the objects. The container can call injecting code and wire the
objects as per the configuration at runtime.
Constructor-based Dependency Injection: Spring container can invoke a class constructor with a number of
arguments. This represents a dependency on other class.
Setter-based Dependency Injection: Spring container can call setter method on a bean after creating it with a no-
argument constructor or no-argument static factory method to instantiate another bean.
It is recommended to use Constructor-based DI for mandatory dependencies. Whereas Setter-based DI is used for
optional dependencies.
With Dependency Injection (DI), we can do concurrent or independent software development. Two teams can
work parallel on classes that will be used by each other.
In Dependency Injection (DI), the client can be configured in multiple ways. It needs to just work with the given
interface. Rest of the implementation can be changed and configured for different features.
Dependency injection is also used to export a system's configuration details into configuration files. So we can
configure same application run in different environments based on configuration.
E.g. Run in Test environment, UAT environment, and Production environment.
Dependency Injection (DI) applications provide more ease and flexibility of testing. These can be tested in
isolation in Unit Test.
Dependency injection (DI) isolates client from the impact of design and implementation changes. Therefore, it
promotes reusability, testability and maintainability.
Most of the time Dependency Injection forces developers to use an injection framework like Spring. This causes
dependency on a framework.
With Dependency Injection, clients are dependent on the configuration data. This becomes extra task for
developers when the application does not need so many custom configuration values.
Code is difficult to trace and read in Dependency Injection. DI separates behavior from construction of objects.
Dependency injection increases complexity in the linkages between classes. It may become harder to manage
such complexity outside the implementation of a class.
A Spring Bean is a plain old Java object (POJO) that is created and managed by a Spring container.
There can be more than one bean in a Spring application. But all these Beans are instantiated and assembled by
Spring container.
Developer provides configuration metadata to Spring container for creating and managing the lifecycle of Spring
Bean.
In general a Spring Bean is singleton. Evert bean has an attribute named "singleton". If its value is true then bean
is a singleton. If its value is false then bean is a prototype bean.
By default the value of this attribute is true. Therefore, by default all the beans in spring framework are singleton
in nature.
A Spring Bean definition contains configuration metadata for bean. This configuration metadata is used by Spring
container to:
What are the different ways to provide configuration metadata to a Spring Container?
Annotation-based configuration: We can use Annotations to specify configuration. This was introduced in Spring
2.5.
Java-based configuration: This is introduced from Spring 3.0. We can embed annotations like @Bean, @Import,
@Configuration in Java code to specify configuration metadata.
Spring framework support seven types of scopes for a Bean. Out of these only five scopes are available for a web-
aware
ApplicationContext application:
singleton: This is the default scope of a bean. Under this scope, there is a single object instance of bean per Spring
IoC container.
prototype: Under this scope a single bean definition can have multiple object instances.
request: In this scope, a single bean definition remains tied to the lifecycle of a single HTTP request. Each HTTP
request will have its own instance of a bean for a single bean definition. It is only valid in the context of a web-
aware Spring ApplicationContext.
session: Under this scope, a single bean definition is tied to the lifecycle of an HTTP Session. Each HTTP Session
will have one instance of bean. It is also valid in the context of a web-aware Spring ApplicationContext.
globalSession: This scope, ties a single bean definition to the lifecycle of a global HTTP Session. It is generally
valid in a Portlet context. It is also valid in the context of a web-aware Spring ApplicationContext.
application: This scope, limits a single bean definition to the lifecycle of a ServletContext. It is also valid in the
context of a web-aware Spring ApplicationContext.
websocket: In this scope, a single bean definition is tied to the lifecycle of a WebSocket. It is also valid in the
context of a webaware Spring ApplicationContext.
In configuration xml, we can specify the scope of bean in its definition. This is used by container to decide the
scope of bean in Spring.
No, Spring framework does not guarantee anything related to multithreaded behavior of a singleton bean.
Developer is responsible for dealing with concurrency issues and maintaining thread safety of a singleton bean.
Spring framework uses many Design patterns. Some of these patterns are:
Singleton – By default beans defined in spring config files are singleton. These are based on Singleton pattern.
Template – This pattern is used in many classes like- JdbcTemplate, RestTemplate, JmsTemplate, JpaTemplate
etc.
Dependency Injection – This pattern is the core behind the design of BeanFactory and ApplicationContext.
Proxy – Aspect Oriented Programming (AOP) heavily uses proxy design pattern.
Front Controller – DispatcherServlet in Spring is based on Front Controller pattern to ensure that incoming
requests are dispatched to other controllers.
Factory pattern – To create an instance of an object, BeanFactory is used. This is based on Factory pattern.
View Helper – Spring has multiple options to separating core code from presentation in views. Like- Custom JSP
tags, Velocity macros etc.
Initialization and creation: Spring container gets the definition of Bean from XML file and instantiates the Bean.
It populates all the properties of Bean as mentioned in the bean definition.
Setting the Behavior of Bean: In case a Bean implements BeanNameAware interface, Spring uses setBeanName()
method to pass the bean’s id. In case a Bean implements BeanFactoryAware interface, Spring uses
setBeanFactory() to pass the BeanFactory to bean.
Post Processing: Spring container uses postProcesserBeforeInitialization() method to call BeanPostProcessors
associated with the bean. Spring calls afterPropertySet() method to call the specific initialization methods. In case
there are any BeanPostProcessors of a bean, the postProcessAfterInitialization() method is called.
Destruction: During the destruction of a bean, if bean implements DisposableBean, Spring calls destroy() method.
Initialization Callbacks: Once all the necessary properties of a Bean are set by the container, Initialization
Callback methods are used for performing initialization work. A developer can implement method
afterPropertiesSet() for this work.
Destruction Callbacks: When the Container of a Bean is destroyed, it calls the methods in DisposableBean to do
any cleanup work. There is a method called destroy() that can be used for this purpose to make Destruction
Callbacks.
Recent recommendation from Spring is to not use these methods, since it can strongly couple your code to Spring
code.
Yes, Spring framework allows developers to override the lifecycle methods of a Bean. This is used for writing
any custom behavior for Bean.
A bean that is used as a property of another bean is known as Inner bean. It can be defined as a <bean/> element
in <property/> or <constructor-arg/> tags.
It is not mandatory for an Inner bean to have id or a name. These are always anonymous.
Spring promotes Dependency Injection (DI) in code. It gives support for injecting not only objects but also
collection of objects.
We can inject collections like- list, set, map etc. in Spring. Following tags can be used for this purpose:
<list> : This type is used for injecting a list of values. In a <list> duplicates are allowed.
<set> : This type is used for injecting a set of values. As per set property, duplicates are not allowed.
<map> : This type is used for injecting name-value pairs in form of map. Name and value can be of any type that
is allowed for a map.
<props> : This type is used to inject a collection of String based name-value. It is like a properties file.
What is Bean wiring in Spring?
A Spring container is responsible for injecting dependencies between beans. This process of connecting beans is
called wiring.
Developer mentions in configuration file, the dependencies between beans. And Spring container reads these
dependencies and wires the beans on creation.
Autowiring is a feature of Spring in which container can automatically wire/connect the beans by reading the
configuration file.
Spring resolves the dependencies automatically by looking at this attribute of beans that are autowired.
no: This is default setting for Autowiring. In this case, we use “ref” mode to mention the explicit bean that is
being referred for wiring.
byName: In this case, Spring container tries to match beans by name during Autowiring. If the name of a bean is
same as the name of bean referred in autowire byname, then it automatically wires it.
byType: In this case, Spring container check the properties of beans referred with attribute byType. Then it
matches the type of bean and wires. If it finds more than one such bean of that type, it throws a fatal exception.
autodetect: This is an advanced mode for autowiring. In this case, by default Spring tries to find a constructor
match. If it does not find constructor then it uses autowire by Type.
What are the cases in which Autowiring may not work in Spring framework?
Autowiring is a great feature in Spring. It can be used in most of the cases. But there are certain scenarios in
which Autowiring may not work.
Explicit wiring: Since Autowiring is done by Spring, developer does not have full control on specifying the exact
class to be used. It is preferable to use Explicit wiring in case of full control over wiring.
Primitive Data types: Autowiring does not allow wiring of properties that are based on primitive data types like-
int, float etc.
Spring allows for Java-based configuration in which a developer can specify configuration by using Java-based
annotations. This feature was introduced in Spring 3.0.
You can use annotations like- @Configuration, @Bean, @Import and @DependsOn in Java classes for specifying
the configuration.
This annotation is used in a class to indicate that this is class is the primary source of bean definitions. This class
can also contain inter-bean dependencies that are annotated by @Bean annotation.
What is the difference between Full @Configuration and 'lite' @Beans mode?
Spring allows for using @Bean annotation on methods that are declared in classes not annotated with
@Configuration. This is known as “lite” mode. In this mode, bean methods can be declared in a @Component
or a plain java class without any annotation.
Now developer can use annotations like @Required, @Autowired, @Qualifier etc. in a class file to specify the
configuration for beans. Spring container can use this information from annotation for creating and wiring the
beans.
To use Annotation based wiring, we need to turn on Annotation based configuration in Spring.
By default, Annotation based configuration is switched off in Spring. To turn it is we can specify
<context:annotation-config/> element in Spring config file.
Once it is turned on, we can use @Autowired annotation or @Required annotation in a Java class for wiring in
Spring.
We can use @Autowired annotation to auto wire a bean on a setter method, constructor or a field. @Autowired
auto wiring is done by matching the data type.
We use @Required annotation to a property to check whether the property has been set or not.
Spring container throws BeanInitializationException if the @Required annotated property is not set.
E.g.
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/bea
http://www.springframework.org/schema/beans/spring-beans2.5.xsd">
<bean class="org.springframework.beans.factory.annotation.RequiredAnno
</beans>
We use @Qualifier annotation to mark a bean as ready for auto wiring. This annotation is used along with
@Autowired annotation to specify the exact bean for auto wiring by Spring container.
Spring provides a mature JDBC framework to provide support for JDBC coding. Spring JDBC handled resource
management as well as error handling in a generic way. This reduces the work of software developers.
They just have to write queries and related statements to fetch the data or to store the data in database.
Spring framework provides JdbcTemplate class that contains many convenient methods for regular tasks like-
converting data into primitives or objects, executing prepared or callable statements etc.
This class makes it very easy to work with database in our Application and it also provides good support for
custom error handling in database access code.
What are the benefits of using Spring DAO?
It makes it easier to work on different data access methods likeJDBC, Hibernate etc.
It provides a consistent and common way to deal with different data access methods.
Spring DAO makes it easier to switch between different data persistence frameworks.
No need for catching framework specific exceptions.
We can extend HibernateDAOSupport and apply an AOP interceptor node to use Hibernate.
We can also use HibernateTemplate and Callback to access Hibernate. This is based on Inversion of Control.
Hibernate
Java Persistence API (JPA)
TopLink
Java Data Objects (JDO)
Apache Object Relational Bridge (ORB)
What are the different types of the Transaction Management supported by Spring framework?
Programmatic: In this method, we have to manage Transaction by programming explicitly. It provides flexibility
to a developer, but it is not easier to maintain.
Declarative: In this approach, we can separate Transaction Management from the Application Business code. We
can use annotations or XML based configuration to manage the transactions in declarative approach.
Consistent: By using Spring Transaction management, we can use consistent programming model across different
transaction APIs like- JPA, JDBC, JTA, Hibernate, JPA, JDO etc.
Simplicity: Spring TM provides simple API for managing the transaction programmatically.
Declarative: Spring also supports annotation or xml based declarative transaction management.
Integration: Spring Transaction management is easier to integrate with other data access abstractions of Spring.
Given a choice between declarative and programmatic Transaction Management, which method will you
choose?
In Spring, Declarative Transaction Management is the preferred choice. This method is very less invasive and it
has very less impact in Application Business Logic.
Although Declarative method gives less flexibility than Programmatic method, it is simpler to use and easier to
maintain in long run.
Aspect Oriented Programming (AOP) is a programming paradigm that promotes programmers to develop code
in different modules that can be parallel or in crosscutting concerns.
E.g. To develop banking software, one team can work on business logic for Money withdrawal, Money deposit,
Money Transfer etc. The other team can work on Transaction Management for committing the transaction across
multiple accounts.
In an Auto company, one team can work on software to integrate with different components of car. The other
team can work on how all the components will send signal and current information to a common dashboard.
An Aspect is the core construct of AOP. It encapsulates the behavior that affects multiple classes in a reusable
module.
In Spring AOP, what is the main difference between a Concern and a Cross cutting concern?
A Concern in Spring is the behavior or expectation from an application. It can be the main feature that we want
to implement in the application.
A Cross cutting concern is also a type of Concern. It is the feature or functionality that is spread throughout the
application in a thin way.
E.g. Security, Logging, Transaction Management etc. are cross cutting concerns in an application.
What is a Joinpoint in Spring AOP?
In Spring AOP, Joinpoint refers to a candidate point in application where we can plug in an Aspect.
This is the place where the code of an Aspect is inserted to add new behavior in the existing execution flow.
An Advice in Spring AOP, is an object containing the actual action that an Aspect introduces.
Before Advice: This type of advice runs just before a method executes. We can use @Before annotation for this.
After (finally) Advice: This type of advice runs just after a method executes. Even if the method fails, this advice
will run. We can use @After annotation here.
After Returning Advice: This type of advice runs after a method executes successfully. @AfterReturning
annotation can be used here.
After Throwing Advice: This type of advice runs after a method executes and throws an exception. The annotation
to be used is @AfterThrowing.
Around Advice: This type of advice runs before and after the method is invoked. We use @Around annotation
for this.
A Pointcut in Spring AOP refers to the group of one or more Joinpoints where an advice can be applied.
We can apply Advice to any Joinpoint. But we want to limit the places where a specific type of Advice should be
applied. To achieve this we use Pointcut.
We can use class names, method names or regular expressions to specify the Pointcuts for an Advice.
In Spring AOP we can declare additional methods or fields on behalf of a type. To do this we use an Introduction.
It is also known as inter-type declaration.
E.g. We can use an Introduction for making a bean implement IsModified interface.
What is a Target object in Spring AOP?
A Target object is the object that gets Advice from one or more Aspects.
In Spring AOP, a Proxy is an object created by the AOP framework to implement Aspect contracts. It is generally
a JDK dynamic proxy or CGLIB proxy.
BeanNameAutoProxyCreator: This is a BeanPostProcessor that creates AOP proxies for beans automatically by
matching names.
DefaultAdvisorAutoProxyCreator: This creator is more powerful that other Proxy Creators. This also applies
eligible advisors automatically to bean in the current context.
In Aspect oriented programming, linking Aspects with the other application types creates an Advised object. This
process is known as Weaving.
Without Weaving, we just have definition of Aspects. Weaving makes use realize full potential of the AOP.
Spring allows for implementing Aspect by using regular classes and XML based configurations. This is different
from Annotation based Aspect implementation. But it achieves the same goal of AOP.
We can use elements like <aop:aspect id=”testAspect" ref="testBean" /> and <aop:pointcut id="testPointcut" />
in Spring XML config file.
xsi:schemaLocation="http://www.springframework.org/schema/beanhttp://www.springframework.org/schema/
beans/spring-beans-
3.0.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-
3.0.xsd
">
This is a declarative style AOP implementation. In this case, we use annotations like @Aspect, @Pointcut,
@Joinpoint etc. to annotate code with different types of AOP elements.
This can be used Java 5 onwards, when the support for Annotations was introduced.
Spring provides its own Model View Controller (MVC) framework for developing web applications.
Spring MVC framework is based on Inversion of Control (IOC) principle. It separates the business objects from
controller.
It is designed around the DispatcherServlet that is responsible for dispatching requests to relevant handlers.
Spring MVC framework also supports annotation based binding of request parameters.
What is DispatcherServlet?
In Spring MVC, DispatcherServlet is the core servlet that is responsible for handling all the requests and
dispatching these to handlers.
Dispatcher servlet knows the mapping between the method to be called and the browser request. It calls the
specific method and combines the results with the matching JSP to create an html document, and then sends it
back to browser.
Yes, a Spring MVC web application can have more than one DispatcherServlets.
Each DispatcherServlet has to operate in its own namespace. It has to load its own ApplicationContext with
mappings, handlers, etc.
Only the root application context will be shared among these Servlets.
Controller is an interface in Spring MVC. It receives HttpServletRequest and HttpServletResponse in web app
just like an HttpServlet, but it is able to participate in an MVC flow.
Spring recommends that the implementation of Controller interface should be a reusable, thread-safe class,
capable of handling multiple HTTP requests throughout the lifecycle of an application.
Controller interprets user input and transforms it into a model. The model is represented to the user by a view.
Spring implements a controller in a very generic way. This enables us to create a wide variety of controllers.
What is @Controller annotation in Spring MVC?
The dispatcher in Spring scans for @Controller annotated classes for mapped methods and detects
@RequestMapping.
In Spring MVC, we use @RequestMapping annotation to map a web request to either a class or a handler method.
In @RequestMapping we can specify the path of URL as well as HTTP method like- GET, PUT, POST etc.
We can also map different media types produced by a controller in @RequestMapping. We use HTTP Header
Accepts for this purpose.
Clear separation of role: In Spring MVC, each role like- controller, validator, command object, form object,
model object, DispatcherServlet, handler mapping, view resolver etc. is fulfilled by a specialized object.
Reusability: Spring MVC promotes reusable business code that reduces the need for duplication. We can use
existing business objects as command or form objects instead of copying them to extend a particular framework
base class.
Flexible Model Transfer: Spring MVC Model transfer supports easy integration with other view technologies as
well.
Customizable binding and validation: In Spring MVC, we can to custom binding between Requests and
Controllers. Even validation can be done on non-String values as well.
JSP form tag library: From Spring 2.0, there is a powerful JSP form tag library that makes writing forms in JSP
pages much easier.
Customizable locale, time zone and theme resolution: Spring MVC supports customization in locale, timezone
etc.
Every bean in Spring has a scope that defines its existence timeframe in the application.
Singleton scope for bean limits a bean to a single object instance per Spring IOC container.
This single instance is limited to a specific ApplicationContext. If there are multiple ApplicationContext then we
can have more than one instance of bean.
By default all the beans in Spring framework are Singleton scope beans.
With Prototype scope a single bean definition can have multiple object instances in a Spring container.
In prototype scope bean, the Spring IoC container creates new bean instance of the object every time a request
for that specific bean is made.
How will you decide which scopePrototype or Singleton to use for a bean in Spring?
In general, we use prototype scope for all stateful beans and singleton scope for stateless beans.
Since a stateless bean does not maintain any state, we can use the same object instance again and again. Singleton
scope bean serves the same purpose.
In a stateful bean, there is a need to maintain the state in each request, it is necessary to use a new instance of
object with each call. A Prototype scope bean ensures that we get a new instance each time we request for the
object.
Partial dependency: We can inject partial dependency by using Setter injection. In Constructor injection, it is not
possible to do just a partial dependency injection.
E.g. If there are two properties in a class, we can use Setter method to inject just one property in the class.
Flexibility: Setter injection gives more flexibility in introducing changes. One can easily change the value by
Setter injection. In case of Constructor injection a new bean instance has to be created always.
Readability: Setter injection is more readable than Constructor injection. Generally Setter method name is similar
to dependency class being used in setter method.
What are the drawbacks of Setter based Dependency Injection (DI) in Spring?
Although Setter based Dependency Injection has higher priority than Constructor based DI, there are some
disadvantages of it.
No Guarantee: In Setter based DI, there is no guarantee that a certain dependency is injected or not. We may have
an object with partial or no dependency. Whereas in Constructor based DI, an object in not created till the time
all the dependencies are ready.
Security: One can use Setter based DI to override another dependency. This can cause Security breach in a Spring
application.
Circular Dependency: Setter based DI can cause circular dependency between objects. Where as Constructor
based DI will throw ObjectCurrentlyInCreationException if there is a circular dependency during the creation of
an object.
Main differences between Dependency Injection (DI) and Factory Pattern are:
Coupling: Factory pattern adds tight coupling between an object, factory and dependency. In case of DI, there is
no coupling between objects. We just mention the dependencies on different objects and container resolves and
introduces these dependencies.
Easier Testing: DI is easier to test, since we can inject the mock objects as dependency in Test environment. In
case of Factory pattern, we need to create actual objects for testing.
Flexibility: DI allows for switching between different DI frameworks easily. It gives flexibility in the choice of
DI framework.
Container: DI always needs a container for injecting the dependencies. This leads to extra overhead as well as
extra code in your application. In factory pattern, you can just use POJO classes to implement the application
without any container.
Cleaner Code: DI code is much cleaner than Factory pattern based code. In DI, we do not need to add extra code
for factory methods.
In FileSystemResource we have to give absolute path / relative path of Spring Configuration file spring-
config.xml file.
In ClassPathResource Spring looks for Spring Configuration file spring-config.xml in ClassPath. Therefore,
developer has to include spring-config.xml in classpath.
ClassPathResource looks for configuration file in CLASSPATH, whereas FileSystemResource looks for
configuration file in file system.
Spring has many Annotations to serve different purposes. For regular use we refer following popular Spring
annotations:
@Controller: This annotation is for creating controller classes in a Spring MVC project.
@RequestMapping: This annotation maps the URI to a controller handler method in Spring MVC.
@PathVariable: To map dynamic values from a URI to handler method arguments, we use this annotation.
RequestHandledEvent: This is a web specific event that informs to all beans that an HTTP request has been
serviced.
DispatcherServlet is the core of Spring MVC application. It loads Spring bean configuration file and initialize all
the beans mentioned in config file.
In case we have enabled annotations in Spring config file, it also scans the packages and configures any bean
annotated with @Component, @Controller, @Repository or @Service annotations.
Spring MVC Framework provides following mechanisms to help us achieve exception handling:
Controller Based: A developer can define exception handler methods in a Controller class. To do so, they have to
annotate the methods with @ExceptionHandler annotation.
Global Exception Handler: Spring provides @ControllerAdvice annotation for exception handling as cross-
cutting concern. We can mark any class as global exception handler by using this annotation.
We can Divide spring bean configurations based on their concerns such as spring-jdbc.xml, spring-security.xml.
It is better to avoid version numbers in schema reference. This makes sure that we have the latest config files.
It is a good practice to configure bean dependencies as much as possible. Unless there is a good reason, we try to
avoid autowiring.
For spring beans that are used in multiple contexts in Spring MVC, we can create them in root context and
initialize with listener.
Spring framework provides many features and modules. We should just use what we need for our application. An
extra dependency has to be removed
For application properties, it is good to create a property file and read it in Spring configuration file.
Annotations are useful for smaller applications, but for larger applications annotations can become an overhead.
It is easier to maintain if all the configurations are in xml files.
When we are doing AOP, we have to make sure to keep the Joinpoint as narrow as possible to avoid Advice on
unwanted methods.
We should use right annotation for components or services. For services use @Service and for DAO beans use
@Repository.
Dependency Injection (DI) has to be used when there is real benefit. It should not be used just for the sake of
loose coupling.
Spring Boot is a ready made solution to create Spring applications with production grade features. It favors
convention over configuration.
We can embed Tomcat or Jetty in in an application created with Spring Boot. Spring Boot automatically
configures Spring in an application.
It does not require any code generation or xml configuration. It is an easy solution to create applications that can
run stand-alone.
Hibernate
Hibernate is a popular Object Relational Mapping (ORM) framework of Java. It helps in mapping the Object
Oriented Domain model to Relational Database tables.
In simple words, it is a framework to retrieve and store data from database tables from Java.
Object Relational Mapping (ORM) is a programming technique to map data from a relational database to Object
oriented domain model. This is the core of Hibernate framework.
In case of Java, most of the software is based on OOPS design. But the data stored in Database is based on
Relation Database Management System (RDBMS).
ORM helps in data retrieval in an Object Oriented way from an RDBMS. It reduces the effort of developers in
writing queries to access and insert data.
Configuration interface can be implemented in an application to specify the properties and mapping documents
for creating a SessionFactory in Hibernate.
Configuration is mainly an initialization time object that loads the properties in helps in creating SessionFactory
with these properties.
Object Relational Impedance Mismatch (ORIM) is also known as paradigm mismatch. It means that Object model
and Relational model do not work well with each other.
Relational model or a RDBMS represents data in tabular format like a spreadsheet. Object model or OOPS
represents the data as an inter-connected graph of objects.
Mixing these two models leads to various problems. The common name for these issues is Object Relational
Impedance Mismatch.
Object model and Relational models (RDBMS) have following problems that are part of Object Relational
Impedance Mismatch:
Granularity: Object model is more granular than Relational model. There are more classes in object model than
the corresponding tables in relational model.
Inheritance: Object model supports inheritance. But Relational model does not have any concept of inheritance.
Identity: Relational model has just one criteria for sameness of data. It is based on primary key. In object model
like Java we can have equals as well as == for sameness of objects.
Associations: In Object model associations are uni-directional. In RDBMS, there is a concept of foreign key for
association. Also multiplicity of a relationship is hard to judge by looking at object model.
Data navigation: In Object model, you can move from one object to another object for getting data. Egg. you can
retrieve and Employee object, then go to its department object and then get the employees in the department
object. In RDBMS, we try to minimize the SQL calls, so we get all the data by using joins.
Object/Relational Mapping (ORM): Hibernate provides ORM capabilities to developers. So then can write code
in Object model for connecting with data in Relational model.
JPA Provider: Hibernate provides an excellent implementation of Java Persistence API (JPA) specification.
Idiomatic persistence: Hibernate provides persistence based on natural Object-oriented idioms with full support
for inheritance, polymorphism, association, composition, and the Java collections framework. It can work with
any data for persistence.
High Performance: Hibernate provides high level of performance supporting features like- lazy initialization,
multiple fetching strategies, optimistic locking etc. Hibernate does not need its own database tables or fields. It
can generate SQL at system initialization to provide better performance at runtime.
Scalability: Hibernate works well in multi server clusters. It has built in scalability support. It can work well for
small projects as well as for large business software.
Reliable: Hibernate very reliable and stable framework. This is the reason for its worldwide acceptance and
popularity among developer community.
Extensible: Hibernate is quite generic in nature. It can be configured and extended as per the use case of
application.
Configuration: Configuration interface can be implemented in an application to specify the properties and
mapping documents for creating a SessionFactory in Hibernate. Hibernate application bootstraps by using this
interface.
SessionFactory: In Hibernate, SessionFactory is used to create and manage Sessions. Generally, there is one
SessionFactory created for one database. It is a thread-safe interface that works well in multithreaded applications.
Session: Session is a lightweight object that is used at runtime between a Java application and Hibernate. It
contains methods to create, read and delete operations for entity classes. It is a basic class that abstracts the
concept of persistence.
Transaction: This is an optional interface. It is a short lived object that is used for encapsulating the overall work
based on unit of work design pattern. A Session can have multiple Transactions.
Query: This interface encapsulates the behavior of an objectoriented query in Hibernate. It can accept parameters
and execute the queries to fetch results. Same query can be executed multiple times.
Criteria: This is a simplified API to retrieve objects by creating Criterion objects. It is very easy to use for creating
Search like features.
How will you map the columns of a DB table to the properties of a Java class in Hibernate?
We can map the class properties and table columns by using one of the two ways:
Annotation: We can also use annotations @Entity and @Table to map a column to the property of a class.
Does Hibernate make it mandatory for a mapping file to have .hbm.xml extension?
No. It is a convention to have.hbm.xml extension in the name of a mapping file. It is not a requirement enforced
by Hibernate. We can use any other extension of our convenience for this.
Configuration: First create a Configuration object. This will refer to the path of configuration file.
Resource: Add config file resource to Configuration object.
Properties: Set properties in the Configuration object.
SessionFactory: Use Configuration object to build SessionFactory.
Egg.
POJO stands for Plain Old Java Objects. A POJO is java bean with getter and setter methods for each property of
the bean.
It is a simple class that encapsulates an object’s properties and provides access through setters and getters.
POJO emphasizes the fact that this class is a simple Java class, not a heavy class like EJB.
Hibernate Query Language is also known as HQL. It is an Object Oriented language. But it is similar to SQL.
HQL works well with persistent objects and their properties. HQL does not work on database tables.
HQL queries are translated into native SQL queries specific to a database.
HQL supports direct running of native SQL queries also. But it creates an issue in Database portability.
Hibernate supports executing not only simple queries but also stored procedure of database. There are three ways
to call a stored procedure in Hibernate:
<sql-query name="callEmployeeStoreProcedure">
<return alias="employee"
class="com.testHibernate.util.Employee"/>
<![CDATA[CALL GetEmployees(:employeeId)]]>
</sql-query>
</hibernate-mapping>
We can call it with getNamedQuery().
Use annotation:
We can also mark out stored procedure with
@NamedNativeQueries annotation.
//Employee.java
Query query =
session.getNamedQuery("callEmployeeStoreProcedure") .setParameter("employeeId", “1234”);
List result = query.list(); for(int i=0; i<result.size(); i++){
Employee employee = (Employee)result.get(i);
System.out.println(employee.getEmployeeCode());
}
Criteria is a simplified API in Hibernate to get entities from database by creating Criterion objects.
It is a very intuitive and convenient approach for search features. Users can specify different criteria for searching
entities and Criteria API can handle these.
This is a trap question. HibernateTemplate has been deprecated. There were earlier good reasons to use
HibernateTemplate. But now the trend has changed towards not using it anymore.
How can you see SQL code generated by Hibernate on console?
To display the SQL generated by Hibernate, we have to turn on the show_sql flag.
<property name=”show_sql”>true</property>
Save method first stores an object in the database. Then it persists the given transient instance by assigning a
generated identifier. Finally, it returns the id of the entity that is just created.
SaveOrUpdate() method calls either save() or update() method. It selects one of these methods based on the
existence of identifier.
If an identifier exists for the entity then update() method is called. If there is no identifier for the entity then save()
method is called as mentioned earlier.
Database Portability: Hibernate can be used with multiple types of database with easy portability. In JDBC,
developer has to write database specific native queries. These native queries can reduce the database portability
of the code.
Complexity: Hibernate handles complex query scenarios very well with its internal API like Criteria. So developer
need not gain expertise in writing complex SQL queries. In JDBC application developer writes most of the
queries.
In Hibernate we can get the statistics of a SessionFactory by using Statistics interface. We can get information
like Close Statement count, Collection Fetch count, Collection Load count, Entity insert count etc.
When an object is just instantiated using the new operator but is not associated with a Hibernate Session, then the
object is in Transient state.
In Transient state, object does not have a persistent representation in database. Also there is no identifier assigned
to an object in Transient state.
An object in Transient state can be garbage collected if there is no reference pointing to it.
An object is in detached state if it was persistent earlier but its Session is closed now.
Any reference to this object is still valid. We can even update this object. Later on we can even attach an object
in detached state to a new session and make it persistent.
Detached state is very useful in application transactions where a user takes some time to finish the work.
Dirty Checking is very useful feature of Hibernate for write to database operations. Hibernate monitors all the
persistent objects for any changes. It can detect if an object has been modified or not.
By Dirty Checking, only those fields of an object are updated that require any change in them. It reduces the time-
consuming database write operations.
Callback interface in Hibernate is mainly used for receiving notifications of different events from an object.
Egg. We can use Callback to get the notification when an object is loaded into or removed from database.
Pure Relational ORM: At this level entire application is designed around the relational model. All the operations
are SQL based at this level.
Light Object Mapping: At this level entity classes are mapped manually to relational tables. Business logic code
is hidden from data access code. Applications with less number of entities use this level.
Medium Object Mapping: In this case, application is designed around an object model. Most of the SQL code is
generated at compile time. Associations between objects are supported by the persistence mechanism. Object-
oriented expression language is used to specify queries.
Full Object Mapping: This is one of the most sophisticated object modeling level. It supports composition,
inheritance, polymorphism and persistence. The persistent classes do not inherit any special base class at this
level. There are efficient fetching and caching strategies implemented transparently to the application.
XML based: We can define the Hibernate configuration in an XML file like ibernate.cfg.xml file
Programming based: We can also use code logic to configure Hibernate in our application.
Hibernate provides Query Cache to improve the performance of queries that run multiple times with same
parameters.
At times Query Caching can reduce the performance of Transactional processing. By default Query Cache is
disabled in Hibernate.
It has to be used based on the benefits gained by it in performance of the queries in an application.
Many to one
One to one
One to many
A Unit of Work is a list of ordered operations that we want to run on a database together. Either all of these go
together or none of these goes.
Most of the time, we use term business transaction in place of Unit of Work.
Egg. In case of money transfer from account A to B, the unit of work can be two operation Debit account A and
Credit account B in a sequence. Both these operations should happen together and in right sequence.
Once the session attached to an Object is closed, the object goes into Detached state. An Object in Detached state
can be attached to another session at a later point of time.
This state is quite useful in concurrent applications that have long unit of work.
Hibernate provides an Order criterion that can be used to order the results. This can be order objects based on
their property in ascending or descending order.
Class is org.hibernate.criterion.Order.
Egg.
In Hibernate, we can create an object with desired properties. Then we can use this object to search for objects
with similar object. For this we can use org.hibernate.criterion.Example criterion.
Egg. First we create a sample book object of author Richard and category mystery. Then we search for similar
books.
In Hibernate we use Session interface to get a new transaction. Once we get the transaction we can run business
operations in that transaction. At the end of successful business operations, we commit the transaction. In case of
failure, we rollback the transaction.
In Hibernate, by default an entity or collection is mutable. We can add, delete or update an entity/collection.
XML file: We can also set the property mutable=false in the XML file for an entity to make it immutable.
What are the different options to retrieve an object from database in Hibernate?
In Hibernate, we can use one of the following options to retrieve objects from database:
Identifier: We can use load() or get() method and pass the identifier like primary key to fetch an object from
database.
HQL: We can create a HQL query and get the object after executing the query.
Criteria API: We can use Criteria API to create the search conditions for getting the objects from database.
Native SQL: We can write native SQL query for a database and just execute it to get the data we want and convert
it into desired object.
We can use the primary key generation strategy of type GenerationType.AUTO to auto-generate primary key
while persisting an object in Hibernate.
Egg.
@Id
@GeneratedValue(strategy=GenerationType.AUTO) private int id;
We can leave it null/0 while persisting and Hibernate automatically generates a primary key for us.
A Hibernate Session is the first level of cache for persistent data in a transaction.
In Hibernate, we can use different cache providers for implementing second level cache at JVM/SessionFactory
level.
Hashtable
EHCache
OSCache
SwarmCache
JBoss Cache 1.x
JBoss Cache 2
Which is the default transaction factory in Hibernate?
In Hibernate, default transaction factory is JDBCTransactionFactory. But we can change it by setting the property
hibernate.transaction.factory_class.
This is a trick question. By default Second level cache is already disabled in Hibernate.
In case, your project is using a second level cache you can use one of the following options to disable second
level cache in Hibernate:
Hibernate 3 onwards there are following fetching strategies to retrieve associated objects:
Join fetching: In Join strategy Hibernate uses OUTER join to retrieve the associated instance or collection in the
same SELECT.
Select fetching: In Select strategy, Hibernate uses a second SELECT to retrieve the associated entity or collection.
We can explicitly disable lazy fetching by specifying lazy="false". By default lazy fetching is true.
Subselect fetching: In Subselect strategy, Hibernate uses a second SELECT to retrieve the associated collections
for all entities retrieved in a previous query or fetch.
Batch fetching: In Batch strategy, Hibernate uses a single SELECT to retrieve a batch of entity instances or
collections by specifying a list of primary or foreign keys. This is a very good performance optimization strategy
for select fetching.
What is the difference between Immediate fetching and Lazy collection fetching?
In Immediate fetching an association, collection or attribute is retrieved at the same time when the owner is
loaded.
But in Lazy collection fetching, a collection is fetched only when an operation is invoked on that collection by
client application.
In Extra lazy fetching, only individual elements of a collection are fetched from the database when they are
required.
In this strategy, Hibernate does not fetch the whole collection into memory unless it is essential.
It is a good fetching strategy for large collections of objects.
How can we check is a collection is initialized or not under Lazy Initialization strategy?
Hibernate provides two convenient methods, Hibernate.initialize() and Hibernate.isInitialized() to check whether
a collection is initialized or not.
Read only: If an application requires caching only for read but not for write operations, then we can use this
strategy. It is very simple to use and give very good performance benefit.
Read/Write: If an application also needs caching for write operations, then we use Read/Write strategy.
Read/write cache strategy should not be used if there is requirement for serializable transaction isolation level.
Nonstrict Read/Write: If an application only occasionally updates the data, then we can use this strategy. It cannot
be used in systems with serializable transaction isolation level requirement.
Transactional: This strategy supports full transactional cache providers like JBoss TreeCache.
A Bag in Hibernate is an unordered collection. It can have duplicate elements. When we persist an object in a
bag, there is no guarantee that bag will maintain any order.
A Set in Hibernate can only store unique objects. If we add the same element to set second time, it just replaces
the old one. By default a Set is unordered collection in Hibernate.
Monitoring SessionFactory: Since there is one SessionFactory in an application, we can collect the statistics of a
SessionFactory to monitor the performance. Hibernate provides sessionFactory.getStatistics()
method to get the statistics of SessionFactory.
Metrics: In Hibernate we can also collect other metrics likenumber of open sessions, retrieved JDBC connections,
cache hit, miss etc.
These metrics give great insight into the performance of Hibernate. We can tune Hibernate settings and strategies
based on these metrics.
How can we check if an Object is in Persistent, Detached or Transient state in Hibernate?
Persistent State: If call to EntityManager.contains(object) returns true, the object is in Persistent state.
Transient State: If call to PersistenceUnitUtil.getIdentifier(object) returns null then object is in Transient state.
Let us consider an example in which a customer can have multiple orders and for every order there has to be a
customer.
In OO world, customer is the owner of order. In SQL world, an Order has reference to customer id.
The inverse side in this mapping is the owner of object. In this case customer is the owner or order. Since an order
cannot exist without a customer. But a customer can exist without an order.
Also customer has no column to save order data. But an Order table can store customer id, which is used for
mapping.
ORM uses metadata for its internal work. ORM maintains metadata to generate code used for accessing columns
and tables.
Application developers can also access Hibernate Metadata by using ClassMetadata and CollectionMetadata
interfaces and Type hierarchy.
The main difference is that load() method will throw an ObjectNotFoundException if row corresponding to an
object is not found in the database.
On the other hand, get() method returns null value when an object is not found in the database.
It is recommended that we should use load() method only when we are sure that object exists in database.
When should we use get() method or load() method in Hibernate?
We should use get() method when we want to load an object. We should use load() method when we need a
reference to an object without running extra SQL queries.
A Named SQL query is the HQL query that is associated with a string name and can be referenced in the
application by name.
There are two popular locking strategies that can be used in Hibernate:
Optimistic: In Optimistic locking we assume that multiple transactions can complete without affecting each other.
So we let the transactions do their work without locking the resources initially.
Just before the commit, we check if any of the resource has changed by another transaction, then we throw
exception and rollback the transaction.
Pessimistic: In Pessimistic locking we assume that concurrent transactions will conflict while working with same
resources. So a transaction has to first obtain lock on the resources it wants to update.
The other transaction can proceed with same resource only after the lock has been released by previous
transaction.
Version number is used in optimistic locking in Hibernate. When a transaction modifies an object, it increments
its version. Based on version number, second transaction can determine if the object it has read earlier has changed
or not.
If the version number at the time of write is different than the version number at the time of read, then we should
not commit the transaction.
Hibernate supports following inheritance mapping strategies between classes and tables:
Table per class hierarchy: In case of multiple types of books, we can have one book class and one book table. We
can store all child classes of book like- HardCoverBook, PaperBackBook etc in same table book. But we can
identify the subclasses by a BookType column in Book table.
Table per subclass: In this case we can have separate table for each kind of book. HardCoverBook table for
HardCoverBook book class. PaperBackBook table for PaperBackBook book class. And there will be a parent
table, Book for Book class.
Table per concrete class: In this case also we have separate table for each kind of book. But in this case we have
even inherited properties defined inside each table. There is no parent table Book for Book class, since it is not a
concrete class.
Maven
269.What is Maven?
Maven is a software project management tool. It is open source software from Apache software foundation.
It is used for building, reporting and documenting a Software project. It is mainly based on POM (Project Object
Model).
Simple: Maven provides simple project setup that is based on best practices.
Fast: You can get a new project or module started in a few seconds in Maven.
Easy to learn: Maven usage and commands are easy to learn across all projects. Therefore ramp up time for new
developers coming onto a project is very less.
Dependency management: Maven provides superior dependency management including automatic updates and
transitive dependencies.
Multiple Projects: You can easily work with multiple projects at the same time by using Maven.
Large Library: Maven has a large and growing repository of libraries and metadata to use out of the box.
Extensible: Maven supports the ability to easily write plugins in Java or scripting languages for extending its
core functionality.
Instant: Maven is online and it provides instant access to new features with very less configuration.
Build
Testing
Release
Reporting
Software Change Management (SCM)
Documentation
Distribution
Common Project Structure: By using Maven, every developer has a common project structure that helps in
understanding the code as well as developing new features in a new project.
Modular Design: Maven promotes modular design that divides a complex project into multiple modules that are
easier to manage. By using Maven, it is easier to manage multiple modules for build, test, release etc.
Centralized Dependency Management: With Maven, each developer does not have to include the jars
separately in each project or module. Maven provides a centralized dependency management that can help
improve efficiency of software development.
Fewer Decisions: With Maven a developer has to make fewer decisions about things unrelated to software
development work. The project structure comes ready with Maven, dependency management is a uniform
approach and build/release are handled by Maven. So a developer can focus on core work of developing software.
Convention over configuration is a Software Design Paradigm that decreases the number of decisions made by a
software developer, without losing flexibility.
In Maven, there are many conventions for setting up the project, building the artifacts, running unit tests and
releasing the code. These conventions lead to common process for Software development.
In case of other tools, there are a lot of configuration options are present. But most of the time, a developer uses
same set of configuration options. So it is better to make these as a default options. Maven uses default options
from best practices and provides right conventions for Software development.
Source Code: A Build tool can generate source code based on templates.
Documentation: We can get documentation files from source code by using a build tool. E.g. Javadoc
Compilation: Primary responsibility of a Build tool is to compile source code into executable code.
Packaging: A Build tool packages compiled code into a deployable file like- jar, zip war etc.
Deployment: We can deploy the packaged code on server by using a Build tool.
Ant is a Java library and command line toolbox for build process. Maven is a framework for many aspects of
software development like- project setup, compile, build, documentation etc.
Ant does not have any conventions for project structure or build processes. Maven has conventions for setting up
project structure as well as for build processes.
Ant is based on procedural programming. We have to write code for compilation build, copy etc. Maven is based
on declarative programming. We have to just configure it for our project setup and programming.
Ant does not impose any lifecycle. We need to create the sequence of tasks manually. Maven has a lifecycle for
software build processes. There are well-defined phases that we can use in Maven.
Ant scripts are not reusable in multiple projects. Maven has plugins that are reusable across multiple projects.
Every MOJO is an executable goal in Maven. It is like an annotated Java class. It specifies metadata about a goal
like- goal name, phase of lifecycle for goal and parameters required by goal.
A repository is a location on file system where build artifacts, jars, dependencies and pom.xml files are stored.
What are the different types of repositories in Maven?
Local Repository: This is your local folder in which a copy of your installation and dependencies is stored.
Remote Repository: This is a remote folder in which jars and other build artifacts are stored. These can be located
on servers within your organization.
Central Remote Repository: This is the central Maven repository that is located on repo.maven.apache.org or
uk.maven.org or any other third party location. This where we can find artifacts from different providers that are
available for download and use. Like- Hibernate, Spring libraries etc.
Maven local repository is a folder in your local files system in which your project’s installation, dependency jars,
plugins etc. are stored.
Default location of Maven local repository is .m2 folder. It can be located under following location on file system:
Maven central repository is a truly remote repository that is located on repo.maven.apache.org or uk.maven.org
or any other third party location.
This contains the jars and artifacts provided by various software providers.
Central repository contains a large amount of data. Therefore it is not allowed to scrape the whole site. But you
can use the relevant jars that you want for download and use in your Maven project.
A Remote repository is a remote location on the internet where the jars and dependencies from different vendors
are stored.
These can be truly remote repositories set up by third party vendors or locations inside your organization that
contains the relevant jars required by your project.
Why we should not store jars in CVS or any other version control system instead of Maven repository?
Maven recommends storing jars in local repository instead of CVS or any other version control system. There are
following advantages of storing it in Maven repo vs. CVS:
Less Storage: A repository is very large, but it takes less space because each JAR is stored only in one place. E.g.
If we have 10 modules dependent on Spring jar, then they all refer to same Spring jar stored in local repository.
Quicker Checkout: Project checkout is quicker from local repository, since there is not need to checkout jars if
they are already present in repo.
No need for versioning: There is no need to version JARS since external dependencies do not change so often.
No, we need special permissions to upload JARS and artifacts to Central Maven Repository?
What is a POM?
POM is an abbreviation for Project Object Model. This is the basic unit of work in Maven. It is an XML file with
name pom.xml.
It contains details of project and project configuration that are used by Maven to build the project.
It also contains default values for many projects. E.g. target is the name of build directory for Java Maven project.
Super POM is Maven’s default POM. All the POM files extend from Super POM.
project root
modelVersion
groupID: the id of the project's group.
artifactID: the id of the artifact (project)
version: the version of the artifact under the specified group
In Maven, each build lifecycle consists of many phases. Default build lifecycle has following phases:
validate: In this phase, Maven validates that the project is correct and all necessary information is available to
run next phase.
compile: Maven compiles the source code of the project in this phase.
test: This is the phase to run unit tests on the compiled source. There should not be any need to package or deploy
the code to run these tests.
package: In this phase, Maven takes the compiled code and packages it in its distributable format, such as a JAR.
verify: Maven runs any checks on results of integration tests to ensure that quality criteria are met.
install: In this phase, Maven installs the package into local repository. After this it can be used as a dependency
in other projects locally.
deploy: In the build environment, Maven copies the final package to the remote repository for sharing with other
developers and projects.
mvn -package
<groupId>:<artifactId>:<version>
Parent pom
E.g. org.Orgname.Projectname:org.Orgname.Projectname-1.0.0.pom
Modules
E.g.
org.Orgname.Projectname:org.Orgname.Projectname.Modulename1.0.0.jar
What is an Archetype in
Maven?
By using an Archetype, an author of Archetype can create a Project template. Users of this project template
(archetype) can pass different parameters to this template and start using it.
Archetype promotes consistency in the process of creating and working on a project. It also helps in reducing the
ramp up time for new developers to come on board on a project.
mvn archetype:generate
Maven has following three build lifecycles that further contain multiple phases:
clean: In this lifecycle any files generated by previous builds are removed.
default: This lifecycle is used for validating, compiling and creating the application. It has multiple phases
likecompile, test, package inside it.
site: Maven generates and deploys the documentation of a site in this phase.
Maven is mainly a plugin execution framework. At the code of Maven all the work is done by plugins. A Maven
plugin can be used for following purposes:
Maven Help Plugin has a describe goal. This can be used for listing the version of a plugin. Sample command for
this is:
Note: In the above command replace Dplugin with the plugin prefix as the argument. Do not use the artifact ID
of plugin here.
What are the different types of profile in Maven? Where will you define these profiles?
Per Project
It is defined in the POM itself (pom.xml).
Per User
We can define it in the Maven-settings
(%USER_HOME%/.m2/settings.xml).
Global
It is defined in the global Maven-settings
(${maven.home}/conf/settings.xml).
Profile descriptor
Descriptor is located in project basedir (profiles.xml) (It is not supported in Maven 3.0)
What are the different setting files in Maven? Where will you find these files?
Maven is very simple to use. At the core it has a setting file names settings.xml. This file contains the setting
element that is used to configure the Maven with different options.
In settings.xml we can have all the configuration information for Maven. Some of the important elements are:
localRepository: The value of this element is the path of this build system’s local repository. The default value
is
${user.home}/.m2/repository.
It is used for a main build server to allow all logged-in users to build from a common local repository.
interactiveMode: If it is true then Maven should attempt to interact with the user for input. If it is false then
Maven does not interact with the user. Default setting is true.
offline: If it is true this build system should be able to operate in offline mode. By default it is false. This element
is used for build servers that cannot connect to a remote repository due to network setup or security reasons.
We can use following command in console to check the version of Maven in our system.
mvn -version
To check this, type mvn –version in cmd prompt of Windows. This will give you the version of Maven installed
on Windows.
A Maven artifact is a file that gets deployed to a Maven repository. In most cases it is a JAR file.
When Maven build runs, it creates one or more artifacts. In case of Java projects, it produces a compiled jar and
a sources jar.
Every artifact in Maven has a group ID, an artifact ID and a version string. These three attributes uniquely identify
an artifact.
compile: This is the default dependency scope in Maven. The compile level dependencies are available in all
classpaths of a project. These dependencies are also propagated to dependent projects.
provided: This scope is similar to compile. But in this scope we expect the JDK or a container to provide the
dependency at runtime. E.g. While building a web application for the Java Enterprise Edition, we can set the
dependency on the Servlet API and related Java EE APIs to scope provided. The web container will provide these
classes at runtime to our application.
This scope is only available on the compilation and test classpath, and is not transitive.
runtime: The dependency in this scope is not required for compilation. It is required for execution. It is available
in the runtime and test classpaths. It is not present in the compile classpath.
test: This scope is used for dependencies that are required for test compilation and execution phases. This scope
is not transitive.
system: This scope is same as provided scope, except that you have to provide the JAR that contains it explicitly.
In this case, he artifact is always available. There is no need to look it up in a repository.
import: This scope is only used on a dependency of type pom in the <dependencyManagement> section. In this
case, the specified POM has to be replaced with the dependencies in that POM's <dependencyManagement>
section. This scope is only available in Maven 2.0.9 or later.
To exclude a dependency we can add the <exclusions> tag under the <dependency> section of the pom.
E.g.
<dependencies>
<dependency>
<groupId>test.ProjectX</groupId>
<artifactId>ProjectX</artifactId>
<version>1.0</version>
<scope>compile</scope>
<exclusions>
<exclusion> <!-- exclusion is mentioned here -->
<groupId>test.ProjectY</groupId>
<artifactId>ProjectY</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
Maven first looks for a JAR related to a dependency in the local repository. If it finds it there then it stops.
If it does not find it in local repo, it looks for the JAR in the remote repository and downloads the corresponding
version of JAR file. From remote repository it stores the JAR into local repository.
Let say you have a Project A that depends on dependency B. The dependency B further depends on dependency
C. So your dependency C is a Transitive Dependency of your project A.
In Maven, starting from 2.0, you do not have to specify transitive dependencies. You just mention your immediate
dependencies in pom.xml.
Maven takes care of resolving the Transitive dependencies and includes them automatically.
Let say a project A depends on project B, and project B depends on project C. The developers of project A can
explicitly exclude project C as a dependency. We can use the "exclusion" element to exclude it.
Let say a project B depends on project C. The developers of project B can mark project C as an optional
dependency by using the "optional" element.
In case project A depends on project B, A will depend only on B and not on B's optional dependency C.
The developers of project A may then explicitly add a dependency on C. The dependency of B on C is known as
Optional dependency in Maven.
Where will you find the class files after compiling a Maven project successfully?
Once Maven completes the compilation successfully, it stores the files in target folder. The default location for
class files is:
${basedir}/target/classes/
What are the default locations for source, test and build directories in Maven?
Source: src/main/java
Test: src/main/test
Build: Target
In Maven, jar:jar goal creates a jar file in the Maven build directory. Jar file is create with the name format
${project.id}${project.currentVersion}.jar.
The id and currentVersion are mentioned in the project.xml of the project being built.
jar:jar does not recompile sources. It just creates a jar from already compiled classes.
How can we get the debug or error messages from the execution of
Maven?
At times, project build or compile fails in Maven. At this time it is very helpful to see the debug or error messages
from Maven execution.
What is the difference between a Release version and SNAPSHOT version in Maven?
A SNAPSHOT version in Maven is the one that has not been released.
If we download 1.0-SNAPSHOT today then we may get different set of files than the one we get on downloading
it yesterday. SNAPSHOT version can keep getting changes in it since it is under development.
But release version always gives exactly same set files with each download.
or
Sometimes Maven compiles the test classes but doesn't run them? What could be the reason for it?
We can configure it to run certain test classes. Sometimes we you may have unintentionally specified an incorrect
value to ${test} in settings.xml or pom.xml.
Yes, Maven gives us the flexibility of creating our own directory structure. We just need to configure the elements
like
<sourceDirectory>, <resources> etc. in the <build> section of pom.xml.
Gradle is nowadays getting more popular. Google uses it for Android development and release. Companies like
LinkedIn also use Gradle.
Gradle gives more flexibility to do custom tasks similar to ANT. Maven scripts have predefined structure. So it
is less flexible.
Maven is mainly used for Java based systems. Gradle is used for a variety of languages. It is a Polyglot build tool.
In Maven, we can create a parent project that will pass its values to its children projects.
A multi-module project is created to manage a group of other subprojects or modules. The multi-module
relationship is like a tree that starts from the topmost level to the bottom level. In a multimodule project, we
specify that a project should include the specific modules for build. Multi-module builds are used to group
modules together in a single build.
Whereas in Inheritance, the parent-child project relationship starts from the leaf node and goes upwards. It deals
more with the definition of a specific project. In this case a child’s pom is derived from its parent’s pom.
A build that does not require any custom configuration or customization of properties files is more portable than
a build that requires a lot of custom work to build it from scratch.
Open source projects from Apache Commons are one of the most portable projects. These build can work just
out of the box.
GIT
319. How can we see n most recent commits in GIT?
We can use git log command to see the latest commits. To see the three most recent commits we use following
command:
git log -3
git branch --merged master : This prints the branches merged into master
git branch --merged lists : This prints the branches merged into
HEAD (i.e. tip of current branch)
git branch --no-merged : This prints the branches that have not been merged
In case we do not need a specific stash, we use git stash drop command to remove it from the list of stashes.
To remove a specific stash we specify as argument in the git stash drop <stashname> command.
At any given time, one head is selected as the ‘current head’ This head is also known as HEAD (always in
uppercase).
What is the most popular branching strategy in GIT?
There are many ways to do branching in GIT. One of the popular ways is to maintain two branches:
master: This branch is used for production. In this branch HEAD is always in production ready state.
develop: This branch is used for development. In this branch we store the latest code developed in project. This
is work in progress code.
Once the code is ready for deployment to production, it is merged into master branch from develop branch.
What is SubGit?
SubGit is software tool used for migrating SVN to Git. It is very easy to use. By using this we can create a writable
Git mirror of a Subversion repository.
It creates a bi-directional mirror that can be used for pushing to Git as well as committing to Subversion.
It sets up the gitweb and a web-server that makes the working repository available online.
Git hooks are scripts that can run automatically on the occurrence of an event in a Git repository. These are used
for automation of workflow in GIT.
What is GIT?
GIT is a mature Distributed Version Control System (DVCS). It is used for Source Code Management (SCM).
It is open source software. It was developed by Linus Torvalds, the creator of Linux operating system.
It contains a sub-directory called .git. There is only one .git directory in the root of the project.
In .git, GIT stores all the metadata for the repository. The contents of .git directory are of internal use to GIT.
Distributed System: GIT is a Distributed Version Control System (DVCS). So you can keep your private work in
version control but completely hidden from others. You can work offline as well.
Flexible Workflow: GIT allows you to create your own workflow. You can use the process that is suitable for
your project. You can go for centralized or master-slave or any other workflow.
Fast: GIT is very fast when compared to other version control systems.
Data Integrity: Since GIT uses SHA1, data is not easier to corrupt.
Free: It is free for personal use. So many amateurs use it for their initial projects. It also works very well with
large size project.
Collaboration: GIT is very easy to use for projects in which collaboration is required. Many popular open source
software across the globe use GIT.
GIT has very few disadvantages. These are the scenarios when GIT is difficult to use. Some of these are:
Binary Files: If we have a lot binary files (non-text) in our project, then GIT becomes very slow. E.g. Projects
with a lot of images or Word documents.
Steep Learning Curve: It takes some time for a newcomer to learn GIT. Some of the GIT commands are non-
intuitive to a fresher.
Slow remote speed: Sometimes the use of remote repositories in slow due to network latency. Still GIT is better
than other VCS in speed.
Decentralized: GIT is decentralized. You have a local copy that is a repository in which you can commit. In SVN
you have to always connect to a central repository for check-in.
Complex to learn: GIT is a bit difficult to learn for some developers. It has more concepts and commands to learn.
SVN is much easier to learn.
Unable to handle Binary files: GIT becomes slow when it deals with large binary files that change frequently.
SVN can handle large binary files easily.
Internal directory: GIT creates only .git directory. SVN creates .svn directory in each folder.
User Interface: GIT does not have good UI. But SVN has good user interfaces.
We use git init command in an existing project directory to start version control for our project.
After this we can use git add and git commit commands to add files to our GIT repository.
In GIT, we use git clone command to create a copy of an existing GIT repository in our local.
This is the most popular way to create a copy of the repository among developers.
It is similar to svn checkout. But in this case the working copy is a full-fledged repository.
To create a new repository in GIT, first we create a directory for the project. Then we run ‘git init’ command.
Now, GIT creates .git directory in our project directory. This is how our new GIT repository is created.
Most of the GIT distributions are written in C language with Bourne shell. Some of the commands are written in
Perl language.
In GIT, git pull internally does a git fetch first and then does a git merge.
We use git pull command to bring our local branch up to date with its remote version.
fetch: First GIT, copies all the extra commits from server into local repo and moves origin/master branch pointer
to the end of commit chain.
merge: Then it merges the origin/master branch into the master branch. Now the master branch pointer moves to
the newly created commit. But the origin/master pointer remains there.
In GIT, sometimes we do not want to commit our code but we do not want to lose also the unfinished code. In
this case we use git stash command to record the current state of the working directory and index in a stash. This
stores the unfinished work in a stash, and cleans the current branch from uncommitted changes.
Now we can work on a clean working directory.
Later we can use the stash and apply those changes back to our working directory.
At times we are in the middle of some work and do not want to lose the unfinished work, we use git stash
command.
In GIT, stage is a step before commit. To stage means that the files are ready for commit.
Let say, you are working on two features in GIT. One of the features is finished and the other is not yet ready.
You want to commit and leave for home in the evening. But you can commit since both of them are not fully
ready. In this case you can just stage the feature that is ready and commit that part. Second feature will remain as
work in progress.
We can set the configuration options for GIT installation by using git config command.
We can use ‘git config --list’ command to print all the GIT configuration settings in GIT installation.
SHA1 name: A 40 character string to identify a commitFiles: List of files that represent the state of a project at a
specific point of time
Reference: Any reference to parent commit objects
If we are simultaneously working on multiple tasks, projects, defects or features, we need multiple branches. In
GIT we can create a separate branch for each separate purpose.
Let say we are working on a feature, we create a feature branch for that. In between we get a defect to work on
then we create another branch for defect and work on it. Once the defect work is done, we merge that branch and
come back to work on feature branch again.
So working on multiple tasks is the main reason for using multiple branches.
What are the different kinds of branches that can be created in GIT?
Hotfix branches: These are used for releasing a hotfix to production for a defect or emergency fix.
We do the development work on a feature branch that is created from master branch. Once the development work
is ready we use git merge command to merge it into master branch.
A pull request in GIT is the list of changes that have been pushed to GIT repository. Generally these changes are
pushed in a feature branch or hotfix branch. After pushing these changes we create a pull request that contains
the changes between master and our feature branch. This pull request is sent to reviewers for reviewing the code
and then merging it into develop or release branch.
A merge conflict in GIT is the result of merging two commits. Sometimes the commit to be merged and current
commit have changes in same location. In this scenario, GIT is not able to decide which change is more important.
Due to this GIT reports a merge conflict. It means merge is not successful. We may have to manually check and
resolve the merge conflict.
When GIT reports merge conflict in a file, it marks the lines as follows:
E.g.
the business days in this week are
<<<<<<< HEAD
five
=======
six
>>>>>>> branch-feature
To resolve the merge conflict in a file, we edit the file and fix the conflicting change. In above example we can
either keep five or six.
After editing the file we run git add command followed by git commit command. Since GIT is aware that it was
merge conflict, it links this change to the correct commit.
After the successful merge of feature branch in main branch, we do not need the feature branch.
What command will you use to delete a branch that has unmerged changes?
To forcibly delete an unwanted branch with unmerged changes, we use following command:
Rebasing is the process of moving a branch to a new base commit. It is like rewriting the history of a branch.
In Rebasing, we move a branch from one commit to another. By this we can maintain linear project history.
Once the commits are pushed to a public repository, it is not a good practice to use Rebasing.
The golden rule of Rebasing is that we should never use git rebase on public branches. If other people are using
the same branch then they may get confused by looking at the changes in Master branch after GIT rebasing.
Therefore, it is not recommended to do rebasing on a public branch that is also used by other collaborators.
By using Interactive rebasing we can alter the commits before moving them to a new branch.
This is more powerful than an automated rebase. It gives us complete control over the branch’s commit history.
Generally, we use Interactive Rebasing to clean up the messy history of commits just before merging a feature
branch into master.
What is the main difference between git clone and git remote?
The main difference between git clone and git remote is that git clone is used to create a new local repository
whereas git remote is used in an existing repository.
git remote adds a new reference to existing remote repository for tracking further changes.
git clone creates a new local repository by copying another repository from a URL.
GIT version control helps us in managing the changes to source code over time by a software team. It keeps track
of all the changes in a special kind of database. If we make a mistake, we can go back in time and see previous
changes to fix the mistake.
GIT version control helps the team in collaborating on developing a software and work efficiently. Every one can
merge the changes with confidence that everything is tracked and remains intact in GIT version control. Any bug
introduced by a change can be discovered and reverted back by going back to a working version.
There are many GUI for GIT that we can use. Some of these are:
GitHub Desktop
GITX-dev
Gitbox
Git-cola
SourceTree
Git Extensions
SmartGit
GitUp
In GIT, git diff command is used to display the differences between 2 versions, or between working directory and
an index, or between index and most recent commit.
It can also display changes between two blob objects, or between two files on disk in GIT.
It helps in finding the changes that can be used for code review for a feature or bug fix.
By using rerere, GIT remembers how we’ve resolved a hunk conflict. The next time GIT sees the same conflict,
it can automatically resolve it for us.
What are the three most popular version of git diff command?
git diff: It displays the differences between working directory and the index.
git diff –cached: It displays the differences between the index and the most recent commit.
git diff HEAD: It displays the differences between working directory and the most recent commit
In GIT, git status command mainly shows the status of working tree.
The paths that have differences between the index file and the current HEAD commit.
The paths that have differences between the working tree and the index file
The paths in the working tree that are not tracked by GIT.
Among the above three items, first item is the one that we commit by using git commit command. Item two and
three can be committed only after running git add command.
What is the main difference between git diff and git status?
In GIT, git diff shows the differences between different commits or between the working directory and index.
Whereas, git status command just shows the current status of working tree.
In GIT, git rm command is used for removing a file from the working tree and the index.
Sometimes we want to save our unfinished work. For this purpose we use git stash command. Once we want to
come back and continue working from the last place where we left, we use git stash apply command to bring back
the unfinished work.
Or we can use
git stash apply <stashname>
We can search git history by author, date or content. It can even list the commits that were done x days before or
after a specific date.
GIT gives us a very good feature of staging our changes before commit. To stage the changes we use git add
command. This adds our changes from working directory to the index.
When we are working on multiple tasks and we want to just commit the finished tasks, we first add finished
changes to staging area and then commit it. At this time git add command is very helpful.
We use git reset command to reset current HEAD to a specific state. By default it reverses the action of git add
command.
So we use git reset command to undo the changes of git add command.
Whenever we do a commit in GIT by using git commit command, GIT creates a new commit object. This commit
objects is saved to GIT repository.
HASH: The SHA1 hash of the Git tree that refers to the state of index at commit time.
Commit Author: The name of person/process doing the commit and date/time.
Comment: Some text messages that contains the reason for the commit .
This option converts the output format from default to other formats. There are pre-built formats available for our
use.
What are the programming languages in which git hooks can be written?
Git hooks are generally written in shell and PERL scripts. But these can be written in any other language as long
as it has an executable.
A commit message is a comment that we add to a commit. We can provide meaningful information about the
reason for commit by using a commit message.
In most of the organizations, it is mandatory to put a commit message along with each commit.
Often, commit messages contain JIRA ticket, bug id, defect id etc. for a project.
GIT is made very secure since it contains the source code of an organization. All the objects in a GIT repository
are encrypted with a hashing algorithm called SHA1.
This algorithm is quite strong and fast. It protects source code and other contents of repository against the possible
malicious attacks.
This algorithm also maintains the integrity of GIT repository by protecting the change history against accidental
changes.
GIT is very flexible version control system. It supports non-linear development workflows. It supports flows that
are compatible with external protocols and existing systems.
GIT also supports both branching and tagging that promotes multiple kinds of workflows in version control.
If a commit has not been pushed to GitHub, we can use git commit -ammend command to change the commit
message.
A repository created with git init –bare command is a bare repository in GIT.
The bare repository does not contain any working or checked out copy of source files. A bare repository stores
git revision history in the root folder of repository instead of in a .git subfolder.
We can create a bare repository in which all developers can push their code.
There is no working tree in bare repository, since no one directly edits files in a bare repository.
To put a local repository on GitHub, we first add all the files of working directory into local repository and commit
the changes. After that we call git remote add <Remote Repo URL> command to add the local repository on
GitHub server.
Once it is added, we use git push command to push the contents of local repository to remote GitHub server.
In case a local branch is not fully merged, but we want to delete it by force, then we use git branch –D
<branchname> command.
We can use git hooks for this kind of purpose. We can write the code sanity checks in script. This script can be
called by pre-commit hook of the repository.
How can we revert a commit that was pushed earlier and is public now?
Internally, git revert command creates a new commit with patches that reverse the changes done in previous
commits.
The other option is to checkout a previous commit version and then commit it as a new commit.
In GIT, how will you compress last n commits into a single commit?
Tom compress last n commits a single commit, we use git rebase command. This command compresses multiple
commits and creates a new commit. It overwrites the history of commits.
How will you switch from one branch to a new branch in GIT?
In GIT, we can use git checkout <new branchname> command to switch to a new branch.
GIT provides git clean command to recursively clean the working tree. It removes the files that are not under
version control in GIT.
If we use git clean –x, then ignored files are also removed.
Tag objects created with options –a, -s, -u are also known as annotated tags.
A git cherry-pick is a very useful feature in GIT. By using this command we can selectively apply the changes
done by existing commits.
In case we want to selectively release a feature, we can remove the unwanted files and apply only selected
commits.
How can you find the names of files that were changed in a specific commit?
Every commit in GIT has a hash code. This hash code uniquely represents the GIT commit object.
We can use git diff-tree command to list the name of files that were changed in a commit.
How can we attach an automated script to run on the event of a new commit by push command?
In GIT we can use a hook to run an automated script on a specific event. We can choose between pre-receive,
update or post-receive hook and attach our script on any of these hooks.
GIT will automatically run the script on the event of any of these hooks.
What is the difference between pre-receive, update and post-receive hooks in GIT?
Pre-receive hook is invoked when a commit is pushed to a destination repository. Any script attached to this hook
is executed before updating any reference. This is mainly used to enforce development best practices and policies.
Update hook is similar to pre-receive hook. It is triggered just before any updates are done. This hook is invoked
once for every commit that is pushed to a destination repository.
Post-receive hook is invoked after the updates have been done and accepted by a destination repository. This is
mainly used to configure deployment scripts. It can also invoke Continuous Integration (CI) systems and send
notification emails to relevant parties of a repository.
A Hook is local to a GIT repository. But the script attached to a hook can be created either inside the hooks
directory or it can be stored in a separate repository. But we have to link the script to a hook in our local repository.
In this way we can maintain versions of a script in a separate repository, but use them in our repository where
hooks are stored.
Also when we store scripts in a separate common repository, we can reuse same scripts for different purposes in
multiple repositories.
In GIT we can use git bisect command to find the commit that has introduced a bug in the system.
GIT bisect command internally uses binary search algorithm to find the commit that introduced a bug.
We first tell a bad commit that contains the bug and a good commit that was present before the bug was introduced.
Then git bisect picks a commit between those two endpoints and asks us whether the selected commit is good or
bad.
It continues to narrow down the range until it discovers the exact commit responsible for introducing the bug.
We can use git diff command to see the differences between two commits. The syntax for a simple git diff
command to compare two commits is:
Each commit object in GIT has a unique hash. This hash is a 40 characters checksum hash. It is based on SHA1
hashing algorithm.
We can use a hash to uniquely identify a GIT commit.
Git also provides support for creating an alias for a commit. This alias is known as refs. Every tag in GIT is a ref.
These refs can also be used to identify a commit. Some of the special tags in GIT are
HEAD, FETCH_HEAD and MERGE_HEAD.
When we run git branch <branchname>, how does GIT know the SHA-1 of the last commit?
GIT uses the reference named HEAD for this purpose. The HEAD file in GIT is a symbolic reference to the
current branch we are working on.
A symbolic reference is not a normal reference that contains a SHA1 value. A symbolic reference contains a
pointer to another reference.
If we run git checkout branchA, Git updates the file to look like this:
$ cat .git/HEAD
ref: refs/heads/branchA
What are the different types of Tags you can create in GIT?
Lightweight Tag: A lightweight tag is a reference that never moves. We can make a lightweight tag by running a
command similar to following:
Annotated Tag: An annotated tag is more complex object in GIT. When we create an annotated tag, GIT creates
a tag object and writes a reference to point to it rather than directly to the commit.
We can create an annotated tag as follows:
We can use command git remote rename for changing the name of a remote repository. This changes the short
name associated with a remote repository in your local. Command would look as follows:
Some people use git checkout and some use git co for checkout. How is that possible?
We can create aliases in GIT for commands by modifying the git configuration.
In case of calling git co instead of git checkout we can run following command:
So the people using git co have made the alias for git checkout in their own environment.
How can we see the last commit on each of our branch in GIT?
When we run git branch command, it lists all the branches in our local repository. To see the latest commit
associated with each branch, we use option –v.
git branch –v
Branch origin is similar to branch master. It does not have any special meaning in GIT.
Master is the default name for a starting branch when we run git init command.
Origin is the default name for a remote when we run git clone command. If we run git clone -o myOrigin instead,
then we will have myOrigin/master as our default remote branch.
How can we configure GIT to not ask for password every time?
When we use HTTPS URL to push, the GIT server asks for username and password for authentication. It prompts
us on the terminal for this information.
If we don’t want to type username/password with every single time push, we can set up a “credential cache”.
What are the four major protocols used by GIT for data transfer?
Local
HTTP
Secure Shell (SSH)
Git
Git protocol is a mechanism for transferring data in GIT. It is a special daemon. It comes pre-packaged with GIT.
It listens on a dedicated port 9418. It provides services similar to SSH protocol.
But Git protocol does not support any authentication.
So on plus side, this is a very fast network transfer protocol. But it lacks authentication.
In case of projects where we do not have push access, we can just fork the repository. By running git fork
command, GIT will create a personal copy of the repository in our namespace. Once our work is done, we can
create a pull request to merge our changes on the real project.
GIT is shipped along with a grep command that allows us to search for a string or regular expression in any
committed tree or the working directory.
We can use git rebase command to reorder commits in GIT. It can work interactively and you can also select the
ordering of commits.
To split a commit, we have to use git rebase command in interactive mode. Once we reach the commit that needs
to be split, we reset that commit and take the changes that have been reset. Now we can create multiple commits
out of that.
In GIT, filter-branch is another option to rewrite history. It can scrub the entire history. When we have large
number of commits, we can use this tool.
It gives many options like removing the commit related changes to a specific file from history.
You can even set you name and email in the commit history by using filter-branch.
In GIT, we get two simple options for resolving merge conflicts: ours and theirs
These options tell the GIT which side to favor in merge conflicts.
As the name suggests, in ours, the changes in our branch are favored over the other branch during a merge conflict.
GIT provides an option ignore-space-change in git merge command to ignore the conflicts related to whitespaces.
In GIT, git blame is a very good option to find the person who changed a specific line. When we call git blame
on a file, it displays the commit and name of a person responsible for making change in that line.
Following is a sample:
In GIT, we can create sub modules inside a repository by using git submodule command.
By using submodule command, we can keep a Git repository as a subdirectory of another Git repository.
It allows us to keep our commits to submodule separate from the commits to main Git repository.
AWS
419.What do you know about AWS Region?
An AWS Region is a completely independent entity in a geographical area. There are two more Availability
Zones in an AWS Region.
Since each AWS Region is isolated from another Region, it provides very high fault tolerance and stability.
For launching an EC2 instance, we have to select an AMI within the same region.
What are the important components of IAM?
The important components of IAM are as follows:
IAM User: An IAM User is a person or service that will interact with AWS. User can sign into AWS Management
Console for performing tasks in AWS.
IAM Group: An IAM Group is a collection of IAM users. We can specify permission to an IAM Group. This
helps in managing large number of IAM users. We can simply add or remove an IAM User to an IAM Group to
manage the permissions.
IAM Role: An IAM Role is an identity to which we give permissions. A Role does not have any credentials
(password or access keys). We can temporarily give an IAM Role to an IAM User to perform certain tasks in
AWS.
IAM Permission: In IAM we can create two types of Permissions. Identity based and Resource based. We can
create a Permission to access or perform an action on an AWS Resource and assign it to a User, Role or Group.
We can also create Permissions on resources like S3 bucket, Glacier vault etc and specify who has access to the
resource.
IAM Policy: An IAM Policy is a document in which we list permissions to specify Actions, Resources and
Effects. This document is in JSON format. We can attach a Policy to an IAM User or Group.
What are the important points about AWS IAM?
Some of the important points about AWS IAM are as follows:
A new User in IAM does not have any permission.
AWS IAM assigns an Access Key and a Secret Access Key to a new User.
An Access Key cannot be used to login to AWS Console.
We use Access Key to access AWS via an APIs or Command Line interface.
IAM is a universal application. It is common across all the regions in
AWS.
When we first setup our AWS account, we get a root account that has complete Admin access.
Amazon S3 supports durability at the scale of 99.999999999% of time. This is 9 nines after decimal.
Amazon S3 supports Read after Write consistency when we create a new object by PUT. It means as soon as we
Write a new object, we can access it.
Amazon S3 supports Eventual Consistency when we overwrite an existing object by PUT. Eventual Consistency
means that the effect of overwrite will not be immediate but will happen after some time.
For deletion of an object, Amazon S3 supports Eventual Consistency after DELETE.
S3 Standard -Infrequent Access (IA): In this tier, S3 provides durable storage that is immediately available.
But in this tier files are infrequently accessed.
S3 Reduced Redundancy Storage (RRS): In this tier, S3 provides the option to customers to store data at lower
levels of redundancy. In this case data is copied to multiple locations but not on as many locations as standard
S3.
How will you upload a file greater than 100 megabytes in Amazon S3?
Amazon S3 supports storing objects or files up to 5 terabytes. To upload a file greater than 100 megabytes, we
have to use Multipart upload utility from AWS. By using Multipart upload we can upload a large file in multiple
parts.
Each part will be independently uploaded. It doesn’t matter in what order each part is uploaded. It even supports
uploading these parts in parallel to decrease overall time. Once all the parts are uploaded, this utility makes these
as one single object or file from which the parts were created.
Amazon Glacier is an extremely low cost cloud based storage service provided by Amazon.
We mainly use Amazon Glacier for long-term backup purpose.
Amazon Glacier can be used for storing data archives for months, years or even decades.
It can also be used for long term immutable storage based on regulatory and archiving requirements. It provides
Vault Lock support for this purpose. In this option, we write once but can read many times same data.
One use case is for storing certificates that can be issued only once and only the original person keeps the main
copy.
No, we cannot disable versioning on a version-enabled bucket in Amazon S3. We can just suspend the versioning
on a bucket in S3.
Once we suspend versioning, Amazon S3 will stop creating new versions of the object. It just stores the object
with null version ID.
On overwriting an existing object, it just replaces the object with null version ID. So any existing versions of the
object still remain in the bucket. But there will be no more new versions of the same object except for the null
version ID object.
What are the use cases of Cross Region Replication Amazon S3?
We can use Cross Region Replication Amazon S3 to make copies of an object across buckets in different AWS
Regions. This copying takes place automatically and in an asynchronous mode.
We have to add replication configuration on our source bucket in S3 to make use of Cross Region Replication. It
will create exact replicas of the objects from source bucket to destination buckets in different regions.
Some of the main use cases of Cross Region Replication are as follows:
Compliance: Some times there are laws/regulatory requirements that ask for storing data at farther geographic
locations. This kind of compliance can be achieved by using AWS Regions that are spread across the world.
Failover: At times, we want to minimize the probability of system failure due to complete blackout in a region.
We can use CrossRegion Replication in such a scenario.
Latency: In case we are serving multiple geographies, it makes sense to replicate objects in the geographical
Regions that are closer to end customer. This helps in reducing the latency.
What are the different types of actions in Object Lifecycle Management in Amazon S3?
There are mainly two types of Object Lifecycle Management actions in Amazon S3.
Transition Actions: These actions define the state when an Object transitions from one storage class to another
storage class. E.g. a new object may transition to STANDARD_IA (infrequent access) class after 60 days of
creation. And it can transition to GLACIER after 180 days of creation.
Expiration Actions: These actions specify what happens when an Object expires. We can ask S3 to delete an
object completely on expiration.
If our application is content rich and used across multiple locations, we can use Amazon CloudFront to increase
its performance. Some of the techniques used by Amazon CloudFront are as follows:
Caching: Amazon CloudFront caches the copies of our application’s content at locations closer to our viewers.
By this caching our users get our content very fast. Also due to caching the load on our main server decreases.
Edge / Regional Locations: CloudFront uses a global network of Edge and Regional edge locations to cache our
content. These locations cater to almost all of the geographical areas across the world.
Persistent Connections: In certain cases, CloudFront keeps persistent connections with the main server to fetch
the content quickly.
Other Optimization: Amazon CloudFront also uses other optimization techniques like TCP initial congestion
window etc to deliver high performance experience.
Cost: With streaming there is no need to download all the content to a user’s device. A user can start viewing
content as soon as some part is available for viewing. This saves costs since we do not have to download a large
media file before starting each viewing session.
In Amazon CloudFront we can detect the country from where end users are requesting our content. This
information can be passed to our Origin server by Amazon CloudFront. It is sent in a new HTTP header.
Based on different countries we can generate different content for different versions of the same content. These
versions can be cached at different Edge Locations that are closer to the end users of that country.
In this way we are able to target our end users based on their geographic locations.
Amazon S3 is a very secure storage service. Some of the main security mechanisms available in Amazon S3 are
as follows:
Access: When we create a bucket or an object, only the owner get the access to the bucket and objects.
Authentication: Amazon S3 also support user authentication to control who has access to a specific object or
bucket.
Access Control List: We can create Access Control Lists (ACL) to provide selective permissions to users and
groups.
HTTPS: Amazon S3 also supports HTTPS protocol to securely upload and download data from cloud.
Encryption: We can also use Server Side Encryption (SSE) in Amazon S3 to encrypt data.
Cloud Computing
Flexibility: The businesses that have fluctuating bandwidth demands need the flexibility of Cloud Computing. If
you need high bandwidth, you can scale up your cloud capacity. When you do not need high bandwidth, you can
just scale down. There is no need to be tied into an inflexible fixed capacity infrastructure.
Disaster Recovery: Cloud Computing provides robust backup and recovery solutions that are hosted in cloud.
Due to this there is no need to spend extra resources on homegrown disaster recovery. It also saves time in setting
up disaster recovery.
Automatic Software Updates: Most of the Cloud providers give automatic software updates. This reduces the
extra task of installing new software version and always catching up with the latest software installs.
Low Capital Expenditure: In Cloud computing the model is Pay as you Go. This means there is very less upfront
capital expenditure. There is a variable payment that is based on the usage.
Collaboration: In a cloud environment, applications can be shared between teams. This increases collaboration
and communication among team members.
Remote Work: Cloud solutions provide flexibility of working remotely. There is no on site work. One can just
connect from anywhere and start working.
Security: Cloud computing solutions are more secure than regular onsite work.
Data stored in local servers and computers is prone to security attacks. In Cloud Computing, there are very few
loose ends. Cloud providers give a secure working environment to its users.
Document Control: Once the documents are stored in a common repository, it increases the visibility and
transparency among companies and their clients. Since there is one shared copy, there are fewer chances of
discrepancies.
Competitive Pricing: In Cloud computing there are multiple players, so they keep competing among themselves
and provide very good pricing. This comes out much cheaper compared to other options.
Environment Friendly: Cloud computing saves precious environmental resources also. By not blocking the
resources and bandwidth.
On-demand Computing is the latest model in enterprise systems. It is related to Cloud computing. It means IT
resources can be provided on demand by a Cloud provider.
In an enterprise system demand for computing resources varies from time to time. In such a scenario, On-demand
computing makes sure that servers and IT resources are provisioned to handle the increase/decrease in demand.
A cloud provider maintains a poll of resources. The pool of resources contains networks, servers, storage,
applications and services. This pool can serve the varying demand of resources and computing by various
enterprise clients.
There are many concepts like- grid computing, utility computing, autonomic computing etc. that are similar to
on-demand computing.
Infrastructure as a Service (IAAS): IAAS providers give low-level abstractions of physical devices. Amazon Web
Services (AWS) is an example of IAAS. AWS provides EC2 for computing, S3 buckets for storage etc. Mainly
the resources in this layer are hardware like memory, processor speed, network bandwidth etc.
Platform as a Service (PAAS): PAAS providers offer managed services like Rails, Django etc. One good example
of PAAS is Google App Engineer. These are the environments in which developers can develop sophisticated
software with ease.
Developers just focus on developing software, whereas scaling and performance is handled by PAAS provider.
Software as a Service (SAAS): SAAS provider offer an actual working software application to clients. Salesforce
and Github are two good examples of SAAS. They hide the underlying details of the software and just provide
an interface to work on the system. Behind the scenes the version of Software can be easily changed.
An IAAS provider can give physical, virtual or both kinds of resources. These resources are used to build cloud.
IAAS provider handles the complexity of maintaining and deploying these services.
IAAS provider also handles security and backup recovery for these services. The main resources in IAAS are
servers, storage, routers, switches and other related hardware etc.
Platform as a service (PaaS) is a kind of cloud computing service. A PaaS provider offers a platform on which
clients can develop, run and manage applications without the need of building the infrastructure.
In PAAS clients save time by not creating and managing infrastructure environment associated with the app that
they want to develop.
It allows development work on higher level programming with very less complexity.
Teams can focus on just the development of the application that makes the application very effective.
Maintenance and enhancement of the application is much easier.
It is suitable for situations in which multiple developers work on a single project but are not co-located.
Some PaaS providers lock in the clients in their platform. This also decreases the flexibility of clients using PaaS.
Private Cloud: Some companies build their private cloud. A private cloud is a fully functional platform that is
owned, operated and used by only one organization.
Primary reason for private cloud is security. Many companies feel secure in private cloud. The other reasons for
building private cloud are strategic decisions or control of operations.
There is also a concept of Virtual Private Cloud (VPC). In VPC, private cloud is built and operated by a hosting
company. But it is exclusively used by one organization.
Public Cloud: There are cloud platforms by some companies that are open for general public as well as big
companies for use and deployment. E.g. Google Apps, Amazon Web Services etc.
The public cloud providers focus on layers and application like- cloud application, infrastructure management
etc. In this model resources are shared among different organizations.
Hybrid Cloud: The combination of public and private cloud is known as Hybrid cloud. This approach provides
benefits of both the approaches- private and public cloud. So it is very robust platform.
A client gets functionalities and features of both the cloud platforms. By using Hybrid cloud an organization can
create its own cloud as well as they can pass the control of their cloud to another third party.
Scalability is the ability of a system to handle the increased load on its current hardware and software resources.
In a highly scalable system it is possible to increase the workload without increasing the resource capacity.
Scalability supports any sudden surge in the demand/traffic with current set of resources.
Elasticity is the ability of a system to increase the workload by increasing the hardware/software resources
dynamically. Highly elastic systems can handle the increased demand and traffic by dynamically commission and
decommission resources. Elasticity is an important characteristic of Cloud Computing applications. Elasticity
means how well your architecture is adaptable to workload in real time.
E.g. If in a system, one server can handle 100 users, 2 servers can handle 200 users and 10 servers can handle
1000 users. But in case for adding every X users, if you need 2X the amount of servers, then it is not a scalable
design.
Let say, you have just one user login every hour on your site. Your one server can handle this load. But, if
suddenly, 1000 users login at once, can your system quickly start new web servers on the fly to handle this load?
Your design is elastic if it can handle such sudden increase in traffic so quickly.
Many applications like Google docs, Microsoft office etc. provide SaaS model for their software.
The benefit of SaaS is that a client can add more users on the fly based on its current needs. And client does not
need to install or maintain any software on its premises to use this software.
Cloud computing consists of different types of Datacenters linked in a grid structure. The main types of
Datacenters in Cloud computing are:
Containerized Datacenter
As the name suggests, containerized datacenter provides high level of customization for an organization. These
are traditional kind of datacenters. We can choose the different types of servers, memory, network and other
infrastructure resources in this datacenter. Also we have to plan temperature control, network management and
power management in this kind of datacenter.
Low-Density Datacenters
In a Low-density datacenter, we get high level of performance. In such a datacenter if we increase the density of
servers, the issue with power comes. With high density of servers, the area gets heated. In such a scenario,
effective heat and power management is done. To reach high level of performance, we have to optimize the
number of servers’ in the datacenter.
Software as a Service (SaaS) is used to offer different kinds of software applications in a Cloud environment.
Generally these are offered on subscription basis. Different modes of SaaS are:
Simple multi-tenancy: In this setup, each client gets its own resources. These resources are not shared with other
clients. It is more secure option, since there is no sharing of resources. But it an inefficient option, since for each
client more money is needed to scale it with the rising demands. Also it takes time to scale up the application in
this mode.
Fine grain multi-tenancy: In this mode, the feature provided to each client is same. The resources are shared
among multiple clients. It is an efficient mode of cloud service, in which data is kept private among different
clients but computing resources are shared. Also it is easier and quicker to scale up the SaaS implementation for
different clients.
What are the important things to care about in Security in a cloud environment?
Organizations have to keep their Data most secure during the transfer between two locations. Also they have to
keep data secure when it is stored at a location. Hackers can hack into application or they can get an unauthorized
copy of the data. So it becomes important to encrypt the data during transit as well as during rest to protect it
from unwanted hackers.
Application Programming Interfaces (API) is used in cloud computing environment for accessing many services.
APIs are very easy to use. They provide a quick option to create different set of applications in cloud environment.
An API provides a simple interface that can be used in multiple scenarios.
There are different types of clients for cloud computing APIs. It is easier to serve different needs of multiple
clients with APIs in cloud computing environment.
Identity Management: This aspect creates different level of users, roles and their credentials to access the services
in cloud.
Access Control: In this area, we create multiple levels of permissions and access areas that can be given to a user
or role for accessing a service in cloud environment.
Authentication: In this area, we check the credentials of a user and confirm that it is the correct user. Generally
this is done by user password and multi-factor authentication like-verification by a one-time use code on cell
phone.
Authorization: In this aspect, we check for the permissions that are given to a user or role. If a user is authorized
to access a service, they are allowed to use it in the cloud environment.
What are the main cost factors of cloud based data center?
Costs in a Cloud based data center are different from a traditional data center. Main cost factors of cloud based
data center are as follows:
Labor cost: We need skilled staff that can work with the cloud-based datacenter that we have selected for our
operation. Since cloud is not a very old technology, it may get difficult to get the right skill people for handling
cloud based datacenter.
Power cost: In some cloud operations, power costs are borne by the client.
Since it is a variable cost, it can increase with the increase in scale and usage.
Computing cost: The biggest cost in Cloud environment is the cost that we pay to Cloud provider for giving us
computing resources. This cost is much higher compared to the labor or power costs.
How can we measure the cloud-based services?
In a cloud-computing environment we pay for the services that we use. So main criteria to measure a cloud based
service its usage.
For computing resource we measure by usage in terms of time and the power of computing resource.
For a storage resource we measure by usage in terms of bytes (giga bytes) and bandwidth used in data transfer.
Another important aspect of measuring a cloud service is its availability. A cloud provider has to specify the
service level agreement (SLA) for the time for which service will be available in cloud.
In a traditional datacenter the cost of increasing the scale of computing environment is much higher than a Cloud
computing environment. Also in a traditional data center, there are not much benefits of scaling down the
operation when demand decreases. Since most of the expenditure is in capital spent of buying servers etc., scaling
down just saves power cost, which is very less compared to other fixed costs.
Also in a Cloud environment there is no need to higher a large number of operations staff to maintain the
datacenter. Cloud provider takes care of maintaining and upgrading the resources in Cloud environment.
With a traditional datacenter, people cost is very high since we have to hire a large number of technical operation
people for in-house datacenter.
Another aspect of cloud environment is that servers often fail or go down. In such a scenario it is important to
implement the application in such a way that we just kill the slow server and restart another server to handle the
traffic seamlessly.
Operating System (OS): We need an OS to support hypervisor in IaaS. We can use open source OS like Linux
for this purpose.
Networking: We have to define and implement networking topology for IaaS implementation. We can use public
or private network for this.
Cloud Model: We have to select the right cloud model for implementing IaaS strategy. It can be SaaS, PaaS or
CaaS.
DOCKER
What is Docker?
Docker is Open Source software. It provides the automation of Linux application deployment in a software
container.
Docker can package software in a complete file system that contains software code, runtime environment, system
tools, & libraries that are required to install and run the software on a server.
A Docker image is an immutable file, which is a snapshot of container. We create an image with build command.
We can use docker rmi command to delete an image from our local system.
If we want to find IDs of all the Docker images in our local system, we can user docker images command.
% docker images
In a Hypervisor environment we first create a Virtual Machine and then install an Operating System on it. After
that we deploy the application. The virtual machine may also be installed on different hardware configurations.
In a Docker environment, we just deploy the application in Docker. There is no OS layer in this environment. We
specify libraries, and rest of the kernel is provided by Docker engine.
If we use a json file then we have to specify in docker command that we are using a json file as follows:
% docker-compose -f docker-compose.json u
Yes, theoretically we can run multiples apps on one Docker server. But in practice, it is better to run different
components on separate containers.
With this we get cleaner environment and it can be used for multiple uses.
Setting up Development Environment: We can use Docker to set the development environment with the
applications on which our code is dependent.
Testing Automation Setup: Docker can also help in creating the Testing Automation setup. We can setup
different services and apps with Docker to create the automation testing environment.
Production Deployment: Docker also helps in implementing the Production deployment for an application. We
can use it to create the exact environment and process that will be used for doing the production deployment.
Multiple environments on same Host: We can use it to create multiple environments on the same host server.
Preserve Volume Data on Container Creation: Docker compose also preserves the volume data when we create
a container.
Recreate the changed Containers: We can also use compose to recreate the changed containers.
Variables in Compose file: Docker compose also supports variables in compose file. In this way we can create
variations of our containers.
The most popular use of Docker is in build pipeline. With the use of Docker it is much easier to automate the
development to deployment process in build pipeline.
We use Docker for the complete build flow from development work, test run and deployment to production
environment.
Since Linux was an open source operating system, it opened new opportunities for developers who want to
contribute to open source systems.
One of the very good outcomes of open source software is Docker. It has very powerful features.
Docker has wide acceptance due to its usability as well as its open source approach of integrating with different
systems.
UNIX Shell
How will you remove all files in current directory? Including the files that are two levels down in a
subdirectory.
In Unix we have rm command to remove files and sub-directories. With rm command we have –r option that
stands for recursive. The –r option can delete all files in a directory recursively.
My_dir
->Level_1_dir
-> Level_1_dir ->Level_2_dir
-> Level_1_dir ->Level_2_dir->a.txt
With rm –r * command we can delete the file a.txt as well as subdirectories Level_1_dir and Level_2_dir.
Command:
rm – r *
The asterisk (*) is a wild card character that stands for all the files with any name.
What is the difference between the –v and –x options in Bash shell scripts?
In a BASH Unix shell we can specify the options –v and –x on top of a script as follows:
#!/bin/bash -x –v
With –x option BASH shell will echo the commands like for, select, case etc. after substituting the arguments and
variables. So it will be an expanded form of the command that shows all the actions of the script. It is very useful
for debugging a shell script.
With –v option BASH shell will echo every command before substituting the values of arguments and variables.
In –v option Unix will print each line as it reads.
In –v option, If we run the script, the shell prints the entire file and then executes. If we run the script interactively,
it shows each command after pressing enter.
In Unix there are many Filter commands like- cat, awk, grep, head, tail cut etc.
A Filter is a software program that takes an input and produces an output, and it can be used in a stream operation.
We can mix and match multiple filters to create a complex command that can solve a problem.
Awk and Sed are complex filters that provide fully programmable features.
Even Data scientists use Unix filters to get the overview of data stored in the files.
A Kernel is the main component that can control everything within Unix OS.
It is the first program that is loaded on startup of Unix OS. Once it is loaded it will manage the rest of the startup
process.
Kernel manages memory, scheduling as well as communication with peripherals like printers, keyboards etc.
But Kernel does not directly interact with a user. For a new task, Kernel will spawn a shell and user will work in
a shell.
Kernel provides many system calls. A software program interacts with Kernel by using system calls.
Kernel has a protected memory area that cannot be overwritten accidentally by any process.
Shell in Unix is a user interface that is used by a user to access Unix services.
Generally a Unix Shell is a command line interface (CLI) in which users enter commands by typing or uploading
a file.
We use a Shell to run different commands and programs on Unix operating system.
A Shell also has a command interpreter that can take our commands and send these to be executed by Unix
operating system.
Some of the popular Shells on Unix are: Korn shell, BASH, C shell etc.
What are the different shells in Unix that you know about?
We use ls -l command to list the files and directories in a directory. With -l option we get long listing format.
In this format the first character identifies the entry type. The entry type can be one of the following:
bBlock special file cCharacter special file dDirectory lSymbolic link sSocket link pFIFO
-Regular file
In a Multi-tasking environment, same user can submit more than one tasks and operating system will execute
them at the same time.
In a Multi-user environment, more than one user can interact with the operating system at the same time.
Each Inode has a number that is used in the index table. Unix kernel uses Inode number to access the contents of
an Inode.
What is the difference between absolute path and relative path in Unix file system?
Absolute path is the complete path of a file or directory from the root directory. In general root directory is
represented by / symbol. If we are in a directory and want to know the absolute path, we can use pwd command.
E.g. In a directory structure /var/user/kevin/mail if we are in kevin directory then pwd command will give absolute
path as
/var/user/kevin.
Absolute path of mail folder is /var/user/kevin/mail. For mail folder ./mail is the relative path of mail directory
from kevin folder.
Program Execution: A shell is responsible for executing the commands and script files in Unix. User can either
interactively enter the commands in Command Line Interface called terminal or they can run a script file
containing a program.
Environment Setup: A shell can define the environment for a user.We can set many environment variables in a
shell and use the value of these variables in our program.
Interpreter: A shell acts as an interpreter for our scripts. It has abuilt in programming language that can be used
to implement the logic.
Pipeline: A shell also can hookup a pipeline of commands. Whenwe run multiple commands separated by | pipe
character, the shell takes the output of a command and passes it to next one in the pipeline.
I/O Redirection: Shell is also responsible for taking input fromcommand line interface (CLI) and sending the
output back to CLI. We use >, <, >> characters for this purpose.
To use a Shell variable in a script we use $ sign in front of the variable name.
Microservices
484.What is a Microservice?
A Microservice is a small and autonomous piece of code that does one thing very well. It is focused on doing
well one specific task in a big system.
It is also an autonomous entity that can be designed, developed and deployed independently.
Architects, in Microservices architecture, play the role of Town planners. They decide in broad strokes about the
layout of the overall software system.
They help in deciding the zoning of the components. They make sure components are mutually cohesive but not
tightly coupled. They need not worry about what is inside each zone.
Since they have to remain up to date with the new developments and problems, they have to code with developers
to learn the challenges faced in day-to-day life.
They can make recommendations for certain tools and technologies, but the team developing a micro service is
ultimately empowered to create and design the service. Remember, a micro service implementation can change
with time.
They have to provide technical governance so that the teams in their technical development follow principles of
Microservice.
At times they work as custodians of overall Microservices architecture.
What is the advantage of Microservices architecture over Service Oriented Architecture (SOA)?
Service Oriented Architecture (SOA) is an approach to develop software by creating multiple services. It creates
small parts of services and promotes reusability of software. But SOA development can be slow due to use of
things like communication protocols SOAP, middleware and lack of principles.
On the other hand, Microservices are agnostic to most of these things. You can use any technology stack, any
hardware/middleware, any protocol etc. as long as you follow the principles of Microservices.
Microservices architecture also provides more flexibility, stability and speed of development over SOA
architecture.
Is it a good idea to provide a
Tailored Service Template for Microservices development in an organization?
If your organization is using similar set of technologies, then it is a good idea to provide a Service Template that
can be tailored by development teams. It can make development faster. Also it can help in promoting adoption of
various good practices that are already built into template.
But if your organization uses wide variety of technologies, then it may not be wise to produce and maintain a
template for each service. Instead of that, it is better to introduce tools that help in maintaining same set of
practices related to Microservices among all such technologies.
There are many organizations that provide tailored templates for Microservices. Eg. Dropwizard, Karyon etc.
You can use these templates to make faster development of services in your organization.
Also remember that template code should not promote shared code.
This can lead to tight coupling between Microservices.
What are the disadvantages of using Shared libraries approach to decompose a monolith application?
You can create shared libraries to increase reuse and sharing of features among teams. But there are some
downsides to it. Since shared libraries are implemented in same language, it constrains you from using multiple
types of technologies.
It does not help you with scaling the parts of system that need better performance.
Deployment of shared libraries is same as deployment of Monolith application, so it comes with same deployment
issues.
Shared libraries introduce shared code that can increase coupling in software.
What are the characteristics of a Good Microservice?
A bounded context is like a specific responsibility that is developed within a boundary. In a domain there can be
multiple bounded contexts that are internally implemented. Eg. A hospital system can have bounded contexts
like- Emergency Ward handling, Regular vaccination, Out patient treatment etc. Within each bounded context,
each sub-system can be independently designed and implemented.
Breaking Changes: Every change in Microservice should not become a breaking change for client. It is better to
minimize the impact of a change on an existing client. So that existing clients’ do not have to keep changing their
code to adapt to changes in a Microservice.
Implementation Hiding: Each Microservice should hide its internal implementation details from another one. This
helps in minimizing the coupling between Microservices that are integrated for a common solution.
Simple to use: A Microservice should be simple to use for a consumer, so that the integration points are simpler.
It should allow clients to choose their own technology stack.
Is it a good idea for Microservices to share a common database?
Sharing a common database between multiple Microservices increases coupling between them. One service can
start accessing data tables of another service. This can defeat the purpose of bounded context. So it is not a good
idea to share a common database between Microservices.
Synchronous communication is a blocking call in which client blocks itself from doing anything else, till the
response comes back. In Asynchronous communication, client can move ahead with its work after making an
asynchronous call. Therefore client is not blocked.
In synchronous communication, a Microservice can provide instant response about success or failure. In real-time
systems, synchronous service is very useful. In Asynchronous communication, a service has to react based on the
response received in future.
Synchronous systems are also known as request/response based.
Asynchronous systems are event-based.
Synchronous Microservices are not loosely coupled.
Depending on the need and critical nature of business domain, Microservices can choose synchronous or
asynchronous form of communication.
What is the difference between Orchestration and Choreography in Microservices architecture?
In Orchestration, we rely on a central system to control and call various Microservices to complete a task. In
Choreography, each Microservice works like a State Machine and reacts based on the input from other parts.
Orchestration is a tightly coupled approach for integrating
Microservices. But Choreography introduces loose coupling. Also, Choreography based systems are more
flexible and easy to change than Orchestration based systems.
Orchestration is often done by synchronous calls. But choreography is done by asynchronous calls. The
synchronous calls are much simpler compared to asynchronous communication.
What are the issues in using REST over HTTP for Microservices?
In REST over HTTP, it is difficult to generate a client stub. Some Web-Servers also do not support all the HTTP
verbs like GET, PUT, POST, DELETE etc.
Due to JSON or plain text in response, performance of REST over HTTP is better than SOAP. But it is not as
good as plain binary communication.
There is an overhead of HTTP in each request for communication.
HTTP is not well suited for low-latency communications.
There is more work in consumption of payload. There may be overhead of serialization, deserialization in HTTP.
Yes, Microservices are independent entities that serve a specific context. For that context, the Microservice can
work as a State Machine. In a State Machine, there are lifecycle events that cause change in the state of the system.
Eg. In a Library service, there is a book that changes state based on different events like- issue a book, return a
book, lose a book, late return of a book, add a new book to catalog etc. These events and book can form a state
machine for Library Microservice.