Wednesday, 24 October 2018

  • Declarative Transaction Management

    • Declarative transaction management is the most common Spring implementation as it has the least impact on application code.
    • The XML declarative approach configures the transaction attributes in a Spring bean configuration file. Declarative transaction management in Spring has the advantage of being less invasive. 
    •  There is no need for changing application code when using declarative transactions.       All you have to do is to modify the application context.
  • Methods
    •  XML based
    • Annotations based
  • Steps
    • Step 1: Define a transaction manager in spring.xml
      • <bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager" id="txManager"/>
    • Step 2: Turn on support for transaction annotations in spring.xml
      • <tx:annotation-driven transaction-manager="txManager"/>
    •  Step 3: Add the @Transactional annotation to the createEmployee Method      @Transactional
    • public int createEmployee(Employee employee) {
..

  • Annotation attributes
    • Transaction readOnly
      • If you don’t explicitly set readOnly attribute to true, you will have read/write transactions.Its always better to explicitly specify the readOnly attribute, as we have noticed some massive performance improvements with Hibernate because of this.
    • Transaction propagation
      • Transaction propagation is REQUIRED by default, which means that the same transaction will propagate from a transactional caller to transactional callee. It will create a new transaction or reuse the one if available. For example, if a read-only transaction calls a read-write transaction method, the whole transaction will be read-only.
      • Depending on the transaction propagation attribute (like for REQUIRES_NEW), sometimes the existing transaction is suspended/paused at some point, a new one is always started and eventually committed, and after that the first transaction is resumed.
    • Isolation Level
      • Isolation level defines a contract between transactions.
        • Read Uncommitted – Allows dirty reads, when a transaction is not yet committed by a thread and another thread is reading the dirty data.
        • Read Committed – Does not allow dirty reads. Only lets a thread to read values which have already been committed by other running transactions in another threads.
        • Repeatable Read – If the same data is read twice in the same transaction, it will always be the same. This level guarantees that any data once read cannot change.
        • Serializable – Transactions occur with locking at all levels (read, range and write locking), because of which they are executed in a fixed sequence. It doesn’t allow concurrent transactions and leads to a performance hit.

  •  Programmatic Transaction Management
    • Spring provides Support for programmatic transaction management by using TransactionTemplate or PlatformTransactionManager implementation.



  • An object is chunk of memory , and the reference to the object is way to reach up to that object in the memory
  • Object reference variable contains address of the object which is declared in the heap memory
  • Class Box { double height; double width; double depth; } Box b1; //declare reference ..it will be null b1 = new Box(); //Create an instance assign to reference variable b1 Box b2 = b1; //Only creates reference to this object.. will not create object memory..use same object memory..
  • Now I  am going to set some property in b1
  • b1.height = 10; b1.width = 20; b1.depth = 30;
  • Then I printed b2 properties
  • System.out.println(b2.height); System.out.println(b2.width); System.out.println(b2.depth); //output 10 20 30
  • I got same values for b2, because it using same memory but different reference


  • This algorithm uses idea of divide and conquer.
  • Find the element called pivot which divides the array into two halves
    • Left side elements should be smaller than the pivot
    • Right side elements are geater than the pivot
  • Steps
    • Bring the pivot to its appropriate position such that left of the pivot is smaller and right is greater.
    • Quick sort left part
    • Quick sort right part
  • There are many different versions of quickSort that pick pivot in different ways.
    • Always pick first element as pivot.
    • Always pick last element as pivot (implemented below)
    • Pick a random element as pivot.
    • Pick median as pivot

  • Reference:

Monday, 22 October 2018


  • Create shared Semaphore object , lock and unlock in consumer - producer  blocks by limiting thread accessible count to 1
  • Output will be like produce 1 and consume 1 , produce 2 and consume 2 ...
  • Producer.java
    • public class Producer implements Runnable { private static List LIST; private static Semaphore semaphore; public Producer(List LISTv, Semaphore semaphoreV) { LIST = LISTv; semaphore = semaphoreV; } public void run() { produce(); } private static void produce() { try { int i = 1; while (true) { semaphore.acquire(); LIST.add(i); System.out.println(i + " Produced"); i++; semaphore.release(); if (i > 100) { break; } } } catch (Exception e) { e.printStackTrace(); } } }
  • Consumer.java
    • public class Consumer implements Runnable { private static List LIST; private static Semaphore semaphore; public Consumer(List LISTv, Semaphore semaphoreV) { LIST = LISTv; semaphore = semaphoreV; } public void run() { consume(); } private static void consume() { int index = 0; try { while (true) { semaphore.acquire(); index = LIST.size() - 1; System.out.println(LIST.get(index) + " Removed"); LIST.remove(index); semaphore.release(); } } catch (Exception e) { e.printStackTrace(); } } }
  • App.java
    • public class App { private static List LIST = new ArrayList(); private static Semaphore SEMAPHORE = new Semaphore(1, true); public static void main(String[] args) { Thread producer = new Thread(new Producer(LIST, SEMAPHORE)); Thread consumer = new Thread(new Consumer(LIST, SEMAPHORE)); producer.start(); consumer.start(); } }
  • Output
    • 1 Produced 1 Removed 2 Produced 2 Removed 3 Produced 3 Removed 4 Produced 4 Removed 5 Produced 5 Removed 6 Produced 6 Removed 7 Produced 7 Removed 8 Produced 8 Removed 9 Produced 9 Removed 10 Produced 10 Removed


  • BlockingQueue amazingly simplifies implementation of Producer-Consumer design pattern by providing outofbox support of blocking on put() and take().
  • No need of manual empty or full check, Blocking Queue handle it internally.
  • Only put and take operation required
  • Output is like one N produce and then consume like FIFO ordedr
  • Producer.java
    • public class Producer implements Runnable { private static BlockingQueue QUEUE; public Producer(BlockingQueue QUEUE_V) { QUEUE = QUEUE_V; } public void run() { try { int i = 1; while (true) { QUEUE.put(i); System.out.println(i + " Produced"); i++; } } catch (Exception e) { e.printStackTrace(); } } }

  • Consumer.java

    • public class Consumer implements Runnable { private static BlockingQueue QUEUE; public Consumer(BlockingQueue QUEUE_V) { QUEUE = QUEUE_V; } public void run() { consumer(); } private static void consumer() { int item; try { Thread.sleep(1000); while (true) { item = QUEUE.take(); System.out.println(item + " Consumed"); } } catch (Exception e) { e.printStackTrace(); } } }

  • App.java

    • private static BlockingQueue QUEUE = new ArrayBlockingQueue(10); public static void main(String[] args) { Thread producer = new Thread(new Producer(QUEUE)); Thread consumer = new Thread(new Consumer(QUEUE)); producer.start(); consumer.start(); }

  • Output

    • 1 Produced 2 Produced 3 Produced 4 Produced 5 Produced 6 Produced 7 Produced 8 Produced 9 Produced 10 Produced 1 Consumed 11 Produced 2 Consumed 3 Consumed 4 Consumed 5 Consumed 12 Produced 6 Consumed 13 Produced 7 Consumed 14 Produced 8 Consumed 15 Produced 9 Consumed 16 Produced 10 Consumed 17 Produced 11 Consumed 18 Produced


    • If List is full then our PRODUCER thread waits until CONSUMER thread consume one item and make space in your queue and call notify() method to inform PRODUCER thread. Both wait() and notify() method are called on shared object which is List in our case.
    • Need synchronised block
    • Check for List size manually and wait for consumer and producer threads
    • Since it is synchronised,
      • Needs to wait till N production
      • Needs to wait till N Consumption
    • Producer.java
      • public class Producer implements Runnable { private static List LIST; private static int SIZE; public Producer(List LIST_V, int SIZE_V) { LIST = LIST_V; SIZE = SIZE_V; } public void run() { producer(); } private static void producer() { try { int i = 1; while (true) { synchronized (LIST) { if (LIST.size() == SIZE) { System.out.println("Producer Waiting for consumer to consume object"); LIST.wait(); } LIST.add(i); System.out.println(i + " Produced"); LIST.notify(); } i++; if (i > 100) { break; } } } catch (Exception e) { e.printStackTrace(); } } }
    • Consumer.java
      • public class Consumer implements Runnable { private static List LIST; public Consumer(List LIST_V) { LIST = LIST_V; } public void run() { consumer(); } private static void consumer() { int index = 0; try { Thread.sleep(2000); while (true) { synchronized (LIST) { if (LIST.size() == 0) { System.out.println("Consumer is waiting for producer to produce"); LIST.wait(); } System.out.println(LIST.get(index) + " Consumed"); LIST.remove(index); LIST.notify(); } } } catch (Exception e) { e.printStackTrace(); } } }
    • App.java
      • public class App { private static List LIST = new ArrayList(); private static int SIZE = 10; public static void main(String[] args) { Thread producer = new Thread(new Producer(LIST, SIZE)); Thread consumer = new Thread(new Consumer(LIST)); producer.start(); consumer.start(); } }
    • Output
      • 1 Produced 2 Produced 3 Produced 4 Produced 5 Produced 6 Produced 7 Produced 8 Produced 9 Produced 10 Produced Producer Waiting for consumer to consume object 1 Consumed 2 Consumed 3 Consumed 4 Consumed 5 Consumed 6 Consumed 7 Consumed 8 Consumed 9 Consumed 10 Consumed Consumer is waiting for producer to produce 11 Produced 12 Produced 13 Produced

    Saturday, 13 October 2018


    • LRU Cache (Java) Design and implement a data structure for Least Recently Used (LRU) cache. 
    • The LRU caching scheme is to remove the least recently used frame when the cache is full and a new page is referenced which is not there in cache.
    • Properties are,
      • Fixed Size: Cache needs to have some bounds to limit memory usages.
      • Fast Access: Cache Insert and lookup operation should be fast , preferably O(1) time.
      • Replacement of Entry in case , Memory Limit is reached: A cache should have efficient algorithm to evict the entry when memory is full.
    • When we think about O(1) lookup , obvious data structure comes in our mind is HashMap. HashMap provide O(1) insertion and lookup.
    • but HashMap does not has mechanism of tracking which entry has been queried recently and which not.To track this we require another data-structure which provide fast insertion ,deletion and updation , in case of LRU we use Doubly Linkedlist . 
    • Reason for choosing doubly LinkList is O(1) deletion , updation and insertion if we have the address of Node on which this operation has to perform.
    •  HashMap will hold the keys and address of the Nodes of Doubly LinkedList . And Doubly LinkedList will hold the values of keys.
    • As We need to keep track of Recently used entries, We will use a clever approach. We will remove element from bottom and add element on start of LinkedList and whenever any entry is accessed , it will be moved to top. so that recently used entries will be on Top and Least used will be on Bottom.

    • package com.iwq.LRU.withhashmap; import java.util.HashMap; import java.util.Map; public class LRUcache { Map hashmap = new HashMap(); Entry start; Entry end; int LRU_SIZE = 4; public void put(int key, int value) { // if key already exists update value and move to top if (hashmap.containsKey(key)) // Key Already Exist, just update the value and move it to top { Entry entry = hashmap.get(key); entry.value = value; removeNode(entry); addAtTop(entry); } else { Entry newnode = new Entry(); newnode.left = null; newnode.right = null; newnode.value = value; newnode.key = key; if (hashmap.size() > LRU_SIZE) // We have reached maxium size so need to make room for new element. { hashmap.remove(end.key); removeNode(end); addAtTop(newnode); } else { addAtTop(newnode); } hashmap.put(key, newnode); } } public void removeNode(Entry node) { // remove from left and right nodes if (node.left != null) { node.left.right = node.right; } else { start = node.right; } if (node.right != null) { node.right.left = node.left; } else { end = node.left; } } public void addAtTop(Entry node) { // node.right = start; node.left = null; if (start != null) start.left = node; start = node; if (end == null) end = start; } }

    Friday, 12 October 2018


    1. What is a Query Plan?
      1. A query plan is a set of steps that the database management system executes in order to complete the query. 
      2. The reason we have query plans is that the SQL you write may declare your intentions, but it does not tell SQL the exact logic flow to use.  The query optimizer determines that.  The result of that is the query plan
      3. The lesson to learn from this when in doubt check the execution plan.  If you feel a query is running slow and an equivalent query, such as a join, may be faster, write one up and check the plan.  Check to see which uses more efficient steps.  This much better than guessing.  As you get better a reading plans you’ll start to notice things about your databases, such as whether you need to add an index.
    2. Database Indexes
      1. Indexes are special lookup tables that the database search engine can use to speed up data retrieval.
      2. An index helps to speed up SELECT queries and WHERE clauses, but it slows down data input, with the UPDATE and the INSERT statements. Indexes can be created or dropped with no effect on the data.
      3. Single-Column Indexes
        1. A single-column index is created based on only one table column.
      4. Unique Indexes
        1. Unique indexes are used not only for performance, but also for data integrity. A unique index does not allow any duplicate values to be inserted into the table. The basic syntax is as follows
      5. Composite Indexes
        1. A composite index is an index on two or more columns of a table. Its basic syntax is as follows.
      6. CREATE INDEX id_index ON students (stdId) USING BTREE;
        1. Will do ab binary search on stdId column and it increases the performance.
      7. A database index is somewhat similar to this table of contents in a book. Indexing will help a data base query to be retrieved fast (Because the query does not require to go through the entire table to get the data, but it will find the data blocks from the index.).
    3. What is the difference between UNION and UNION ALL?
      1. UNION removes duplicate records (where all columns in the results are the same), UNION ALL does not.
      2. There is a performance hit when using UNION instead of UNION ALL, since the database server must do additional work to remove the duplicate rows, but usually you do not want the duplicates.
    4.  How to retrieve data from json string saved in a column?
      1. JSON
      2. {"male" : 2000, "female" : 3000, "other" : 600}
      3. Query
      4. SELECT ID, CITY, json_extract(POPULATION_JSON_DATA, '$.male') AS POPULATION_MALE, json_extract(POPULATION_JSON_DATA, '$.female') AS POPULATION_FEMALE, json_extract(POPULATION_JSON_DATA, '$.other') AS POPULATION_OTHER FROM JSON_TABLE;
    5. Oracle bind variables?
      1. Using :variable instead of direct values
      2. Before Oracle runs a SQL statement it checks it's valid and determines how to access the tables and join them together. This is called parsing. The optimizer has the task of figuring out which table access and join methods to use. This produces an execution plan. When Oracle sends a statement to the optimiser to do this it's called a hard parse.
      3. If a plan already exists for a query, Oracle doesn't need to go through the optimization process again. It can reuse the existing plan. This is referred to as soft parsing.
      4. select * from orders where order_id = :ord;
      5. If we run this query twice in succession with different values for :ord there's one hard parse and one soft parse and increases the performance.


    • Java Memory Management, with its built-in garbage collection, is one of the language's finest achievements
    •  It allows developers to create new objects without worrying explicitly about memory allocation and deallocation, because the garbage collector automatically reclaims memory for reuse
    • How Garbage Collection Really Works
      • Many people think garbage collection collects and discards dead objects. In reality, Java garbage collection is doing the opposite! Live objects are tracked and everything else designated garbage.
      • Object creation is faster because global synchronization with the operating system is not needed for every single object. An allocation simply claims some portion of a memory array and moves the offset pointer forward . The next allocation starts at this offset and claims the next portion of the array.
      • When an object is no longer used, the garbage collector reclaims the underlying memory and reuses it for future object allocation. This means there is no explicit deletion and no memory is given back to the operating system.
    • All objects are allocated on the heap area managed by the JVM. Every item that the developer uses is treated this way, including class objects, static variables, and even the code itself. As long as an object is being referenced, the JVM considers it alive. Once an object is no longer referenced and therefore is not reachable by the application code, the garbage collector removes it and reclaims the unused memory.
    • There are four kinds of GC roots in Java:
      • Local variables are kept alive by the stack of a thread. This is not a real object virtual reference and thus is not visible. For all intents and purposes, local variables are GC roots
      • Active Java threads are always considered live objects and are therefore GC roots. This is especially important for thread local variables. 
      • Static variables are referenced by their classes. This fact makes them de facto GC roots. Classes themselves can be garbage-collected, which would remove all referenced static variables. This is of special importance when we use application servers, OSGi containers or class loaders in general. We will discuss the related problems in the Problem Patterns section.
      • JNI References are Java objects that the native code has created as part of a JNI call. Objects thus created are treated specially because the JVM does not know if it is being referenced by the native code or not. Such objects represent a very special form of GC root, which we will examine in more detail in the Problem Patterns section below.
    • Marking and Sweeping Away Garbage
      • To determine which objects are no longer in use, the JVM intermittently runs what is very aptly called a mark-and-sweep algorithm
      • it's a straightforward, two-step process:
        • The algorithm traverses all object references, starting with the GC roots, and marks every object found as alive.
        • All of the heap memory that is not occupied by marked objects is reclaimed. It is simply marked as free, essentially swept free of unused objects.
        • It's possible to have unused objects that are still reachable by an application because the developer simply forgot to dereference them. Such objects cannot be garbage-collected.




    1. Java 8  : How to Sort a List using lambdas?
      1. Integer[] arr = { 1, 7, 3, 9, 4, 67, 100, 23, 26, 76, 8 }; List list = Arrays.asList(arr); list.sort((a1, a2) -> a1.compareTo(a2)); System.out.print(list);
    2. Is singleton is lazy initialisation?
      1. Yes. As in the below code singleton is lazy initialisation.
      2. We will not initialise on static instance property. And initialise only on getInstance method, so it will initialise on required time only and lazy loading. If we need to make it as eager initialise instance on static field, then it will initialise on the time of class loading.
      3. public class Singleton { private static Singleton instance; private LazyInitializedSingleton(){ } public static Singleton getInstance(){ if(instance == null){ synchronized (DclSingleton.class) { instance = new Singleton(); } } return instance; } }
    3. How to find the nth element In QUEUE?
      1. The fact that accessing elements by index is not part of the concept of a queue.If you need to access elements by index, you want a list, not a queue.
    4. What is a partially checked exception in Java?
      1. A checked exception is said to be partially checked exception if and only if some of its child classes are unchecked 
        1. Ex: Exception
      2. The only possible partially checked exception in java are  
        1. Exception 
        2. Throwable 
    5. String intern()?
      1. The java string intern() method returns the interned string. It returns the canonical representation of string.
      2. It can be used to return string from memory, if it is created by new keyword. It creates exact copy of heap string object in string constant pool.
      3. public class InternExample{ public static void main(String args[]){ String s1=new String("hello"); String s2="hello"; String s3=s1.intern();//returns string from pool, now it will be same as s2 System.out.println(s1==s2);//false because reference variables are pointing to different instance System.out.println(s2==s3);//true because reference variables are pointing to same instance } }
    6. Can an abstract class have main method and run it?
      1. Yes. It have main method and run. But canot create its own object,.
      2. public abstract class AbstractMainEx { public static void main(String[] args) { System.out.println("Hi"); } public abstract boolean test(); }
    7. How to create a custom Exception?
      1. To create you own exception extend the Exception class or any of its subclasses.
      2. class New1Exception extends Exception { } // this will create Checked Exception class NewException extends IOException { } // this will create Checked exception class NewException extends NullPonterExcpetion { } // this will create UnChecked exception
    8. Can we have private constructor for parent constructor in inheritance?
      1. No
      2. Implicit super constructor Animal() is not visible for default constructor. Must define an explicit 
         constructor



    • It is the first concurrent utility framework in java and used for standardising invocation, scheduling, execution and control of asynchronous tasks in parallel threads.
    • Executor implementation in java uses thread pools which consists of worker threads. The entire management of worker threads is handled by the framework. So the overhead in memory management is much reduced compared to earlier multithreading approaches.
    • The Java Executor framework creates tasks by using instances of Runnable or Callable. In case of Runnable, the run () method does not return a value or throw any checked exception. But Callable is a more functional version in that area. It defines a call () method that allows the return of some computed value which can be used in future processing and it also throws an exception if necessary.
    • The FutureTask class is another important component which is used to get future information about the processing. An instance of this class can wrap either a Callable or a Runnable. You can get an instance of this as the return value of submit () method of an ExecutorService. You can also manually wrap your task in a FutureTask before calling execute () method.
    • Following are the functional steps to implement the Java ThreadPoolExecutor.
      • Create an executor
        •  Executor class has a number of static factory methods to create an ExecutorService depending upon the requirement of the application.
          • The newFixedThreadPool () returns a ThreadPoolExecutor instance with an initialized and unbounded queue and a fixed number of threads.
          • The newCachedThreadPool () returns a ThreadPoolExecutor instance initialized with an unbounded queue and unbounded number of threads
        • newFixedThreadPool ()
          • No extra thread is created during execution
          • If there is no free thread available the task has to wait and then execute when one thread is free
        • newCachedThreadPool ()
          • Existing threads are reused if available. But if no free thread is available, a new one is created and added to the pool to complete the new task. Threads that have been idle for longer than a timeout period will be removed automatically from the pool.
        • This is a fixed pool of 10 threads.
        private static final Executor executor = Executors.newFixedThreadPool(10);
        • This is a cached thread pool
        private static ExecutorService exec = Executors.newCachedThreadPool();
        • Following is an example of customized thread pool executor. The parameter values depend upon the application need. Here the core pool is having 8 threads which can run concurrently and the maximum number is 12. The queue is capable of keeping 250 tasks. Here one point should be remembered that the pool size should be kept on a higher side to accommodate all tasks. The idle time limit is kept as 5 ms.
        private static final Executor executor = new ThreadPoolExecutor(5, 12, 50000L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue(250));
      • Create one or more tasks and put in the queue
        • After creating the executor now it’s time for creating tasks. Create one or more tasks to be performed as instances of either Runnable or Callable. In this framework, all the tasks are created and populated in a queue. After the task creation is complete the populated queue is submitted for concurrent execution.
      • Submit the task to the Executor
        • After creating the ExecutorService and proposed tasks, you need to submit the task to the executor by using either submit () or execute () method. Now as per your configuration the tasks will be picked up from the queue and run concurrently. For example if you have configured 5 concurrent executions, then 5 tasks will be picked up from the queue and run in parallel. This process will continue till all the tasks are finished from the queue.
      • Execute the task
        • Next the actual execution of the tasks will be managed by the framework. The Executor is responsible for managing the task’s execution, thread pool, synchronization and queue. If the pool has less than its configured number of minimum threads, new threads will be created as per requirement to handle queued tasks until that limit is reached. If the number is higher than the configured minimum, then the pool will not start any more threads. Instead, the task is queued until a thread is freed up to process the request. If the queue is full, then a new thread is started to handle it. But again it depends upon the type of constructor used during executor creation.
      • Shutdown the Executor
        • The termination is executed by invoking its shutdown () method. You can choose to terminate it gracefully, or abruptly.


    • A Semaphore is a thread synchronization construct that can be used either to send signals between threads to avoid missed signals, or to guard a critical section like you would with a lock
    • Simple Semaphore implementation:
      • The take() method sends a signal which is stored internally in the Semaphore. The release() method waits for a signal. When received the signal flag is cleared again, and the release() method exited.
      • // Prototype pattern public abstract class Prototype implements Cloneable { public Prototype clone() throws CloneNotSupportedException{ return (Prototype) super.clone(); } } public class ConcretePrototype1 extends Prototype { @Override public Prototype clone() throws CloneNotSupportedException { return (ConcretePrototype1)super.clone(); } } public class ConcretePrototype2 extends Prototype { @Override public Prototype clone() throws CloneNotSupportedException { return (ConcretePrototype2)super.clone(); } }
      • Using a semaphore like this you can avoid missed signals. You will call take() instead of notify() and release() instead of wait().
    • Using Semaphores for Signaling
      • Here is a simplified example of two threads signaling each other using a Semaphore:
      • MainApp.java
      • Semaphore semaphore = new Semaphore(); SendingThread sender = new SendingThread(semaphore); ReceivingThread receiver = new ReceivingThread(semaphore); receiver.start(); sender.start();
      • SendingThread.java
      • public class SendingThread { Semaphore semaphore = null; public SendingThread(Semaphore semaphore){ this.semaphore = semaphore; } public void run(){ while(true){ //do something, then signal this.semaphore.take(); } } }
      • RecevingThread.java
      • public class RecevingThread { Semaphore semaphore = null; public ReceivingThread(Semaphore semaphore){ this.semaphore = semaphore; } public void run(){ while(true){ this.semaphore.release(); //receive signal, then do something... } } }
    • Semaphore to block threads


    1. How Volatile in Java works?
      1. The Java volatile keyword cannot be used with method or class and it can only be used with a variable.
      2. Java volatile keyword also guarantees visibility and ordering and write to any volatile variable happens before any read into the volatile variable.
      3. Example: Singleton Class 
        1. public class Singleton{ private static volatile Singleton _instance; //volatile variable public static Singleton getInstance(){ if(_instance == null){ synchronized(Singleton.class){ if(_instance == null) _instance = new Singleton(); } } return _instance; }
        2. writer thread comes out of synchronized block, memory will not be synchronized and value of _instance will not be updated in main memory. With Volatile keyword in Java, this is handled by Java himself and such updates will be visible by all reader threads.
      4. If a variable is not shared between multiple threads, you don't need to use volatile keyword with that variable.
      5. Both T1 and T2 can refer to a class containing this variable. You can then make this variable volatile, and this means that changes to that variable are immeditately visible in both threads.
      6. public class App { public static volatile boolean isEven = true; public static void main(String[] args) { Object mutex = new Object(); Thread odd = new Thread(new Runnable() { @Override public void run() { try { int i = 0; while (i < 20) { synchronized (mutex) { if (isEven) { mutex.wait(); } System.out.println("Odd"); isEven = true; mutex.notify(); } i++; } } catch (Exception e) { e.printStackTrace(); } } }); Thread even = new Thread(new Runnable() { @Override public void run() { try { int i = 0; while (i < 20) { synchronized (mutex) { if (!isEven) { mutex.wait(); } System.out.println("Even"); isEven = false; mutex.notify(); } i++; } } catch (Exception e) { e.printStackTrace(); } } }); odd.start(); even.start(); } }
      7. Volatile keyword in Java guarantees that value of the volatile variable will always be read from main memory and not from Thread's local cache.
      8. In Java reads and writes are atomic for all variables declared using Java volatile keyword (including long and double variables).
      9. Using the volatile keyword in Java on variables reduces the risk of memory consistency errors because any write to a volatile variable in Java establishes a happens-before relationship with subsequent reads of that same variable.
      10. Java volatile keyword doesn't mean atomic, its common misconception that after declaring volatile ++ will be atomic, to make the operation atomic you still need to ensure exclusive access using synchronized method or block in Java.
    2. How is CountDownLatch used in Java Multithreading?
      1. CountDownLatch works in latch principle, the main thread will wait until the gate is open. One thread waits for n threads, specified while creating the CountDownLatch.
      2. Any thread, usually the main thread of the application, which calls CountDownLatch.await() will wait until count reaches zero or it's interrupted by another thread. 
      3. All other threads are required to count down by calling CountDownLatch.countDown() once they are completed or ready.
      4. As soon as count reaches zero, the waiting thread continues. One of the disadvantages/advantages of CountDownLatch is that it's not reusable: once count reaches zero you cannot use CountDownLatch any more.
    3. can we make array volatile in java?
      1. Yes, you can make an array (both primitive and reference type array e.g. an int array and String array) volatile in Java
      2. But declaring an array volatile does NOT give volatile access to it's fields. you're declaring the reference itself volatile, not it's elements.
        1. protected volatile int[] primes = new int[10];
          1. then if you assign a new array to primes variable, change will be visible to all threads, but changes to individual indices will not be covered under volatile guarantee i.e
        2. primes = new int[20];
          1. will follow the "happens-before" rule and cause memory barrier refresh visible to all threads
        3. primes[0] = 10;
          1.  will not visible changes in all threads
      3. Same for collections also
      4. In other words you're declaring a volatile set of elements, not a set of volatile elements. The solution here is to use AtomicIntegerArray in case you want to use integers
    4.  Thread Local?
      1. The ThreadLocal class in Java enables you to create variables that can only be read and writte by the same thread
      2. private ThreadLocal myThreadLocal = new ThreadLocal();
      3. Now you can only store strings in the ThreadLocal instance.
      4. myThreadLocal.set("Hello ThreadLocal"); String threadLocalValue = myThreadLocal.get();
    5. How immutable objects manage memory ?
      1. The advantage we get with String is that a common pool of string literals is kept by the virtual machine stopping the Heap getting filled up . The reasoning behind this is that much of the memory of a program can be taken up with storing commonly used strings.
    6. How to throw exceptions from Runnable.run?
      1. Do not use Runnable interface from Thread library, but instead create your own interface with the modified signature that allows checked exception to be thrown
      2. public interface MyRunnable { void myRun ( ) throws MyException; }
      3. You may even create an adapter that converts this interface to real Runnable ( by handling checked exception ) suitable for use in Thread framework.
    7. Difference Between Daemon and User Threads?
      1. Java offers two types of threads: user threads and daemon threads.
      2. JVM will wait for all active user threads to finish their execution before it shutdown itself.
      3. Daemon thread doesn't get that preference, JVM will exit and close the Java program even if there is a daemon thread running in the background
      4.  Daemon threads are low-priority threads whose only role is to provide services to user threads..
      5. A daemon thread is a thread that does not prevent the JVM from exiting when the user thread finishes but the thread is still running. An example for a daemon thread is the garbage collection.
      6. That’s why infinite loops, which typically exist in daemon threads, will not cause problems, because any code, including the finally blocks, won’t be executed once all user threads have finished their execution. For this reason, daemon threads are not recommended for I/O tasks.
      7. // Java program to demonstrate the usage of // setDaemon() and isDaemon() method. public class DaemonThread extends Thread { public DaemonThread(String name){ super(name); } public void run() { // Checking whether the thread is Daemon or not if(Thread.currentThread().isDaemon()) { System.out.println(getName() + " is Daemon thread"); } else { System.out.println(getName() + " is User thread"); } } public static void main(String[] args) { DaemonThread t1 = new DaemonThread("t1"); DaemonThread t2 = new DaemonThread("t2"); DaemonThread t3 = new DaemonThread("t3"); // Setting user thread t1 to Daemon t1.setDaemon(true); // starting first 2 threads t1.start(); t2.start(); // Setting user thread t3 to Daemon t3.setDaemon(true); t3.start(); } } ######OUT PUT#### t1 is Daemon thread t2 is User thread


    • If your code is executing in a multi-threaded environment, you need synchronization for objects, which are shared among multiple threads, to avoid any corruption of state or any kind of unexpected behavior.
    • Synchronization in Java will only be needed if shared object is mutable.
    • JVM guarantees that Java synchronized code will only be executed by one thread at a time
    • we can not have synchronized variable in java. Using synchronized keyword with a variable is illegal and will result in compilation error. You can use java synchronized keyword only on synchronized method or synchronized block.
    • we need to take care is that static synchronized method locked on class object lock and nonstatic synchronized method locks on current object (this). So it’s possible that both static and nonstatic java synchronized method running in parallel
    • public class Counter{ private static int count = 0; public static synchronized int getCount(){ return count; } public synchoronized setCount(int count){ this.count = count; } }
    • In this example of Java, the synchronization code is not properly synchronized because both getCount() and setCount() are not getting locked on the same object and can run in parallel which may result in the incorrect count.
    • Whenever a thread enters into java synchronized method or blocks it acquires a lock and whenever it leaves java synchronized method or block it releases the lock. The lock is released even if thread leaves synchronized method after completion or due to any Error or Exception.
    • Object level lock
      •  Java Thread acquires an object level lock when it enters into an instance synchronized java method 
    • Class level lock 
      • Acquires a class level lock when it enters into static synchronized java method.
    • Re-entrant Lock
      •  if a java synchronized method calls another synchronized method which requires the same lock then the current thread which is holding lock can enter into that method without acquiring the lock.
    • Locks
      • One Major disadvantage of Java synchronized keyword is that it doesn't allow concurrent read, which can potentially limit scalability. 
      • By using the concept of lock stripping and using different locks for reading and writing, you can overcome this limitation of synchronized in Java. You will be glad to know that java.util.concurrent.locks.ReentrantReadWriteLock provides ready-made implementation of ReadWriteLock in Java.
    • One more limitation of java synchronized keyword is that it can only be used to control access to a shared object within the same JVM. If you have more than one JVM and need to synchronize access to a shared file system or database, the Java synchronized keyword is not at all sufficient. You need to implement a kind of global lock for that.
    • Java synchronized block is better than java synchronized method in Java because by using synchronized block you can only lock critical section of code and avoid locking the whole method which can possibly degrade performance.
    • Do not synchronize on the non-final field on synchronized block in Java. because the reference of the non-final field may change anytime and then different thread might synchronizing on different objects i.e. no synchronization at all.
    • Locks vs Synchronisation
      • Synchronisation
        • One thread at a time and other threads waiting
        • Cannot do multi read even no write happening
        • Cannot interrupt any thread which is waiting for acquire lock
        • Cannot change priority of threads
      • Locks
        • Lock comes under java.util.concurrent.Lock
        • One thread at a time and other threads waiting
        • ReetantReadWriteLock.readLock
        • ReetantReadWriteLock.writeLock
        • Allows multiple reads as long as no write happens
        • tryLock ->if lock available lock it 
        • Fairness Policy
          • Longest waiting will get higher priority
        • Able interrupt thread

    Thursday, 11 October 2018


    • S.O.L.I.D is an acronym for the first five object-oriented design(OOD) principles by Robert C. Martin, popularly known as Uncle Bob.
    • These principles, when combined together, make it easy for a programmer to develop software that are easy to maintain and extend
    • They also make it easy for developers to avoid code smells, easily refactor code, and are also a part of the agile or adaptive software development.
      • S - Single-responsiblity principle
      • O - Open-closed principle
      • L - Liskov substitution principle
      • I - Interface segregation principle
      • D - Dependency Inversion Principle
    • Single-responsibility Principle(like Encapsulation)
      • A class should have one and only one reason to change, meaning that a class should have only one job.
      • SOLID Principles and Design Patterns plays a key role in achieving all of the above points.
        • Each class and module should focus on a single task at a time
        • Everything in the class should be related to that single purpose
        • There can be many members in the class as long as they related to the single responsibility
        • With SRP, classes become smaller and cleaner
        • Code is less fragile
        • class Circle { public $radius; public function **construct($radius) { $this->radius = $radius; } } class Square { public $length; public function **construct($length) { $this->length = $length; } }
    • Open-closed Principle(like Abstraction)
      • Objects or entities should be open for extension, but closed for modification.
      • This simply means that a class should be easily extendable without modifying the class itself. 
      • Implementation
        •  The simplest way to apply OCP is to implement the new functionality on new derived (sub) classes that inherit the original class implementation.
        • Another way is to allow client  to access the original class with an abstract interface
    • Liskov substitution principle(like Aggregation)
      • Substitutability is a principle in object-oriented programming and it states that, in a computer program, if S is a Subtype of T, then objects of type T may be replaced with objects of type S
      •  This principle is just an extension of the Open Close Principle 
    • Interface segregation principle(avoid unused methods from interface)
      • The interface-segregation principle (ISP) states that "no client should be forced to depend on methods it does not use".
      • Which means, Instead of one fat interface many small interfaces are preferred based on groups of methods with each one serving one submodule 
    • Dependency Inversion principle
      • High-level modules should not depend on low-level modules. Both should depend on abstractions.
      • Abstractions should not depend on concrete. Concrete should depend on abstractions.
      • Exmaple:
        • The PasswordReminder class should not care what database your application uses, to fix this again we "code to an interface", since high level and low level modules should depend on abstraction, we can create an interface:

    Tuesday, 9 October 2018


    • Prototype pattern refers to creating duplicate object 
    • This pattern involves implementing a prototype interface which tells to create a clone of the current object. This pattern is used when creation of object directly is costly. For example, an object is to be created after a costly database operation. We can cache the object, returns its clone on next request and update the database as and when needed thus reducing database calls.
    • // Prototype pattern public abstract class Prototype implements Cloneable { public Prototype clone() throws CloneNotSupportedException{ return (Prototype) super.clone(); } } public class ConcretePrototype1 extends Prototype { @Override public Prototype clone() throws CloneNotSupportedException { return (ConcretePrototype1)super.clone(); } } public class ConcretePrototype2 extends Prototype { @Override public Prototype clone() throws CloneNotSupportedException { return (ConcretePrototype2)super.clone(); } }


    • This pattern involves a single class which is responsible to create an object while making sure that only single object gets created.
    • SingleObject class have its constructor as private and have a static instance of itself.                                         
    1. Create a Singleton Class.
    public class SingleObject { //create an object of SingleObject private static SingleObject instance = new SingleObject(); //make the constructor private so that this class cannot be //instantiated private SingleObject(){} //Get the only object available public static SingleObject getInstance(){ return instance; } public void showMessage(){ System.out.println("Hello World!"); } }
    1. Get the only object from the singleton class.
    public class SingletonPatternDemo { public static void main(String[] args) { //illegal construct //Compile Time Error: The constructor SingleObject() is not visible //SingleObject object = new SingleObject(); //Get the only object available SingleObject object = SingleObject.getInstance(); //show the message object.showMessage(); } }

    • Abstract Factory patterns work around a super-factory which creates other factories. This factory is also called as factory of factories. This type of design pattern comes under creational pattern as this pattern provides one of the best ways to create an object.
    • In Abstract Factory pattern an interface is responsible for creating a factory of related objects without explicitly specifying their classes. Each generated factory can give the objects as per the Factory pattern.
    • We are going to create a Shape and Color interfaces and concrete classes implementing these interfaces. We create an abstract factory class AbstractFactory as next step. Factory classes ShapeFactory and ColorFactory are defined where each factory extends AbstractFactory. A factory creator/generator class FactoryProducer is created.
    • Step 1
    • public interface Shape { void draw(); }
    • Step 2
    • public class Rectangle implements Shape { @Override public void draw() { System.out.println("Inside Rectangle::draw() method."); } }

    • public class Square implements Shape { @Override public void draw() { System.out.println("Inside Square::draw() method."); } }

    • public class Circle implements Shape { @Override public void draw() { System.out.println("Inside Circle::draw() method."); } }
    • Step 3
    • public interface Color { void fill(); }
    • Step 4
    • public class Red implements Color { @Override public void fill() { System.out.println("Inside Red::fill() method."); } }

    • public class Blue implements Color { @Override public void fill() { System.out.println("Inside Blue::fill() method."); } }

    • public class Green implements Color { @Override public void fill() { System.out.println("Inside Green::fill() method."); } }
    • Step 5
    • public abstract class AbstractFactory { abstract Color getColor(String color); abstract Shape getShape(String shape) ; }
    • Step 6
    • public class ShapeFactory extends AbstractFactory { @Override public Shape getShape(String shapeType){ if(shapeType == null){ return null; } if(shapeType.equalsIgnoreCase("CIRCLE")){ return new Circle(); }else if(shapeType.equalsIgnoreCase("RECTANGLE")){ return new Rectangle(); }else if(shapeType.equalsIgnoreCase("SQUARE")){ return new Square(); } return null; } @Override Color getColor(String color) { return null; } }

    • public class ColorFactory extends AbstractFactory { @Override public Shape getShape(String shapeType){ return null; } @Override Color getColor(String color) { if(color == null){ return null; } if(color.equalsIgnoreCase("RED")){ return new Red(); }else if(color.equalsIgnoreCase("GREEN")){ return new Green(); }else if(color.equalsIgnoreCase("BLUE")){ return new Blue(); } return null; } }
    • Step 7
    • public class FactoryProducer { public static AbstractFactory getFactory(String choice){ if(choice.equalsIgnoreCase("SHAPE")){ return new ShapeFactory(); }else if(choice.equalsIgnoreCase("COLOR")){ return new ColorFactory(); } return null; } }
    • Step 8
    • public class AbstractFactoryPatternDemo { public static void main(String[] args) { //get shape factory AbstractFactory shapeFactory = FactoryProducer.getFactory("SHAPE"); //get an object of Shape Circle Shape shape1 = shapeFactory.getShape("CIRCLE"); //call draw method of Shape Circle shape1.draw(); //get an object of Shape Rectangle Shape shape2 = shapeFactory.getShape("RECTANGLE"); //call draw method of Shape Rectangle shape2.draw(); //get an object of Shape Square Shape shape3 = shapeFactory.getShape("SQUARE"); //call draw method of Shape Square shape3.draw(); //get color factory AbstractFactory colorFactory = FactoryProducer.getFactory("COLOR"); //get an object of Color Red Color color1 = colorFactory.getColor("RED"); //call fill method of Red color1.fill(); //get an object of Color Green Color color2 = colorFactory.getColor("Green"); //call fill method of Green color2.fill(); //get an object of Color Blue Color color3 = colorFactory.getColor("BLUE"); //call fill method of Color Blue color3.fill(); } }
    • Step 2



    • The factory method pattern is a creational pattern that uses factory methods to deal with the problem of creating objects without having to specify the exact class of the object that will be created.
    • Design problems to design flexible and reusable object-oriented software, that is, objects that are easier to implement, change, test, and reuse.
    • The Factory Method design pattern solves problems like
      • How can an object be created so that subclasses can redefine which class to instantiate?
    • Creating an object directly within the class that requires (uses) the object is inflexible because it commits the class to a particular object and makes it impossible to change the instantiation independently from (without having to change) the class.
    • Factory Method design pattern will,
      • Define a separate operation (factory method) for creating an object.
      • Create an object by calling a factory method.
    • In this way subcalss can redefine which class to initiate

    • Step 1
      • Create an interface.
      • public interface Shape { void draw(); }
    • Step 2
      • Create concrete classes implementing the same interface.
      • Rectangle.java
      • public class Rectangle implements Shape { @Override public void draw() { System.out.println("Inside Rectangle::draw() method."); } }
      • Square.java
      • public class Square implements Shape { @Override public void draw() { System.out.println("Inside Square::draw() method."); } }
      • public class Circle implements Shape { @Override public void draw() { System.out.println("Inside Circle::draw() method."); } }
          
    • Step 3
      • Create a Factory to generate object of concrete class based on given information
      • ShapeFactory.java
      • public class ShapeFactory { //use getShape method to get object of type shape public Shape getShape(String shapeType){ if(shapeType == null){ return null; } if(shapeType.equalsIgnoreCase("CIRCLE")){ return new Circle(); } else if(shapeType.equalsIgnoreCase("RECTANGLE")){ return new Rectangle(); } else if(shapeType.equalsIgnoreCase("SQUARE")){ return new Square(); } return null; } }
    • Step 4
      • Use the Factory to get object of concrete class by passing an information such as type.
      • FactoryPatternDemo.java
      • public class FactoryPatternDemo { public static void main(String[] args) { ShapeFactory shapeFactory = new ShapeFactory(); //get an object of Circle and call its draw method. Shape shape1 = shapeFactory.getShape("CIRCLE"); //call draw method of Circle shape1.draw(); //get an object of Rectangle and call its draw method. Shape shape2 = shapeFactory.getShape("RECTANGLE"); //call draw method of Rectangle shape2.draw(); //get an object of Square and call its draw method. Shape shape3 = shapeFactory.getShape("SQUARE"); //call draw method of square shape3.draw(); } }


      • The Builder is a design pattern designed to provide a flexible solution to various object creation problems in object-oriented programming. 
      • The intent of the Builder design pattern is to separate the construction of a complex object from its representation.
      • The Builder design pattern solves problems like
        • Create different representations of a complex object
        • Creating a complex object be simplified
      sasasasasasasa
      /** * Represents the product created by the builder. */ class Car { private int wheels; private String color; public Car() { } public String getColor() { return color; } public void setColor(final String color) { this.color = color; } public int getWheels() { return wheels; } public void setWheels(final int wheels) { this.wheels = wheels; } @Override public String toString() { return "Car [wheels = " + wheels + ", color = " + color + "]"; } } /** * The builder abstraction. */ interface CarBuilder { Car build(); CarBuilder setColor(final String color); CarBuilder setWheels(final int wheels); } class CarBuilderImpl implements CarBuilder { private Car car; public CarBuilderImpl() { car = new Car(); } @Override public Car build() { return car; } @Override public CarBuilder setColor(final String color) { car.setColor(color); return this; } @Override public CarBuilder setWheels(final int wheels) { car.setWheels(wheels); return this; } } public class CarBuildDirector { private CarBuilder builder; public CarBuildDirector(final CarBuilder builder) { this.builder = builder; } public Car construct() { return builder.setWheels(4) .setColor("Red") .build(); } public static void main(final String[] arguments) { final CarBuilder builder = new CarBuilderImpl(); final CarBuildDirector carBuildDirector = new CarBuildDirector(builder); System.out.println(carBuildDirector.construct()); } }
      • Steps:
        • Create car builder interface
        • Car builder implementation
          • Create car object in constructor and use this object for all car object manipulation like buildCar, setCarColour ,setCarWheel etc
        • Create CarBuildDirector class with
          • initiate car builder object
          • create car using car builder methods like below
            • car builder.buildcar.setWheels(2).setColor("Red")
      • Advantages
        • Allows you to vary a product’s internal representation.
        • Encapsulates code for construction and representation.
        • Provides control over steps of construction process.
      • Disadvantages
        • Requires creating a separate ConcreteBuilder for each different type of product.
        • Requires the builder classes to be mutable.
        • Data members of class aren't guaranteed to be initialized.
        • Dependency injection may be less supported.



      • Creational design patterns are design patterns that deal with object creation mechanisms, trying to create objects in a manner suitable to the situation
      • The basic form of object creation could result in design problems or in added complexity to the design. Creational design patterns solve this problem by somehow controlling this object creation.
      • Creational design patterns are composed of two dominant ideas.
        • Encapsulating knowledge about which concrete classes the system uses.
        • Hiding how instances of these concrete classes are created and combined.
      • Creational design patterns are further categorized as
        • Object-creational patterns
          • Object-creational patterns deal with Object creation.
          • Object creation to another object
        • Class-creational patterns
          • Class-creational patterns deal with Class-instantiation.
          • Object creation to subclasses.
      • Five well-known design patterns that are parts of creational patterns are the
        • Builder pattern
          • Separate the construction of a complex object from its representation so that the same construction process can create different representations
        • Factory method pattern
          • Centralize creation of an object of a specific type choosing one of several implementations
        • Abstract factory pattern
          • A class requests the objects it requires from a factory object instead of creating the objects directly
        • Singleton pattern
          • Restrict instantiation of a class to one object
        • Prototype pattern
          • Used when the type of objects to create is determined by a prototypical instance, which is cloned to produce new objects
        • Dependency Injection pattern
          • A accepts the objects it requires from an injector instead of creating the objects directly

      Friday, 5 October 2018


      • Spring Boot is a Spring framework module which provides RAD (Rapid Application Development) feature to the Spring framework.
      •  It is highly dependent on the starter templates feature
      • Starter Template
        • Spring Boot starters are templates that contain a collection of all the relevant  dependencies that are needed to start a particular functionality. 
        • For example, If you want to create a Spring WebMVC application then in a traditional setup, you would have included all required dependencies yourself. It leaves the chances of version conflict which ultimately result in more runtime exceptions.
        • With String boot, to create MVC application all you need to import is spring-boot-starter-web dependency.
        •  We do not need to provide version information into child dependencies. All versions are resolved in relation to version of parent starter
        


      •  Bootstrap the application
        • To run the application, we need to use @SpringBootApplication annotation. Behind the scenes, that’s equivalent to @Configuration, @EnableAutoConfiguration, and @ComponentScan together.
        • It enables the scanning of config classes, files and load them into spring context. In below example, execution start with main() method. It start loading all the config files, configure them and bootstarp the application based on application properties in application.properties file in /resources folder.
        • YlbSBA.java
        • @ComponentScan({ "com.ylb.web", }) @SpringBootApplication public class YlbSBA { public static void main(String[] args) { SpringApplication.run(YlbSBA.class, args); } }
          application.properties

          ### Server port ######### server.port=8080 ### Context root ######## server.contextPath=/home

        • To execute the application, you can run the main() method from IDE such eclipse, or you can build the jar file and execute from command prompt.
        • $ java -jar spring-boot-demo.jar


      • Embedded server
        • Spring boot applications always include tomcat as embedded server dependency. It means you can run the Spring boot applications from the command prompt without needling complex server infrastructure.
        • You can exclude tomcat and include any other embedded server if you want. Or you can make exclude server environment altogether. It’s all configuration based.
        • For example, below configuration exclude tomcat and include jetty as embedded server.
        • To remove embedded tomcat and deploy in external server
          • pom.xml
            • Make starter -tomcat dependency to provided
                             
          • YLBSBA.java
            • Ovrride configure methode from SpringBootServletInitializer
            • @ComponentScan({ "com.ylb.web", }) @SpringBootApplication public class YlbSBA extends SpringBootServletInitializer { public static void main(String[] args) { SpringApplication.run(YlbSBA.class, args); } /** * spring boot dedicated tomcat config step #2 */ @Override protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) { return builder.sources(YlbSBA.class); } }

      • Spring boot autoconfiguration
        • Autoconfiguration is enabled with @EnableAutoConfiguration annotation. Spring boot auto configuration scans the classpath, finds the libraries in the classpath and then attempt to guess the best configuration for them, and finally configure all such beans.
      • Actuator
        • Spring Boot Actuator help you monitor and manage your application health when you push it to production.
        • You can choose to manage and monitor your application by using HTTP endpoints.
      • Advantages of Spring boot
        • Spring boot helps in resolving dependency conflict. It identifies required dependencies and import them for you.
        • It has information of compitable version for all dependencies. It minimizes the runtime classloader issues.
        • It’s “opinionated defaults configuration” approach helps you in configuring most important pieces behind the scene. Override them only when you need. Otherwise everything just works, perfectly. It helps in avoiding boilerplate code, annotations and XML configurations.
        • It provides embedded HTTP server Tomcat so that you can develop and test quickly.
        • It has excellent integration with IDEs like eclipse and intelliJ idea.
      •  Spring Cloud?
        • It provides microservices infrastructure like provide use services such as Service Discovery, Configuration server and Monitoring.
        • Eureka is the Netflix Service Discovery Server and Client. Eureka Server is using Spring Cloud.
        • @EnableEurekaServer annotation uses to create  eureka server.
        • @EnableDiscoveryClient annotation also allows us to query Discovery server to find miroservices.
        • Spring provide smart RestTemplate for service discovery and load balancing by using @LoadBalanced annotation with RestTemplate instance.
        • @EnableEurekaClient makes Micro-service as EurekaClient

      Search This Blog

      Contact us

      Name

      Email *

      Message *