Sunday 18 June 2023

Executor Framework (In progress)

 Executor Framework:

Executor framework/service represents asynchronous execution mechanism which is capable of executing tasks concurrently in the background. Using executor service threads can be easily managed and scheduled.


Why executor framework is important and what are its advantages?

1)Executor service mainly separates task creation and submission. Since both are separate so we can easily replace task anytime.

2)With executor service producer and consumer design  can be easily implemented.

3)Its easy to manage and schedule threads using executor service. We don't need to write Thread Manager of our own which could be erroneous. Like to run 2 or more threads we just need to pass runnable to the execute method of the executor-service.


What are advantages of executor service over Thread approach?

1)Poor resource management:  Thread creates new resource on every request and has no limit on resource creation whereas Executor service reuses existing resources and has limit on resource creation.

2)Not robust as there is no limit on thread creation and we may get stack-overflow exception using thread approach.

3)Overhead creation of time: creation time of thread is extra overhead and is repetitive process for every thread as compared to executor service as it make use of its own threadpool.

4)Response time increases by using threadpool as thread creation time is saved.

5)With Executor service we can change execution policy whenever required by just  replacing executor service implementation class. Like if we want to change one thread to multiple thread we can do so by changing executor service implementation.


Various classes/Interfaces present in Executor framework.

Executor (I)--->ExecutorService(I)-->AbstractExecutorService(C)---->ThreadPoolExecutor(C)


Executor (I)-->ExecutorService(I)-->ScheduledExecutorService(I)-->ScheduledThreadPoolExecutor(C)


                                            Executor (I)

                                                    |

                                       ExecutorService(I)

                                                    |

                      _____________________________________

                     |                                                                           |  

   AbstractExecutorService (AC)                                ScheduledExecutorService(I)

                    |

ThreadPoolExecutor  (C)

                    |

ScheduledThreadPoolExecutor (C) implements ScheduledExecutorService

      

          

Executors  :Executors is a factory class used to create instance of the ExecutorService.


Various concrete implementation of Executor Service:

1)ThreadPoolExecutor

2)ScheduledThreadPoolExecutor

3)ForkJoinPool

    

                       






SPRING INTERVIEW QUESTIONS

1)What is Inversion of Control?

Inversion of control is a design principle in which control of object is transferred to framework. It means that it is  the framework that would take control of the flow of the program and makes calls to our custom code. Framework has abstraction around how it does that along with additional behaviour.

In IOC if we want to add our own behaviour we need to extend the classes of the framework or plugin our own classes.

                                                         OR

Inversion of Control is a design principle (many people called it pattern) which is used to invert different kind of controls in object oriented design to achieve loose coupling. Here,  control refers to any additional capabilities that a class has other than its main responsibility. This control could be control over flow of program, control over dependent object creation and binding etc.


Advantages of IOC:

Helps in creating loosely coupled classes which are easy to test , maintain and extend . It provides loosely coupling as all other task/controls are delegated to someone else rather than an individual class. For example IOC container is responsible for creating object in case of spring bean.


Various controls inverted by IOC

1)control over the flow of program

2)control over dependent object creation


Different design pattern which follow IOC

1)Factory Design pattern

2)Abstract Factory

3)Service Locator

4)Dependency Injection

5)Template Method.

 

2)What is Dependency Injection?

Dependency Injection is a design pattern to implement IOC where the control which is inverted is the way dependent objects will be created. Dependent objects wont be created by class but that will be others responsibility to do so.

 Object dependency creation in traditional programming.

public class Store {

    private Item item;

 

    public Store() {

        item = new ItemImpl1();    

    }

}


Using DI we can add dependent object without writing its implementation.


public class Store {

    private Item item;

    public Store(Item item) {

        this.item = item;

    }

}


3)Spring IOC container:

IOC container is the characteristic of the framework that implements IOC.

Responsibilities of IOC container

1)In spring interface ApplicationContext is the IOC container which is responsible for instantiating, configuring , assembling objects known as beans .

In oder to assemble beans, container uses configuration metadata which is in the form of xml or annotation.

2)It also managed the entire lifecycle of the objects from creation till removal.


Different Implementation of ApplicationContext:

1)ClassPathXMLApplicationContext for standalone application

2)FileSystemXMLApplicationContext for standalone application

3)WebApplicationContext for web application


How to initialize/instantiate  container manually:

ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");


4)Different ways to do dependency injection

    4.1)Constructors

        @Configuration // It tells that this class is source to various beans . We can have other configuration                                                   classes as well.


         class appconfig{

          @Bean

            public Item item1(){ 

            return new ItemImpl();                 

            }


          @Bean

            public Store  store(){ 

            return new Store(item1());         //Constructor DI         

            }

        }

      

    4.2)Setters

        @Configuration // It tells that this class is source to various beans . We can have other configuration                                                   classes as well.


         class appconfig{

          @Bean

            public Item item1(){ 

            return new ItemImpl();                 

            }


          @Bean

            public Store  store(){ 

             Store store= new Store();        

              store.setItem(item1());   ////Setter  DI 

           

            }

        }

    4.3)Field-Based :

             In order to inject field dependency we can use @Autowired annotation .


            public class Store {

                    @Autowired

                    private Item item; 

            }

