Integrate Shell with SpringBoot – SpringBoot Shell

Integrate Shell with SpringBoot – SpringBoot Shell:

What is a Shell?
Shell is an environment where user provides the input and it program will execute and returns the result. We can run shell with commands or scripts.

SpringBoot provides us a way to integrate this shell environment within our application. We can easily build a shell application just by including a dependency which has all Spring shell jars. We can also declare our own commands in the application to executing it.

Dependency for Shell in SpringBoot:

The above dependency will download Springshell jars.

Lets create a main class for springboot application,

Now let us create our shell class,

@ShellComponent is an stereotype kind of annotation similar to @Component, @Service etc. to make springboot to understand this class is Shell Component.

Now let us write a method for shell to execute,

@ShellMethod – This annotation is used to explicitly define the custom shell command.
We have written a method which takes String as a parameter and will return the String with – “Shell Command Executed” followed by the parameter String.

Let us check this by running our SpringBoot application,

Once we deploy the application, we will get CLI for entering shell command in our console. When we give help,


We can see the available in-build commands and the method which we have created.

display – method name
value – Description for the method which we have provided along with @ShellMethod annotation.

Now let us execute the Shell Command,

We have to give the method name – display followed by the parameter. Here we given display and parameter – ‘Success’ where we get the output – Shell Command Executed Success.

Let us see another example to perform addition of 2 numbers,

Here we have written a method to pass 2 integer parameters and returning addition of 2 values.

let us try to execute our shell command,

We have executed our add method, we have declared in 2 different ways,

We have used positional parameter concept, without giving parameter name we directly passed the values for a and b. Suppose if we have to pass based on parameter we can use the 2nd way to executing the method,

add –b 2 –a 1.

Now let us see another method to pass String parameter with default value.

We have to declare with @ShellOption value,
Here we have mentioned defaultValue for the parameter s, so if we try to execute this command even without any parameter it will return with default value.

Here we have called default-display without any parameter, it gives the default value. With parameter it gives the parameter value instead of default value.

We can also perform validation for the parameters. Let us see an example below.

Here we have 2 methods, one to check with Integer with size minimum of 2 and maximum of 4. Another method to check String is not null.

Now let us execute the commands in shell,

From the above screenshot, we can confirm the validation is done.

There is also a way where we can change the text that is being displayed in console – shell:> – we can replace this text. Let us see how to change,

We need to implement the PromptProvider interface and need to override the method – getPrompt().

We are returning new AttributedString(“String”, String start index,String end Index);

In our code we have used the String – “ShellCommandPrompt:>”. Now let use run our SpringBoot application and see our changes,

The shell:> is changed to ShellCommandPrompt: from our Configuration.

Please find the complete code below,



What happens if we do not override hashcode() and equals() in hashmap?

What happens if we do not override hashcode() and equals() in hashmap?

In this post, let us understand what is the use of equals() and hashcode(), why it is important to override them and what will happen if we dont override them

To understand this post, it is expected to have knowledge of Internal Working of HashMap.

If not aware of internal working of hashmap, lets have a quick overview.

Important Points of HashMap:

  • HashMap has Key and Value pairs.
  • HashMap is not Synchronized (i.e. Not Thread Safe)
  • HashMap has no guarantees as to the order of the map
  • HashMap does not guarantee that the order will remain constant over time.
  • HashMap allows only one Null Key, Which will always be stored at 0th position in the bucket
  • HashMap can have multiple null values, but only one null key is allowed
  • HashMap can be Synchronized externally using Collections.synchronizedMap(HashMap)

Internal Working of HashMap: (Quick Summary)
So How does HashMap works Internally?
HashMap has the implementation of Map Interface.  HashMap has key and value pairs.

The initial capacity of HashMap is 16 and where as load factor is 0.75.

What is Initial Capacity and LoadFactor?
The initial capacity is the number of buckets in the hashtable and the load factor is a measure of how full the hash table is allowed to get before its capacity is automatically increased.

When we try to put a Key and Value within HashMap, first the equals method will check whether both objects are equal and then it hashes and find the bucket where to insert this Key and Value. If both the objects are equal, it will override the already existing Object in Bucket.
In Short,  equals() will help us to identify if the object is unique and HashCode helps us to identify the bucket in which the values has to be Stored.

