js4j 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,75 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ /**
5
+ * Example 01 — Basic usage
6
+ *
7
+ * Shows how to connect to a Java gateway, call methods on the entry point
8
+ * object, and work with primitive types (numbers, strings, booleans, null).
9
+ *
10
+ * Run:
11
+ * node examples/01-basic.js
12
+ */
13
+
14
+ const { startTestGateway } = require('./_gateway');
15
+
16
+ async function main() {
17
+ console.log('Connecting to Java gateway...\n');
18
+ const { gateway, kill } = await startTestGateway();
19
+
20
+ try {
21
+ const ep = gateway.entry_point;
22
+
23
+ // -----------------------------------------------------------------------
24
+ // Arithmetic
25
+ // -----------------------------------------------------------------------
26
+ console.log('--- Arithmetic ---');
27
+ console.log('add(3, 4) =', await ep.add(3, 4)); // 7
28
+ console.log('multiply(6, 7) =', await ep.multiply(6, 7)); // 42
29
+ console.log('divide(5.5, 2.2) =', await ep.divide(5.5, 2.2)); // 2.5
30
+ console.log('addDoubles(1.1, 2.2) =', await ep.addDoubles(1.1, 2.2)); // 3.3
31
+ console.log('addLongs(2^32, 1) =', await ep.addLongs(4294967296, 1)); // 4294967297
32
+
33
+ // -----------------------------------------------------------------------
34
+ // Strings
35
+ // -----------------------------------------------------------------------
36
+ console.log('\n--- Strings ---');
37
+ console.log(await ep.greet('World')); // Hello, World!
38
+ console.log(await ep.concatenate('foo', 'bar')); // foobar
39
+ console.log('length("hello") =', await ep.stringLength('hello')); // 5
40
+ console.log(await ep.toUpperCase('js4j')); // JS4J
41
+ console.log('containsSubstring =', await ep.containsSubstring('hello world', 'world')); // true
42
+ console.log(await ep.repeatString('ab', 3)); // ababab
43
+
44
+ // -----------------------------------------------------------------------
45
+ // Booleans
46
+ // -----------------------------------------------------------------------
47
+ console.log('\n--- Booleans ---');
48
+ console.log('true && false =', await ep.andBool(true, false)); // false
49
+ console.log('true || false =', await ep.orBool(true, false)); // true
50
+ console.log('!true =', await ep.notBool(true)); // false
51
+
52
+ // -----------------------------------------------------------------------
53
+ // Null handling
54
+ // -----------------------------------------------------------------------
55
+ console.log('\n--- Null ---');
56
+ console.log('maybeNull(false) =', await ep.maybeNull(false)); // "not null"
57
+ console.log('maybeNull(true) =', await ep.maybeNull(true)); // null
58
+ console.log('isNull(null) =', await ep.isNull(null)); // true
59
+
60
+ // -----------------------------------------------------------------------
61
+ // Type round-trips
62
+ // -----------------------------------------------------------------------
63
+ console.log('\n--- Type round-trips ---');
64
+ console.log('echoInt(42) =', await ep.echoInt(42));
65
+ console.log('echoDouble(3.14) =', await ep.echoDouble(3.14));
66
+ console.log('echoBool(true) =', await ep.echoBool(true));
67
+ console.log('echoString("hi") =', await ep.echoString('hi'));
68
+
69
+ } finally {
70
+ await kill();
71
+ console.log('\nGateway shut down.');
72
+ }
73
+ }
74
+
75
+ main().catch((err) => { console.error(err.message); process.exit(1); });
@@ -0,0 +1,108 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ /**
5
+ * Example 02 — Java collections
6
+ *
7
+ * Demonstrates JavaList, JavaSet, JavaMap, and JavaArray — the wrappers
8
+ * js4j creates automatically when Java methods return collection types.
9
+ *
10
+ * Run:
11
+ * node examples/02-collections.js
12
+ */
13
+
14
+ const { startTestGateway } = require('./_gateway');
15
+
16
+ async function main() {
17
+ console.log('Connecting to Java gateway...\n');
18
+ const { gateway, kill } = await startTestGateway();
19
+
20
+ try {
21
+ const ep = gateway.entry_point;
22
+
23
+ // -----------------------------------------------------------------------
24
+ // JavaList
25
+ // -----------------------------------------------------------------------
26
+ console.log('--- JavaList ---');
27
+ const list = await ep.getStringList(); // returns ArrayList<String>
28
+
29
+ console.log('size() =', await list.size()); // 3
30
+ console.log('get(0) =', await list.get(0)); // alpha
31
+ console.log('get(2) =', await list.get(2)); // gamma
32
+ console.log('contains("beta")=', await list.contains('beta')); // true
33
+ console.log('indexOf("gamma")=', await list.indexOf('gamma')); // 2
34
+
35
+ // Mutation
36
+ await list.add('delta');
37
+ console.log('after add("delta"), size =', await list.size()); // 4
38
+
39
+ // Convert to a plain JS array
40
+ const arr = await list.toArray();
41
+ console.log('toArray() =', arr); // ['alpha','beta','gamma','delta']
42
+
43
+ // Iteration with for-await
44
+ process.stdout.write('for-await: ');
45
+ for await (const item of list) process.stdout.write(item + ' ');
46
+ console.log();
47
+
48
+ // -----------------------------------------------------------------------
49
+ // JavaSet
50
+ // -----------------------------------------------------------------------
51
+ console.log('\n--- JavaSet ---');
52
+ const set = await ep.getStringSet(); // returns LinkedHashSet<String>
53
+
54
+ console.log('size() =', await set.size()); // 3
55
+ console.log('contains("one") =', await set.contains('one')); // true
56
+ console.log('contains("four")=', await set.contains('four')); // false
57
+
58
+ await set.add('four');
59
+ console.log('after add("four"), size =', await set.size()); // 4
60
+
61
+ const nativeSet = await set.toSet(); // JS Set
62
+ console.log('toSet() =', nativeSet);
63
+
64
+ // -----------------------------------------------------------------------
65
+ // JavaMap
66
+ // -----------------------------------------------------------------------
67
+ console.log('\n--- JavaMap ---');
68
+ const map = await ep.getStringIntMap(); // returns LinkedHashMap<String,Integer>
69
+
70
+ console.log('size() =', await map.size()); // 3
71
+ console.log('get("a") =', await map.get('a')); // 1
72
+ console.log('get("z") =', await map.get('z')); // null
73
+ console.log('containsKey("b")=', await map.containsKey('b')); // true
74
+
75
+ await map.put('d', 4);
76
+ console.log('after put("d",4), size =', await map.size()); // 4
77
+
78
+ // Convert to a plain JS object
79
+ const obj = await map.toObject();
80
+ console.log('toObject() =', obj); // { a:1, b:2, c:3, d:4 }
81
+
82
+ // -----------------------------------------------------------------------
83
+ // JavaArray
84
+ // -----------------------------------------------------------------------
85
+ console.log('\n--- JavaArray ---');
86
+ const intArr = await ep.getIntArray(); // int[]{10,20,30,40,50}
87
+
88
+ console.log('length() =', await intArr.length()); // 5
89
+ console.log('get(0) =', await intArr.get(0)); // 10
90
+ console.log('get(4) =', await intArr.get(4)); // 50
91
+
92
+ // Convert all elements to a JS array
93
+ console.log('toArray() =', await intArr.toArray()); // [10,20,30,40,50]
94
+
95
+ // Create a new Java array from the JS side
96
+ const newArr = await gateway.newArray(gateway.jvm.java.lang.Integer, 3);
97
+ await newArr.set(0, 100);
98
+ await newArr.set(1, 200);
99
+ await newArr.set(2, 300);
100
+ console.log('newArray result =', await newArr.toArray()); // [100,200,300]
101
+
102
+ } finally {
103
+ await kill();
104
+ console.log('\nGateway shut down.');
105
+ }
106
+ }
107
+
108
+ main().catch((err) => { console.error(err.message); process.exit(1); });
@@ -0,0 +1,99 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ /**
5
+ * Example 03 — Java objects
6
+ *
7
+ * Shows how to work with Java objects returned from the gateway:
8
+ * - Calling methods on entry-point-created objects (Counter)
9
+ * - Creating Java standard-library objects from the JS side (StringBuilder)
10
+ * - Reading and writing fields via gateway.getField / gateway.setField
11
+ * - Introspection: getMethods, getFields, getStaticMembers, help
12
+ *
13
+ * Run:
14
+ * node examples/03-objects.js
15
+ */
16
+
17
+ const { startTestGateway } = require('./_gateway');
18
+
19
+ async function main() {
20
+ console.log('Connecting to Java gateway...\n');
21
+ const { gateway, kill } = await startTestGateway();
22
+
23
+ try {
24
+ const ep = gateway.entry_point;
25
+ const jvm = gateway.jvm;
26
+
27
+ // -----------------------------------------------------------------------
28
+ // Objects returned by the entry point
29
+ // -----------------------------------------------------------------------
30
+ console.log('--- Counter object ---');
31
+ const counter = await ep.createCounter(10);
32
+
33
+ console.log('getValue() =', await counter.getValue()); // 10
34
+ await counter.increment();
35
+ await counter.increment();
36
+ console.log('after 2x increment:', await counter.getValue()); // 12
37
+ await counter.add(8);
38
+ console.log('after add(8) =', await counter.getValue()); // 20
39
+ await counter.decrement();
40
+ console.log('after decrement =', await counter.getValue()); // 19
41
+ await counter.reset();
42
+ console.log('after reset =', await counter.getValue()); // 0
43
+
44
+ console.log('toString() =', await counter.toString()); // Counter(0)
45
+
46
+ // -----------------------------------------------------------------------
47
+ // Creating Java objects from the JS side via gateway.jvm
48
+ // -----------------------------------------------------------------------
49
+ console.log('\n--- StringBuilder (created from JS) ---');
50
+ const sb = await jvm.java.lang.StringBuilder('Hello');
51
+ await sb.append(', ');
52
+ await sb.append('World');
53
+ await sb.append('!');
54
+ console.log('toString() =', await sb.toString()); // Hello, World!
55
+ console.log('length() =', await sb.length()); // 13
56
+
57
+ // -----------------------------------------------------------------------
58
+ // Static methods via the jvm namespace
59
+ // -----------------------------------------------------------------------
60
+ console.log('\n--- Static methods ---');
61
+ const absVal = await jvm.java.lang.Math.abs(-42);
62
+ console.log('Math.abs(-42) =', absVal); // 42
63
+
64
+ const maxVal = await jvm.java.lang.Math.max(17, 99);
65
+ console.log('Math.max(17,99) =', maxVal); // 99
66
+
67
+ const sqrtVal = await jvm.java.lang.Math.sqrt(12.25);
68
+ console.log('Math.sqrt(12.25) =', sqrtVal); // 3.5
69
+
70
+ const parsed = await jvm.java.lang.Integer.parseInt('255');
71
+ console.log('Integer.parseInt("255") =', parsed); // 255
72
+
73
+ // -----------------------------------------------------------------------
74
+ // Static fields via gateway.getField
75
+ // -----------------------------------------------------------------------
76
+ console.log('\n--- Static fields ---');
77
+ const pi = await gateway.getField(jvm.java.lang.Math, 'PI');
78
+ const maxInt = await gateway.getField(jvm.java.lang.Integer, 'MAX_VALUE');
79
+ console.log('Math.PI =', pi); // 3.141592...
80
+ console.log('Integer.MAX_VALUE =', maxInt); // 2147483647
81
+
82
+ // -----------------------------------------------------------------------
83
+ // Introspection
84
+ // -----------------------------------------------------------------------
85
+ console.log('\n--- Introspection ---');
86
+ const methods = await gateway.getMethods(counter);
87
+ console.log('Counter methods:', methods.sort().join(', '));
88
+
89
+ const staticMembers = await gateway.getStaticMembers(jvm.java.lang.Math);
90
+ const mathStatics = staticMembers.filter(m => ['abs', 'max', 'min', 'sqrt', 'PI', 'E'].includes(m));
91
+ console.log('Math static members (subset):', mathStatics.sort().join(', '));
92
+
93
+ } finally {
94
+ await kill();
95
+ console.log('\nGateway shut down.');
96
+ }
97
+ }
98
+
99
+ main().catch((err) => { console.error(err.message); process.exit(1); });
@@ -0,0 +1,97 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ /**
5
+ * Example 04 — Callbacks (Java → JS)
6
+ *
7
+ * Demonstrates passing JavaScript objects to Java as interface implementations.
8
+ * Java calls back into Node.js over a separate TCP connection handled by the
9
+ * CallbackServer.
10
+ *
11
+ * Run:
12
+ * node examples/04-callbacks.js
13
+ */
14
+
15
+ const { startTestGateway } = require('./_gateway');
16
+ const { createJavaProxy } = require('../src/callbackServer');
17
+ const { ClientServer } = require('../src/clientServer');
18
+ const { GatewayParameters, CallbackServerParameters } = require('../src/gateway');
19
+
20
+ async function main() {
21
+ console.log('Connecting to Java gateway (with callback server)...\n');
22
+ const { process: jvmProcess, kill: killProcess } = await startTestGateway();
23
+
24
+ const cs = new ClientServer(
25
+ new GatewayParameters({ port: 25333 }),
26
+ new CallbackServerParameters({ port: 25334 })
27
+ );
28
+ await cs.connect();
29
+
30
+ try {
31
+ const jvm = cs.jvm;
32
+
33
+ // -----------------------------------------------------------------------
34
+ // Runnable — Java calls run() on the JS object
35
+ // -----------------------------------------------------------------------
36
+ console.log('--- Runnable callback ---');
37
+
38
+ let runCount = 0;
39
+ const runnable = createJavaProxy(['java.lang.Runnable'], {
40
+ run() {
41
+ runCount++;
42
+ console.log(` run() called! (invocation #${runCount})`);
43
+ return null;
44
+ },
45
+ });
46
+
47
+ const thread = await jvm.java.lang.Thread(runnable);
48
+ await thread.start();
49
+ await thread.join();
50
+
51
+ console.log(`Runnable was invoked ${runCount} time(s)`);
52
+
53
+ // -----------------------------------------------------------------------
54
+ // Comparator — Java calls compare(a, b) to sort a list
55
+ // -----------------------------------------------------------------------
56
+ console.log('\n--- Comparator callback (sort by string length) ---');
57
+
58
+ const byLength = createJavaProxy(['java.util.Comparator'], {
59
+ compare(a, b) {
60
+ return String(a).length - String(b).length;
61
+ },
62
+ });
63
+
64
+ const words = await jvm.java.util.ArrayList();
65
+ await words.add('banana'); await words.add('fig'); await words.add('apple');
66
+ await words.add('kiwi'); await words.add('date');
67
+ await jvm.java.util.Collections.sort(words, byLength);
68
+
69
+ const sorted = await words.toArray();
70
+ console.log('Sorted by length:', sorted);
71
+
72
+ // -----------------------------------------------------------------------
73
+ // Callable — returns a value back to Java
74
+ // -----------------------------------------------------------------------
75
+ console.log('\n--- Callable callback (returns a value) ---');
76
+
77
+ const callable = createJavaProxy(['java.util.concurrent.Callable'], {
78
+ call() {
79
+ const value = 'computed by JavaScript at ' + new Date().toISOString();
80
+ console.log(' call() invoked, returning:', value);
81
+ return value;
82
+ },
83
+ });
84
+
85
+ const future = await jvm.java.util.concurrent.FutureTask(callable);
86
+ await future.run();
87
+ const result = await future.get();
88
+ console.log('FutureTask result:', result);
89
+
90
+ } finally {
91
+ await cs.shutdown();
92
+ killProcess();
93
+ console.log('\nGateway shut down.');
94
+ }
95
+ }
96
+
97
+ main().catch((err) => { console.error(err.message); process.exit(1); });
@@ -0,0 +1,123 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ /**
5
+ * Example 05 — Java standard library
6
+ *
7
+ * Demonstrates direct access to Java standard-library classes via the
8
+ * gateway.jvm namespace — no custom Java code required.
9
+ *
10
+ * Topics covered:
11
+ * - java.lang (String, Math, System, Integer, StringBuilder)
12
+ * - java.util (ArrayList, HashMap, TreeMap, Collections, UUID, Date)
13
+ * - java.time (LocalDate, LocalDateTime, Duration) [Java 8+]
14
+ * - javaImport shortcut
15
+ *
16
+ * Run:
17
+ * node examples/05-stdlib.js
18
+ */
19
+
20
+ const { startTestGateway } = require('./_gateway');
21
+
22
+ async function main() {
23
+ console.log('Connecting to Java gateway...\n');
24
+ const { gateway, kill } = await startTestGateway();
25
+
26
+ try {
27
+ const jvm = gateway.jvm;
28
+
29
+ // -----------------------------------------------------------------------
30
+ // java.lang
31
+ // -----------------------------------------------------------------------
32
+ console.log('--- java.lang ---');
33
+
34
+ const sb = await jvm.java.lang.StringBuilder();
35
+ await sb.append('js4j');
36
+ await sb.append(' + ');
37
+ await sb.append('Java');
38
+ console.log('StringBuilder:', await sb.toString());
39
+
40
+ const strVal = await jvm.java.lang.String.valueOf(42);
41
+ console.log('String.valueOf(42): ', strVal);
42
+
43
+ console.log('Math.PI: ', await gateway.getField(jvm.java.lang.Math, 'PI'));
44
+ console.log('Math.exp(1.5):', await jvm.java.lang.Math.exp(1.5));
45
+ console.log('Math.floor(3.9):', await jvm.java.lang.Math.floor(3.9));
46
+ console.log('Math.log(Math.E):', await jvm.java.lang.Math.log(
47
+ await gateway.getField(jvm.java.lang.Math, 'E')
48
+ ));
49
+
50
+ const ms = await jvm.java.lang.System.currentTimeMillis();
51
+ console.log('System.currentTimeMillis:', ms);
52
+
53
+ console.log('Integer.MAX_VALUE:', await gateway.getField(jvm.java.lang.Integer, 'MAX_VALUE'));
54
+ console.log('Integer.toBinaryString(255):', await jvm.java.lang.Integer.toBinaryString(255));
55
+ console.log('Integer.toHexString(255):', await jvm.java.lang.Integer.toHexString(255));
56
+
57
+ // -----------------------------------------------------------------------
58
+ // java.util
59
+ // -----------------------------------------------------------------------
60
+ console.log('\n--- java.util ---');
61
+
62
+ const list = await jvm.java.util.ArrayList();
63
+ await list.add('cherry');
64
+ await list.add('apple');
65
+ await list.add('banana');
66
+ await jvm.java.util.Collections.sort(list);
67
+ console.log('Sorted ArrayList:', await list.toArray());
68
+
69
+ const map = await jvm.java.util.HashMap();
70
+ await map.put('x', 10);
71
+ await map.put('y', 20);
72
+ await map.put('z', 30);
73
+ console.log('HashMap size: ', await map.size());
74
+ console.log('HashMap get x: ', await map.get('x'));
75
+
76
+ const tree = await jvm.java.util.TreeMap(map);
77
+ const keys = await tree.keySet();
78
+ console.log('TreeMap keys: ', await keys.toArray());
79
+
80
+ const uuid = await jvm.java.util.UUID.randomUUID();
81
+ const uuidStr = await uuid.toString();
82
+ console.log('UUID: ', uuidStr);
83
+ console.log('UUID version: ', await uuid.version());
84
+
85
+ const nums = await jvm.java.util.ArrayList();
86
+ await nums.add(5); await nums.add(3); await nums.add(9); await nums.add(1); await nums.add(7);
87
+ console.log('max of [5,3,9,1,7]:', await jvm.java.util.Collections.max(nums));
88
+ console.log('min of [5,3,9,1,7]:', await jvm.java.util.Collections.min(nums));
89
+
90
+ // -----------------------------------------------------------------------
91
+ // java.time (Java 8+)
92
+ // -----------------------------------------------------------------------
93
+ console.log('\n--- java.time ---');
94
+
95
+ const today = await jvm.java.time.LocalDate.now();
96
+ console.log('LocalDate.now():', await today.toString());
97
+
98
+ const fixed = await jvm.java.time.LocalDate.of(2000, 1, 1);
99
+ console.log('Year 2000: ', await fixed.toString());
100
+
101
+ const duration = await jvm.java.time.Duration.ofHours(3);
102
+ console.log('Duration (3h): ', await duration.toString());
103
+ console.log('In minutes: ', await duration.toMinutes());
104
+
105
+ // -----------------------------------------------------------------------
106
+ // javaImport — shortcut access
107
+ // -----------------------------------------------------------------------
108
+ console.log('\n--- javaImport shortcut ---');
109
+
110
+ await gateway.javaImport('java.util.LinkedList');
111
+ const linked = await jvm.LinkedList();
112
+ await linked.add('first');
113
+ await linked.add('second');
114
+ await linked.addFirst('zeroth');
115
+ console.log('LinkedList:', await linked.toArray());
116
+
117
+ } finally {
118
+ await kill();
119
+ console.log('\nGateway shut down.');
120
+ }
121
+ }
122
+
123
+ main().catch((err) => { console.error(err.message); process.exit(1); });
@@ -0,0 +1,78 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * Shared helper used by all examples.
5
+ *
6
+ * Locates the py4j JAR, compiles TestEntryPoint.java if needed,
7
+ * then launches the gateway and returns { gateway, kill }.
8
+ *
9
+ * Set PY4J_JAR=/path/to/py4j.jar if auto-detection fails.
10
+ */
11
+
12
+ const { execSync } = require('child_process');
13
+ const fs = require('fs');
14
+ const path = require('path');
15
+ const { launchGateway } = require('../src/launcher');
16
+
17
+ const ROOT = path.resolve(__dirname, '..');
18
+ const JAVA_DIR = path.join(ROOT, 'java');
19
+ const BUILD_DIR = path.join(JAVA_DIR, 'build');
20
+
21
+ function findPy4jJar() {
22
+ if (process.env.PY4J_JAR) return process.env.PY4J_JAR;
23
+
24
+ // Common system install locations
25
+ const fixed = [
26
+ '/usr/share/py4j/py4j.jar',
27
+ '/usr/local/share/py4j/py4j.jar',
28
+ ];
29
+ for (const p of fixed) {
30
+ if (fs.existsSync(p)) return p;
31
+ }
32
+
33
+ // pip install py4j puts the JAR next to the Python package
34
+ try {
35
+ const site = execSync(
36
+ 'python3 -c "import py4j, os; print(os.path.dirname(py4j.__file__))"',
37
+ { encoding: 'utf8', stdio: ['pipe', 'pipe', 'pipe'] }
38
+ ).trim();
39
+ const libDir = path.join(site, 'java', 'lib');
40
+ if (fs.existsSync(libDir)) {
41
+ const jar = fs.readdirSync(libDir).find(f => f.endsWith('.jar'));
42
+ if (jar) return path.join(libDir, jar);
43
+ }
44
+ } catch (_) {}
45
+
46
+ return null;
47
+ }
48
+
49
+ function buildIfNeeded(jar) {
50
+ const cls = path.join(BUILD_DIR, 'TestEntryPoint.class');
51
+ if (fs.existsSync(cls)) return; // already built
52
+
53
+ console.log('Compiling TestEntryPoint.java...');
54
+ fs.mkdirSync(BUILD_DIR, { recursive: true });
55
+ execSync(
56
+ `javac -cp "${jar}" -d "${BUILD_DIR}" "${path.join(JAVA_DIR, 'TestEntryPoint.java')}"`,
57
+ { stdio: 'inherit' }
58
+ );
59
+ console.log('Compiled.\n');
60
+ }
61
+
62
+ async function startTestGateway() {
63
+ const jar = findPy4jJar();
64
+ if (!jar) {
65
+ throw new Error(
66
+ 'py4j JAR not found. Install py4j (pip install py4j) or set PY4J_JAR=/path/to/py4j.jar'
67
+ );
68
+ }
69
+
70
+ buildIfNeeded(jar);
71
+
72
+ return launchGateway({
73
+ classpath: `${BUILD_DIR}${path.delimiter}${jar}`,
74
+ mainClass: 'TestEntryPoint',
75
+ });
76
+ }
77
+
78
+ module.exports = { startTestGateway };