While constructing the Store object if there is no constructor and setter method to inject item object then container uses Reflection to inject item object into store bean.

Field based dependency Injection is not recommened why?

1)becoz it uses Reflection to inject dependent object which is costly as compared to constructor or setter injection.

2)It so simple to add multiple objects and doing so violate Single responsibility of class as class is doing additional task may be.













Friday 2 June 2023

Design Patterns

1) Singleton Design Pattern: In this pattern we create the object only once and reuse existing object as object creation is costly affair.

2) Factory Design Pattern: This pattern can be used when we have multiple concrete classes and we want to centralise object creation in one place called Factory class.

    Drawbacks:

       2.1)Data is exposed to the client which is not good.

       2.2)No abstraction in object creation.

       2.3)Many if else or switch cases in case concrete classes increase.

3)Abstract Factory Design Pattern:  This can be used to overcome the limitation of Factory design pattern. In this case we create factory classes of each concrete class and those factories are exposed to the client.

         Example: Let say we have Computer class as base class and has 2 concrete class say PC and Server. So in order to create object of PC and Server we will have two factories like PCFactory and ServerFactory 

public abstract class Computer {
     
    public abstract String getRAM();
    public abstract String getHDD();
    public abstract String getCPU();
     
    @Override
    public String toString(){
        return "RAM= "+this.getRAM()+", HDD="+this.getHDD()+", CPU="+this.getCPU();
    }
}


   

  public class PC extends Computer {
    private String ram;
    private String hdd;
    private String cpu;
     
    public PC(String ram, String hdd, String cpu){
        this.ram=ram;
        this.hdd=hdd;
        this.cpu=cpu;
    }
    @Override
    public String getRAM() {
        return this.ram;
    }
 
    @Override
    public String getHDD() {
        return this.hdd;
    }
 
    @Override
    public String getCPU() {
        return this.cpu;
    }
 
}


public class Server extends Computer {
 
    private String ram;
    private String hdd;
    private String cpu;
     
    public Server(String ram, String hdd, String cpu){
        this.ram=ram;
        this.hdd=hdd;
        this.cpu=cpu;
    }
    @Override
    public String getRAM() {
        return this.ram;
    }
 
    @Override
    public String getHDD() {
        return this.hdd;
    }
 
    @Override
    public String getCPU() {
        return this.cpu;
    }
 
}

import com.journaldev.design.model.Computer;

public interface ComputerAbstractFactory {

	public Computer createComputer();

}
public class PCFactory implements ComputerAbstractFactory {

	private String ram;
	private String hdd;
	private String cpu;
	
	public PCFactory(String ram, String hdd, String cpu){
		this.ram=ram;
		this.hdd=hdd;
		this.cpu=cpu;
	}
	@Override
	public Computer createComputer() {
		return new PC(ram,hdd,cpu);
	}

}
public class ServerFactory implements ComputerAbstractFactory {

	private String ram;
	private String hdd;
	private String cpu;
	
	public ServerFactory(String ram, String hdd, String cpu){
		this.ram=ram;
		this.hdd=hdd;
		this.cpu=cpu;
	}
	
	@Override
	public Computer createComputer() {
		return new Server(ram,hdd,cpu);
	}

}

public class ComputerFactory {

	public static Computer getComputer(ComputerAbstractFactory factory){
		return factory.createComputer();
	}
}
public class TestDesignPatterns {

	public static void main(String[] args) {
		testAbstractFactory();
	}

	private static void testAbstractFactory() {
		Computer pc = ComputerFactory.getComputer(new PCFactory("2 GB","500 GB","2.4 GHz"));
		Computer server = ComputerFactory.getComputer(new ServerFactory("16 GB","1 TB","2.9 GHz"));
		System.out.println("AbstractFactory PC Config::"+pc);
		System.out.println("AbstractFactory Server Config::"+server);
	}

 

Advantages:

       3.1)Provides approach to code for interfaces rather than classes.

       3.2)Easily accomodate more classes object creation 

       3.3)Its robust and avoid conditional logic like Factory pattern.

Examples:

         javax.xml.parsers.DocumentBuilderFactory # newInstance()

         javax.xml.parsers.transform.TransformerFactory #newInstance()

        javax.xml.parsers.xpath.XPathFactory # newInstance()


4)Builder  Design Pattern: Builder is a creational patterns used to create complex objects when there are lot of attributes for object and some of them are optional and some are required. In order to create object it takes help of builder object and the idea is not expose all attributes to the client as well.



 

  

      








Saturday 6 May 2023

AWS Short Notes(In Progress)

AWS CloudFormation:

It is a template used to CRUD infrastructure in AWS environment. It has template format which is described below.

AWSTemplateFormatVersion: "version date"  (section (optional) identifies the capabilities of the template. The latest template format version is 2010-09-09 and is currently the only valid value.)

         JSON way to represent:

        "AWSTemplateFormatVersion" : "2010-09-09"

        YAML way to represent:

        AWSTemplateFormatVersion: "2010-09-09"