Now Let us see this with an Example,

For the below Example, we are going to create Employee class and another Main class.

We have created an Employee class, Now let us create a main method

equals() and hashcode() – Not Overridden:

The above code, we haven’t implemented equals() and hashcode() method. Let us the what output our code gives,

Though both objects are equal() since we haven’t overridden the equals(), so it considers both the objects as unique keys. We also haven’t overridden the hashcode(), so even when both objects are same, their hashcode is different.

How it works without Overriding equals() and hashcode()?

From the output, first it compares two objects (eventhough they are equals, since we have not overridden the equals()) it shows both the objects are not equals and will be considered as Unqiue Keys and with values.

From the hashing, it goes to different buckets – duplicate entries for same object.

Override equals() and Not hashcode:

Now let us Override only Equals() method,


Now after overriding equals method, let use slightly modify our main method,

Now after overriding only equals() method, we can see both objects are compared and identified as equals objects (Both Objects are  Equal: true)

But here the problem is, though both the objects are equal() the hashcode() is different and so the both objects will be stored in different buckets.

If both objects are equal and if it points to same bucket then the value will be overridden.

Override hashcode() and Not equals():

When we run the code,

Since we have overridden only hashcode() and not equals method() –> The objects comparison becomes false, means the objects are unique. So even though the hashcode points to same bucket, the objects are considered as unique keys and both the values will be stored in the bucket.

override both equals() and hashcode():

Now let us run the above code and see,

Since we have overridden the equals() and hashcode(), when inserting in map — It has identified both objects are equal and both has same hashcode values. So when trying to insert into the bucket, only one value will be inserted that is the reason we have only one element in hashmap (Key is: Employee@13665 Value is: Two)

Complete Code:


How does hashmap work Internally | Internal Working of HashMap

How does hashmap work Internally – Explained:

In this post, let us see how hashmap works internally – How the elements are added and retrieved from buckets.

Features of HashMap:

  • Implementation of Map Interface – With Key and Value pairs
  • No order of maps, also order of map changes over time
  • Accepts one null key and multiple null values
  • Keys should be unique and cannot have duplicates
  • Unsynchronized i.e. Not Thread Safe
  • Initial capacity is 16 and load factor is 0.75
  • Synchronized externally using Collections.SynchronizedMap(hashmap)

What is Initial Capacity and Load factor?

Initial Capacity is number of buckets in hashtable, that i.e. by default HashMap provides 16 buckets when created, we can define number of buckets required when creating the HashMap.

Load Factor indicates when a certain capacity of elements are populated in HashMap, it size will increaase. Load factor decides how much of capacity should be filled before increasing the size of hashmap.

HashMap Creation:

  • public HashMap()
  • public HashMap(int initialCapacity)
  • public HashMap(int initialCapacity, float loadFactor)
  • public HashMap(Map<? extends k, ? extends v> m) –> Cretes new HashMap with the specified Map.

To understand how hashmap works internally, let us consider we have an employee model class with a variable employee name,

Let us create employee object and put the employee object as key in HashMap and let us see how it gets inserted into HashMap.


From the above,

We have created 3 employee objects – e1, e2 and e3 with names Alpha, Beta and Charlie

Then we have put these values in hashmap with employee object as Key

HashMap<Employee, String> hm = new HashMap<Employee, String>();

hm.put(e1, “One”);
hm.put(e1, “Two”);
hm.put(e1, “Three”);

Now we have inserted the values into HashMap, we can see how they are populated in Buckets.

For our example, let us consider the hashcode values of

e1 – 756475 and it puts in bucket 2
e2 – 897865 and it puts in bucket 14
e3 – 756909 and it puts in bucket 2 again

First it checks the bucket, if any values are present. Since we do not have any values, it inserts the value in bucket 2.
It will insert hashcode first , i.e. 756475, next it will insert the key of HashMap – here the key is e1, then the value “One”, and last will be the pointer to next node. For now it will be null as no other elements are present to be populated in bucket.

