Skip to content

HBASE-30419 Add .jsh/.java single-file script dispatch to bin/hbase - #8703

Open
mnpoonia wants to merge 1 commit into
apache:masterfrom
mnpoonia:HBASE-30419
Open

mnpoonia wants to merge 1 commit into
apache:masterfrom
mnpoonia:HBASE-30419

Conversation

@mnpoonia

@mnpoonia mnpoonia commented Sep 25, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • Add bin/hbase dispatch for .jsh (JShellToolProvider) and .java (JEP 330 single-file source launch), mirroring the existing .rb → org.jruby.Main path.
  • Pass positional args to JShell via HBASE_JSH_ARG_N / HBASE_JSH_ARG_COUNT; forward args natively for .java.
  • Shared init_jshell_args for interactive jshell and *.jsh: optional hbase_startup.jsh, default --execution local (honors user --execution / --execution=<spec>).
  • Script mode defaults to -q only when no feedback option is already set in HBASE_JSHELL_ARGS.
  • HBASE_PROC_NAME=jsh|java for -Dproc_*; JAVA_MAIN argv array so empty CLASS and paths with spaces are handled safely.

This is the replacement path for retiring the standalone JRuby scripts under bin/.

JIRA: https://issues.apache.org/jira/browse/HBASE-30419

Test plan

  • bin/hbase path/to/script.jsh arg1 arg2 — System.exit propagates; args readable via HBASE_JSH_ARG_*
  • bin/hbase path/to/Script.java arg1 arg2 — args reach main; path with spaces works
  • HBASE_JSHELL_ARGS='--feedback verbose' bin/hbase script.jsh does not fail with "Only one feedback option"
  • HBASE_JSHELL_ARGS='--execution=jdi:...' bin/hbase script.jsh does not append a second --execution local
  • bin/hbase --help lists script.jsh / Script.java

@mnpoonia

Copy link
Copy Markdown
Contributor Author

@apurtell @NihalJain @virajjasani Can you please help with review.

@apurtell
apurtell requested a balanced review from Copilot September 25, 2026 17:54

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot wasn't able to review any files in this pull request. Check if the Files changed in this pull request are included in default exclusions.


💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@mnpoonia
mnpoonia force-pushed the HBASE-30419 branch 2 times, most recently from f136c1d to d8e0b45 Compare September 25, 2026 18:16
Comment thread bin/hbase Outdated
set --
CLASS='jdk.internal.jshell.tool.JShellToolProvider'
init_jshell_args
JSHELL_ARGS+=(-q "$JSH_SCRIPT")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This unconditionally appends -q regardless of what's in HBASE_JSHELL_ARGS. This will make bin/hbase myscript.jsh fail immediately with exit 1 in many cases (e.g. any --feedback <mode> other than literally -q)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch — confirmed: jshell exits 1 with Only one feedback option (--feedback, -q, -s, or -v) may be used. when -q is appended on top of a user --feedback from HBASE_JSHELL_ARGS.

Fixed in the latest push: script mode only defaults to -q when none of --feedback / -q / -s / -v is already set.

Mirror the existing .rb -> org.jruby.Main path with dispatch for .jsh
(JShellToolProvider) and .java (JEP 330 single-file source launch).

JShell script mode defaults to --execution local so System.exit()
propagates as the process exit code, honors a user-supplied --execution
/ --execution=<spec> from HBASE_JSHELL_ARGS, and passes positional args
via HBASE_JSH_ARG_N / HBASE_JSH_ARG_COUNT. Interactive jshell and *.jsh
share init_jshell_args so defaults cannot drift. Document script.jsh /
Script.java in show_usage and the arg convention in the header,
hbase-env.sh, and hbase_startup.jsh.