Description:  The Description section (optional) enables you to include comments about your template. [ 0 and 1024 bytes in length]

eg:    JSON way

           "Description" : "Here are some details about the template."

       YAML way

            Description: >

                   Here are some details about the template.


Metadata:

Parameters:

Mappings:

Conditions:

Transform:

Resources: (mandatory field)

Outputs:

Take Away: 

1)Resources is mandatory field.

2)If we have both Description and AWSTemplateFormatVersion then its mandatory for the description field to follow AWSTemplateFormatVersion . Important restriction 




Friday 5 May 2023

AWS CLI commands [In progress]

1)aws configure

2)aws configure list : will list config being used to connect to aws services. Credentials are present inside shared credentials file located in .aws/credentials file and other configs like region is present inside .aws/config



Thursday 23 March 2023

Pytest usage in Pycharm

Setup Pytest in Pycharm for running test cases 

 1)Install pytest package from python interpreter option by navigating to preferences ---->python                       interpreter

2)Create new run/debug configuration for test cases wherein following information need to be given:

    2.1) Name of the run/debug give it as per your choice.

    2.2)  Target: This will the folder under which you want to run tests . It has different options like script,              custom etc.

          * Use script if want to execute all test cases under folder/project.

         * Use custom if want to make dynamic file selection like I did by passing --tb=1 as argument . This                will   pick current file and run test cases inside that file.

3)Working directory: This is last and mandatory to specify where to pick files from. 

4)Last change is make sure you are using pytest as test runner and it is selected in preferences-->Python Integrated Tools---->Testing--->Default test Runner --(pytest)


Below is step 2 configuration screenshot



  


Thursday 5 January 2023

Mongo Commands

Basic commands in Mongo:

1)use dbname: is used to select specific database that need to be used. If no database is present , it will create new db.
2)show collections : is used to list all collection in db.
3)db.collectionName.find({}). : is used to list all documents in specific collection.
4)db.collectionName.countDocuments({}) ::  returns number of documents present in collection.
5)db.collectionName.find().sort({"date":-1}) :: sort by date in descending order .
6)db.collectionName.find().sort({"date":1}) :: sort by date in ascending order.
7)db.collectionName.deleteMany({}) :: delete all documents in collection
8)db.collectionName.deleteOne({}) :: 
9) db. collectionName .insertMany():  will create collection if does not exist with multiple insert.
10)aggregation examples: we can use aggregation whenever we want to aggregate data. Mongo supports aggregation using pipeline wherein pipeline consists of different stages. Each stage can do different task like filtering, matching , sorting on the selected set of documents. I feel like aggregation is important so putting some examples for reference. 


10.1) created demo collection with multiple records.

db.demo.insertMany([{
"tid": 1,
"sq": 1,
"state": "assigned",
"date": "2023-05-25T10:00:00.000Z"
}, {
"tid": 1,
"sq": 1,
"state": "assigned",
"date": "2023-05-25T11:00:00.000Z"
}, {
"tid": 1,
"sq": 2,
"state": "assigned",
"date": "2023-05-25T12:00:00.000Z"
}, {
"tid": 1,
"sq": 1,
"state": "assigned",
"date": "2023-05-25T12:00:00.000Z"
}, {
"tid": 1,
"sq": 2,
"state": "assigned",
"date": "2023-05-25T13:00:00.000Z"
}, {
"tid": 1,
"sq": 1,
"state": "assigned",
"date": "2023-05-25T14:00:00.000Z"
}, {
"tid": 1,
"sq": 1,
"state": "assigned",
"date": "2023-05-25T15:00:00.000Z"
}])



10.2)  Perform aggregation while using some options supported by aggregate function.


db.demo.aggregate([{
"$match": {
"state": "assigned",
"date": {
"$gte": "2023-05-25T10:00:00.000Z",
"$lte": "2023-05-26T10:00:00.000Z"
}
}
}, {
"$sort": {
"date": 1
}
}, {
"$group": {
"_id": {
"state": "$state",
"sq": "$sq",
"ticketId": "$tid"
},
"firstdate": {
"$first": "$date"
},
"lastdate": {
"$last": "$date"
},
"doc": {
"$first": "$$ROOT"
}
}
}])


10.3) Query result will be as follows: 

{
"_id": {
"state": "assigned",
"sq": 2,
"ticketId": 1
},
"firstdate": "2023-05-25T12:00:00.000Z",
"lastdate": "2023-05-25T13:00:00.000Z",
"doc": {
"_id": ObjectId("646fbf7fada80b4697d958a5"),
"tid": 1,
"sq": 2,
"state": "assigned",
"date": "2023-05-25T12:00:00.000Z"
}
} {
"_id": {
"state": "assigned",
"sq": 1,
"ticketId": 1
},
"firstdate": "2023-05-25T10:00:00.000Z",
"lastdate": "2023-05-25T15:00:00.000Z",
"doc": {
"_id": ObjectId("646fbf7fada80b4697d958a3"),
"tid": 1,
"sq": 1,
"state": "assigned",
"date": "2023-05-25T10:00:00.000Z"
}
}





9) aggregate pipeline