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:

	<dependency>
		<groupId>org.springframework.shell</groupId>
		<artifactId>spring-shell-starter</artifactId>
		<version>2.0.1.RELEASE</version>
	</dependency>

The above dependency will download Springshell jars.

Lets create a main class for springboot application,

@SpringBootApplication
public class ShellApplication {

	public static void main(String[] args) {
		SpringApplication.run(ShellApplication.class, args);
	}

}

Now let us create our shell class,

@ShellComponent
public class ShellOperations {

@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 (value = "Displaying Shell Method")
public String display(String s) {
     return "Shell Command Executed "+s;
}

@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,

shell:>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,

@ShellMethod(value = "Adding 2 numbers")
public Integer add(Integer a, Integer b) {
    return a+b;
}

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.

@ShellMethod(value = "Default parameter")
public String defaultDisplay(@ShellOption(defaultValue="Hello this is default") String s) {
    return s;
}

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.

@ShellMethod(value = "validation 1")
public Integer validateDisplay1(@Size(min=2,max=4) Integer s) {
    return s;
}
	
@ShellMethod(value = "validation 2")
public String validateDisplay2(@NotNull String s) {
    return s;
}

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,

@Configuration
public class ShellPromptProvider implements PromptProvider{

	@Override
	public AttributedString getPrompt() {
		String s = "ShellCommandPrompt:>";
		return new AttributedString(s, 0,s.length()-1);
	}

}

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,

ShellApplication.java

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class ShellApplication {

	public static void main(String[] args) {
		SpringApplication.run(ShellApplication.class, args);
	}

}

ShellOperations.java

import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;

import org.springframework.shell.standard.ShellComponent;
import org.springframework.shell.standard.ShellMethod;
import org.springframework.shell.standard.ShellOption;

@ShellComponent
public class ShellOperations {
	
	@ShellMethod (value = "Displaying Shell Method")
	public String display(String s) {
		return "Shell Command Executed "+s;
	}
	
	@ShellMethod(value = "Adding 2 numbers")
	public Integer add(Integer a, Integer b) {
		return a+b;
	}
	
	@ShellMethod(value = "Default parameter")
	public String defaultDisplay(@ShellOption(defaultValue="Hello this is default") String s) {
		return s;
	}
	
	@ShellMethod(value = "validation 1")
	public String validateDisplay1(@Size(min=2,max=4) String s) {
		return s;
	}
	
	@ShellMethod(value = "validation 2")
	public String validateDisplay2(@NotNull String s) {
		return s;
	}

}

ShellPromptProvider.java

import org.jline.utils.AttributedString;
import org.springframework.context.annotation.Configuration;
import org.springframework.shell.jline.PromptProvider;

@Configuration
public class ShellPromptProvider implements PromptProvider{

	@Override
	public AttributedString getPrompt() {
		String s = "ShellCommandPrompt:>";
		return new AttributedString(s, 0,s.length()-1);
	}

}

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.4.2</version>
		<relativePath /> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.javainfinite</groupId>
	<artifactId>Shell</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>Shell</name>
	<description>Demo project for Spring Boot</description>
	<properties>
		<java.version>1.8</java.version>
	</properties>
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter</artifactId>
		</dependency>

	<!-- https://mvnrepository.com/artifact/org.springframework.shell/spring-shell-starter -->
	<dependency>
		<groupId>org.springframework.shell</groupId>
		<artifactId>spring-shell-starter</artifactId>
		<version>2.0.1.RELEASE</version>
	</dependency>


	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>

 

Leave a Reply

Your email address will not be published. Required fields are marked *