Second we have the hashmap with element key e2 and value “Two”. It will check the bucket 14 and since no value is already present, it will populate the values in bucket 14.
hashcode of e2 – 897865, then the element Key, then element value, followed by the next value pointer, which is null for now.

Third, we have the hashmap with element key e3 and value “Three”. It will check for the bucket 2, and we have a value in it.

Here comes the key role for equals() method, it will check whether the e3 Key is unique when compared to e1. (e3.equals(e1)). It will return false as both objects are not equal. Then from the node which is kept as null when inserting first element, will point to next element i.e. e3.

In the same bucket as second entry, e3 will be populated with hashcode –  756909, Key – e3, value – Three and next will be kept as null until we get another value to be populated.

e1 entry which had null next now will point to e3 entry.


What happens when we insert duplicate Key?

Here we have created another employee object e4, with same value as of e1.

Employee e4 = new Employee(“Alpha”);

hm.put(e4, “Four”);

How as we discussed, it will calculate the hashcode for the object e4. The hascode is 756475 and it points to bucket 2.

But the bucket 2 already has more records available. So first will check for hashcode, if the inserting record hashcode and available record hashcode matches, then it will compare the Key. This is where equals() plays an important role.

In the above case, e1.equals(e4) which will return true as both objects are equal. Then the values of object e1 will be replaced with values of e4.

so now the hashbucket first entry will be of e4 values,

Important Keypoints:

  • HashMap uses hashcode() to identify the bucket where the record to be inserted
  • If a record is already available in the bucket, it will check for key (to check uniqueness) with equals() method, if it return true then the record will be replaced. If it false, new record will be inserted.
  • When more than one record is available in the bucket, it will have a next node which will point to the next available record in the bucket.

How does get() method work in HashMap?

Now let us try to retrieve an element from hashmap, let us retrieve e3,


Now hashmap will use hashcode() and will identify the bucket in which element might be present. Next it will go to the bucket (In this case 2) and finds more than one record is available.

Now it will compare the key, if both the keys are matched then it will retrieve the value.



So When we try to get e3, first it will calculate the hashcode

hashcode() for Key e3 : 756909 and based on indexing to identify the bucket, it is calculated to be Bucket 2.

But Bucket 2, already has more than one record. Next the calculated hashcode will be compared to the inserted record in hashmap bucket 2. First it will compare 756909 with first record in hashmap that is 756475. Both are not equal, next will check the next node. Here the next node is pointing to another record. So it will go to the next record and will compare the hashcodes. 756909 and next record’s hashcode 756909 both are equal. Next will take the key of that record from bucket 2 and will compare with the key user requested. In this case, e3.equals(e3) which will return true.

Since both objects are equal and hashcodes are matching, that record will be retrieved from hashbucket and given to the user. This is how get method works.

Key Note:

If two objects are equal, their hashcode will always be same
If two hashcodes are same, that doesn’t mean both objects are equal.

Strings are Immutable | StringBuilder | StringBuffer

Strings are Immutable | StringBuilder | StringBuffer:

In this post, let us discuss about Strings, why Strings are immutable where as StringBuilder and StringBuffer are mutable.


What is Immutability?

When we assign a value to a String variable, that value can never be changed. That is known as immutability.

Strings can be created in 2 ways,

String S1 = “One”;

String S1 = new String(“One”);

What is the difference between these two ways of String creation?

String creation Way 1:

First let us see the type 1, i.e. String S1 = “One”;

For better understanding, let us create 3 strings

In general, Whenever a String is created all the values will be stored in StringPool. Here we have created 3 Strings so all these values – “One”, “Two” and “One” should be stored in StringPool.

Let us see how these above String values are Stored in StringPool.


As we can see the values – “One” and “Two” are stored in StringPool but another value of String S3 = “One” is not stored in StringPool. What actually happened?

When the values are Stored in StringPool when Strings are created in above mentioned way, When two or more strings has the same value only one of that such value will be stored in StringPool and the address of that value in StringPool will be referenced to String Variables.

So from above, since S1 and S3 has same value only one of such value is stored in StringPool and the address Addr1 will be referenced to S1 and S3

So the String variables will point to,

S1 = Addr1
S2 = Addr2
S3 = Addr1

