Bashj programming guide
This is a complement to the general bashj presentation page.
Understanding the architecture of bashj
The key idea behind bashj is the execution of a bashj server. It is a JVM instance performing essentially two tasks
- translate bashj code into bash code
- execute any java method call for any running bashj client
The benefit of this is the extreme efficiency of this minimal architecture, taking advantage of combined strengths of java & bash.
The following slide explains the global flows of bashj
But the developper of a bashj script should be aware of the fact that any global component of the JVM (static variables, Threads,...) will be shared with all other bashj clients launched.
For instance if a client modifies a static variable during the execution of a bashj script, the next execution of the same script will start with the modified value of that variable. This may be convenient ... or not, depending on siuations.
Similarly, if a bashj client launches a Thread without closing it, this Thread will survive in the server JVM (which may not be the intention).
Composition of a bashj script file
A bashj script contains typically 3 components
- the header
- the java section
- the bash section
Header
The shebang header is a mandatory line
Java section
The java section is optional. Without this part, the script behaves exactly as a bash script file with the same content.
The java section starts with a line
and it ends with one of the lines
Bash section
The bash section is also optional.
If absent, the execution becomes a pure java 'interpreter' (see below).
If present, it includes standard bash lines, with the possible presence of java calls.
The java call translation is enabled with the directive
and disabled with the directive
The java calls are detected by the source processor thread when the translation is enabled. They are coded:
For instance
The result of such calls may be used to produce bash shell values, and for instance:
It is recommended not to use complex bash expressions as arguments to java method calls.
Java static fields are detected like java methods, like
Knowing how the detection / substitution works, it is the developer responsibility to avoid in the bash section unintended detectable expressions. The source processor is unable to handle and avoid all complex bash constructions. For instance this bash line
is strange but valid with bash, but it is likely to raise unwanted results with bashj...
Concurrency issues
[version 0.992 ] Concurrent execution of multiple bashj scripts will raise problems if some of the called methods are blocking. This happens for sleeping Threads, for UI blocking dialogs, and possibly for any method waiting for delayed results. The server processes all calls sequentially [ improvement expected ].
2 simple workarounds for this
- organize and use only methods providing rapid answers; or
- avoid concurrent executions of bashj scripts
Useful coding rules
String arguments : String arguments should always be double quoted. The correct way to use String arguments is:
Boolean returned values. Bash and java have very different concepts related to booleans. To test return values of boolean java calls, use this:
Special characters. It is not allowed to use these two characters ® © in bashj sources.
Multiple call of a method. It is not allowed to call mote than once in a bash line a given java method. Use multiple lines for multiple calls to the same method.
Embedded calls. It is not possible to embed bashj java method calls ( Math.log(Math.sin($X)) will not work).
Using bashj as a pure java 'interpreter'
It is possible to create a bashj page without any bash line. In this case, the interpreter will automatically call and execute the method static void main(String... a) , as in this example:
#!java
{u.p("Hello world, welcome to bashj");}
This minimal but complete code will execute as expected.
Convenience u methods
Various convenience methods are include with bashj. It is recommended to cheks their list using the command
or their javadoc.
Swinging bash
As any other java package, it is possible to take advantage of Swing UI components, and this provides (through bashj) a windowing interface to bash.
Here is a minimal example:
#!java
import javax.swing.JFrame;
import javax.swing.JOptionPane;
{JOptionPane.showMessageDialog(new JFrame(),"Welcome to bashj swing UI");}
The same swing tasks may be achieved using convenient u methods:
MSG="Welcome to bashj swing UI"
u.swingInfo("$TITLE","$MSG")
ERMSG="There is a problem!"
u.swingError("$TITLE","$ERMSG")
QUESTION="Do you confirm ?"
CON=u.swingConfirm("$TITLE","$QUESTION")
Inter process communication using bashj
Given the persistence features of the bashj server, it is easy to set up fast IPC between bashj scripts.
The following u methods allow to set() and get() inter process variables:
public static String get(String key,boolean scriptSpecific,boolean persist)
public static String get(String key)
The scriptSpecific flag indicates whether this value is shared or not with other scripts. These values will be kept during successive calls of the calling scripts, until the server is stopped.
The persist flag indicates whether the values should persist in the host file system. These values will be saved when the server is stopped.
The simple calls (without boolean parameters) assume scriptSpecific is true, persist is false.