ballerina-platform / ballerina-lang

The Ballerina Programming Language
https://ballerina.io/
Apache License 2.0
3.55k stars 736 forks source link

[Improvement]: Bal CLI tool to cannot be written in ballerina #42729

Open niveathika opened 1 month ago

niveathika commented 1 month ago

Description

Currently, the bal tools need to be in java.

This is a restriction since logic cannot be written in ballerina as we have done in edi-tool (https://github.com/ballerina-platform/ballerina-library/issues/6473). Due to this we need a java dependency.

We need a way to write a tool in ballerina

azinneera commented 1 month ago

As per the offline discussion with @niveathika the requirement of Java for the execution of the tool is because of the way the tool's execution is written. Since the tool is written in Ballerina, an executable JAR is built and it is executed via a ProcessBuilder using the java -jar command. This is the reason for the dependency on Java.

The most ideal solution would be to be able to support tools written in Ballerina but this is not feasible to do in the near future since all the compiler APIs are written in Ballerina.

An alternative solution would be to use the JDK packed with the distribution. For this, we would need to introduce a bal command to get the JDK path used for the particular distribution which can be used to execute the EDI tool. @keizer619 @sameerajayasoma WDYT?

niveathika commented 1 month ago

Notes from offline discussion with @sameerajayasoma @azinneera @gayaldassanayake,

The ideal solution in this case would be to expose Runtime Environment of the tools package to the CLI interface. Through this any ballerina function can be invoked asynchronously. This is planned for U10.

Until this is done, we can call bal run <java-executable.jar> instead of java -jar command.

gayaldassanayake commented 1 week ago

Had an offline discussion with @warunalakshitha and @HindujaB.

There is an already available method io.ballerina.runtime.api.Runtime.invokeMethodAsync which allows for taking in a method name and parameters to be executed. However, that cannot be directly used for running tools written in Ballerina since the built jar is not in the current class loader.

We need to update the above method with the ability to pass a URLClassLoader. That way we can build the Ballerina tool package, add it to a URLClassLoader and pass to invokeMethodAsync to be executed.

azinneera commented 1 week ago

@warunalakshitha can we have an ETA for the API please?

gayaldassanayake commented 1 week ago

I did a simple demo where a pre-built edi tool jar is added to the class path and the main method is called. Tested the functionality with the edi codegen subcommand. https://github.com/ballerina-platform/ballerina-lang/issues/42729

warunalakshitha commented 4 days ago

Best case it will take 2 weeks to complete. We hope to start work on this next sprint.

gayaldassanayake commented 2 days ago

Tool development design

If the execute() method of the BLauncherCmd entry function is there, compile and run it. Otherwise, we run the the Ballerina execute function provided in the default module of the tool package.

public function execute(string[] args) {
   # logic goes here
}

Help text behavior

Currently, the help text is derived using BLauncherCmd:printLongDesc java method. Similarly, we require the tool developers to have a Ballerina function printLongDesc.

public function printLongDesc() returns string {
   return "This is a Ballerina program to " +
   "generate code and libraries for EDI files.";
}

The short help text was picked from the @CommandLine.Command:description annotation provided by the Picocli library in java. Instead, we introduce a printShortDesc() method.

public function printShortDesc() returns string {
   return "EDI Code Generator";
}

**Note: This is for handling bal help command and the bal help <tool-name> only. The bal <tool-name> --help flag should be handled by the developer accordingly.

Subcommand support

The subcommands can be internally handled by the developers, by switching the program flows based on the subcommand provided in the args array.