Use HBASE_PROC_NAME=jsh|java for -Dproc_* and a JAVA_MAIN argv array so
empty CLASS (JEP 330) does not create a spurious argument and paths with
spaces stay intact. Only default -q for scripts when HBASE_JSHELL_ARGS
does not already set a feedback mode (--feedback / -q / -s / -v).
Comment thread bin/hbase
# unless the user already passed --execution / --execution=<spec>.
init_jshell_args() {
if [ -n "${HBASE_JSHELL_ARGS}" ]; then
read -r -a JSHELL_ARGS <<< "${HBASE_JSHELL_ARGS}"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please either:

  • explicitly document that HBASE_JSHELL_ARGS cannot contain whitespace-bearing arguments, or
  • add a parsing approach that supports values such as a startup file path containing spaces.

Comment thread bin/hbase
echo " clean Run the HBase clean up script"
fi
echo " jshell Run a jshell with HBase on the classpath"
echo " script.jsh Run a JShell script non-interactively (args via HBASE_JSH_ARG_N)"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we move these besides CLASSNAME, at the end? Currently, I am not sure if this help arg is clear; it might seem like hbase script.jsh is in itself a command and not a placeholder.

@NihalJain

NihalJain commented Sep 25, 2026 •

Copy link
Copy Markdown
Contributor

I checked-out out this PR and ran few tests via https://gist.github.com/NihalJain/0d5f0370598b7e730b0106ab8f3f0d0b

Overall this PR LGTM!

@NihalJain ➜ /workspaces/hbase (HBASE-30419) $  ./validate-hbase-8703.sh

==== Repository and prerequisite checks ====
PASS: bin/hbase is executable
PASS: bin/hbase passes bash -n
PASS: bin/hbase-config.sh passes bash -n
PASS: conf/hbase-env.sh passes bash -n
PASS: Java executable is usable
PASS: HBase launcher can execute version
SKIP: ShellCheck not requested; set RUN_SHELLCHECK=1 to enable

==== Help output ====
PASS: bin/hbase --help succeeds
PASS: help lists script.jsh
PASS: help lists Script.java

==== Create test scripts ====
PASS: test scripts created

==== JShell script dispatch ====
PASS: .jsh dispatch succeeds with quoted arguments
PASS: .jsh preserves spaces, empty arguments, and literal glob characters
PASS: .jsh dispatch succeeds with no arguments
PASS: .jsh reports zero positional arguments

==== JShell System.exit propagation ====
PASS: System.exit status propagates from .jsh

==== JShell feedback options ====
PASS: .jsh accepts HBASE_JSHELL_ARGS='--feedback verbose'
PASS: no duplicate JShell feedback option for '--feedback verbose'
PASS: script runs with feedback option '--feedback verbose'
PASS: .jsh accepts HBASE_JSHELL_ARGS='--feedback=verbose'
PASS: no duplicate JShell feedback option for '--feedback=verbose'
PASS: script runs with feedback option '--feedback=verbose'
PASS: .jsh accepts HBASE_JSHELL_ARGS='-s'
PASS: no duplicate JShell feedback option for '-s'
PASS: script runs with feedback option '-s'
PASS: .jsh accepts HBASE_JSHELL_ARGS='-v'
PASS: no duplicate JShell feedback option for '-v'
PASS: script runs with feedback option '-v'

==== JShell execution options ====
PASS: .jsh accepts HBASE_JSHELL_ARGS='--execution local'
PASS: script runs with execution option '--execution local'
PASS: .jsh accepts HBASE_JSHELL_ARGS='--execution=local'
PASS: script runs with execution option '--execution=local'
PASS: debug execution-option invocation succeeds
PASS: debug execution-option invocation runs the script

==== Java single-file dispatch ====
PASS: .java dispatch succeeds with quoted arguments
PASS: .java preserves spaces, empty arguments, and literal glob characters
PASS: .java dispatch handles a path containing spaces
PASS: .java path-with-spaces invocation reaches main

==== Missing-script diagnostics ====
PASS: missing .jsh fails
PASS: missing .java fails
PASS: missing .jsh has a useful diagnostic
PASS: missing .java has a useful diagnostic

==== JShell stdin handling ====
PASS: .jsh terminates with stdin redirected
PASS: .jsh completes without remaining interactive input

==== Interactive JShell regression ====
PASS: interactive jshell starts and exits
PASS: interactive jshell evaluates code

==== Custom JShell startup file ====
PASS: custom JShell startup file is loaded
PASS: custom startup marker is visible to the script

==== Known HBASE_JSHELL_ARGS whitespace behavior ====
SKIP: HBASE_JSHELL_ARGS values containing spaces are not supported by current parsing

==== HBASE_NOEXEC path ====
PASS: HBASE_NOEXEC .java path succeeds
PASS: HBASE_NOEXEC preserves .java arguments
PASS: HBASE_NOEXEC .jsh path succeeds
PASS: HBASE_NOEXEC preserves .jsh execution

==== Optional Maven validation ====
SKIP: Maven validation not requested; set RUN_MAVEN=1 to enable

==== Summary ====

Repository: /workspaces/hbase
Test files: /tmp/hbase-8703-validation.Ze2TV2

Passed:  51
Skipped: 3
Failed:  0

Validation completed successfully.

@NihalJain

Copy link
Copy Markdown
Contributor

On a side note, please refrain from using force push, it destroys commit history and review experience.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Interactive JShell execution options can conflict with the newly appended default.

Get a fresh assessment by requesting another Copilot review.

Review effort: Balanced
Findings: None

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants