Spring Boot Integration Picocli Quick Start Demo

HBLOG
3 min readMay 16, 2024

--

1. What is Picocli?

Picocli is a single-file command-line parsing framework that allows you to create command-line applications with little to no code. use @Option or @Parameters Comment on the fields in your app, and Picocli will populate them with command line options and positional arguments, respectively. usePicoclito write a powerful command-line program.

pain point

  • There is no full-fledged framework to encapsulateParameter receivingParameter hintsandParameter validation
  • It’s hard to deal with parametersmutually exclusiveas well as the mutuality of specific commandsDependencies
  • Commands cannot be madeAutocomplete
  • Since the JVM interprets the execution bytecode and the JIT cannot be usedShort-term executionJava command-line programsSlow start
  • After integrating SpringBoot and other components, the startup is even slower

2. Code engineering

Experiment purpose: Use Picocli to write an email sending command

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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>springboot-demo</artifactId>
<groupId>com.et</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>picocli</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>info.picocli</groupId>
<artifactId>picocli-spring-boot-starter</artifactId>
<version>4.7.6</version>
</dependency>
<!--email-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
</dependencies>
<!--<build>
<finalName>demo1</finalName>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<mainClass>com.et.picocli.MySpringMailer</mainClass>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>-->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>

</project>

Startup class

package com.et.picocli;
import com.et.picocli.command.MailCommand;
import org.springframework.boot.*;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import picocli.CommandLine;
import picocli.CommandLine.IFactory;
@SpringBootApplication
public class MySpringMailer implements CommandLineRunner, ExitCodeGenerator {
private IFactory factory;
private MailCommand mailCommand;
private int exitCode;
// constructor injection
MySpringMailer(IFactory factory, MailCommand mailCommand) {
this.factory = factory;
this.mailCommand = mailCommand;
}
@Override
public void run(String... args) {
// let picocli parse command line args and run the business logic
exitCode = new CommandLine(mailCommand, factory).execute(args);
}
@Override
public int getExitCode() {
return exitCode;
}
public static void main(String[] args) {
// let Spring instantiate and inject dependencies
System.exit(SpringApplication.exit(SpringApplication.run(MySpringMailer.class, args)));
}
}

service

package com.et.picocli.service;
import java.util.List;
public interface IMailService {
void sendMessage(List<String> to, String subject, String text);
}
package com.et.picocli.service;
import org.slf4j.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.*;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Service;
import java.util.List;
@Service("MailService")
public class MailServiceImpl implements IMailService {
private static final Logger LOGGER= LoggerFactory.getLogger(MailServiceImpl.class);
private static final String NOREPLY_ADDRESS = "noreply@picocli.info";
@Autowired(required = false)
private JavaMailSender emailSender;
@Override
public void sendMessage(List<String> to, String subject, String text) {
LOGGER.info(" start Mail to {} sent! Subject: {}, Body: {}", to, subject, text);
try {
SimpleMailMessage message = new SimpleMailMessage(); // create message
message.setFrom(NOREPLY_ADDRESS); // compose message
for (String recipient : to) { message.setTo(recipient); }
message.setSubject(subject);
message.setText(text);
emailSender.send(message); // send message
LOGGER.info(" end Mail to {} sent! Subject: {}, Body: {}", to, subject, text);
}
catch (MailException e) { e.printStackTrace(); }
}
}

command

package com.et.picocli.command;
import com.et.picocli.service.IMailService;
import org.springframework.stereotype.Component;
import org.springframework.beans.factory.annotation.Autowired;
import picocli.CommandLine;
import picocli.CommandLine.*;
import java.util.List;
import java.util.concurrent.Callable;
@Component
//@Command(name = "mailCommand")
@CommandLine.Command(
subcommands = {
GitAddCommand.class,
GitCommitCommand.class
}
)
public class
MailCommand implements Callable<Integer> {
@Autowired
private IMailService mailService;
@Option(names = "--to", description = "email(s) of recipient(s)", required = true)
List<String> to;
@Option(names = "--subject", description = "Subject")
String subject;
@Parameters(description = "Message to be sent")
String[] body = {};
public Integer call() throws Exception {
mailService.sendMessage(to, subject, String.join(" ", body));
return 0;
}
}

application.properties

# configuration mail service
spring.mail.host=smtp.gmail.com
spring.mail.port=587
spring.mail.username=email
spring.mail.password=password
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.properties.mail.smtp.starttls.required=true

The above are just some of the key codes, all of which can be found in the repositories below

Code repositories

3. Testing

Package the Spring Boot application

mvn install

Go to the target directory

cd target

Execute the command

//send mail 
java -jar picocli-1.0-SNAPSHOT.jar --to ss@163.com --subject testmail text 111111
//sub command
java -jar picocli-1.0-SNAPSHOT.jar --to ss@163.com --subject testmail text 111111 add

Print help

java -jar picocli-1.0-SNAPSHOT.jar --help

4. References

--

--

HBLOG
HBLOG

Written by HBLOG

talk is cheap ,show me your code

No responses yet