How does “==” Work when Strings are created in above mentioned way?

The “==” works by comparing the address of the String variable rather than comparing the exact value of Strings. So in this case if we try to compare (S1==S3), Since both has same address it will
return True.

What if we concatenate the String? Will the value be replaced?

As we discussed, Strings are immutable. That is, once a value has been created that value will never change.
Consider this example,

If we concatenate String S1, what will happen?

S1 = “One” + “Three”;

Will the above statement replace the value One in StringPool? The answer is No.

Now we have concatenated the String, How the values will be at StringPool?

The new concatenated value will be inserted into StringPool and the String Variable S1 will point to new inserted value address – Addr3, Where as the value “One” remains unchanged.
This is the reason Strings are said to be Immutable.

Second way of Creating a String:

Another way of creating a String is using new Keyword, Let us create 3 strings for our understanding.

So we have created 3 Strings – S1,S2 and S3 and assigned the value – “One”, “Two” and “One” using new keyword.

How are these values stored in StringPool?

As you can see the difference, the value “One” is inserted again for the variable S3. Why?

Because the way we created String, We have used new keyword. When we create a String using new keyword, each String is considered as new value and it will be Stored in StringPool even though the same value might be available in StringPool.

So here, The String S1 will have Addr1 pointed to it, S2 will have Addr2 and S3 will have Addr3 – even though S1 and S3 has same value, since we used new keyword to insert the String – it inserted the “One” as new value and new address is given.

How does “==” Work when Strings are created in second String creation way?

Since each value is created newly and inserted in StringPool, The result will always be false for S1==S3 as both S1 and S3 have different addresses.

Why is StringBuilder and StringBuffer are mutable?

StringBuilder internally extends AbstractStringBuilder, it has a value which has an underlying working of Array. Since Arrays are mutable and StringBuilder is an Array wrapped class, it is mutable.

What if we perform Concatenation in StringBuilder?

It will not create a new value, instead it will replace the existing value with newly concatenated value

So what is the difference between StringBuilder and StringBuffer?

The only difference between StringBuilder and StringBuffer is – StringBuilder is not Synchronized (i.e. Not Thread Safe) where as StringBuffer is Synchronized (i.e.Thread Safe)

When considering the performance, StringBuilder is faster than StringBuffer because, StringBuilder is not synchronized.

Coupling | Tight Coupling vs Loose Coupling | Examples

Coupling | Tight Coupling vs Loose Coupling | Examples

What is Coupling?
When one object is used by another object it is known as Coupling. In general, it is based on dependency. One object dependency over another object.

There are two types of Coupling,

  • Tight Coupling
  • Loose Coupling

First let us see about tight coupling,

Tight Coupling:

When one object is dependent very much over another object it is known as Tight Coupling. Let us understand with an Example.

For understanding this example, let us create an interface first,

We have a Job Interface with a method display in it.

Now to understand this example, let us create 2 classes. Doctor and Engineer which implements the Job Interface.

Now in main class,

This will give us the output,

So far so good, right?

Now let us consider the scenario, The requirement changes in future. We might have to add another professional for example Scientist. What we do now?

We need to create a class, implement job interface and override display method.

In, we need to give reference to Scientist, add the Scientist variable to Constructor and create a new object and pass Scientist Object and then call display() method in App. java.

Too much of work right?

This is known as tight coupling. One object too much dependent and coupled with another object.

So how can we overcome this, here we are going to use concept of Loose coupling.

By this time, you might have guessed – Reducing the dependencies between object is known as Loose Coupling.

Now for the above same requirement with Doctor and Engineer, let us see how can we write the main class with Loosely Coupling method,

Loose Coupling:

Reducing the dependencies of one object with another object is known as Loose Coupling.

The above main method is re-written again with concept of Loose Coupling.

This code looks simpler when compared to Tight Coupled Code.

Instead of passing Doctor and Engineer objects directly, we have passed Job as reference.

During the run time we are passing the required object to perform the process. In this case, even if the requirement changes in future we do not have to make much changes for the above code.

Even when a new profession is introduced, example : Scientist. Now it is easy for us to make code changes without much change.