Releases: MarkusJx/node-java-bridge
Release v2.7.0
What's Changed
Full Changelog: v2.6.0...v2.7.0
Release v2.6.0
Major changes
Errors thrown by the java process are now returned to the node process
Added a new property to each error, called cause
which will contain the throwable from the Java process (if present):
import type { JavaError } from 'java-bridge';
try {
// Call a method that throws an error
someInstance.someMethodSync();
} catch (e: unknown) {
const throwable = (e as JavaError).cause;
throwable?.printStackTraceSync();
}
Added a config option called asyncJavaExceptionObjects
to control whether the Java throwable should be returned from async contexts. This is required as enabling this option will cause the JavaScript stack trace to be lost. This option is disabled by default.
import { importClass, JavaError } from 'java-bridge';
const SomeClass = importClass('path.to.SomeClass', {
asyncJavaExceptionObjects: true,
});
try {
await SomeClass.someMethod();
} catch (e: unknown) {
const throwable = (e as JavaError).cause;
throwable?.printStackTraceSync();
}
What's Changed
- feat(bridge): return java throwable to node process by @MarkusJx in #104
- test(bridge): test import and method not found errors by @MarkusJx in #105
Full Changelog: v2.5.2...v2.6.0
Release v2.5.2
Major changes
Added an option to manually release objects
import { importClass, deleteObject } from 'java-bridge';
const JString = importClass('java.lang.String');
const string = new JString('Hello World');
// Release the string, allowing the java process to garbage collect it
deleteObject(string);
What's Changed
- fix(bridge): local references not being deleted by @MarkusJx in #99
- fix(bridge): proxy memory not being freed by @MarkusJx in #100
- docs: fix title by @MarkusJx in #101
Full Changelog: v2.5.1...v2.5.2
Release v2.5.1
Release v2.5.0
NOTE: This version is broken, please use v2.5.1
instead.
What's Changed
- refactor(deps): remove glob as a dependency by @MarkusJx in #87
- ci: cancel tests if a new commit has been pushed by @MarkusJx in #90
- fix(bridge): add a toString method to all objects by @MarkusJx in #89
- ci(build): create build-alpine docker image by @MarkusJx in #95
- feat(bridge): add support for musl libc by @MarkusJx in #94
- docs: add note about proxy garbage collection by @MarkusJx in #96
Full Changelog: v2.4.0...v2.5.0
Release v2.4.0
Major changes
Improved object to string conversion
Previously, when a java object was converted to a string using an implicit conversion,
the toString
method of the java object wasn't used. Instead, the js object representation
was returned as a string.
In order to improve this behaviour, the toString
method now returns a string
instead
of a Promise<string>
, a toStringAsync
method returning a Promise<string>
was added
and the toStringSync
method has been deprecated.
Now, the toString
method of the java object is properly utilized in order to convert an object
to a string:
import { importClass } from 'java-bridge';
const ArrayList = importClass('java.util.ArrayList');
const list = new ArrayList();
list.addSync('Hello');
list.addSync('World');
// Convert the list to a string (implicit conversion)
const str = list + ''; // [Hello, World]
Improved the conversion of objects to a string inside console.log
This improved conversion also applies to objects passed into console.log
,
when the customInspect
config setting is set to true:
import { importClass, config } from 'java-bridge';
config.customInspect = true;
const ArrayList = importClass('java.util.ArrayList');
const list = new ArrayList();
list.addSync('Hello');
list.addSync('World');
console.log(list); // [Hello, World]
Added more config options
A few rules around the configuration of the module have changed:
- The configuration is now bound to a java class proxy. This means,
the config cannot be for a specific class, once this class has been imported
explicitly or implicitly (as a dependency of some sorts) usingimportClass
orimportClassAsync
. This means, that the config should be set before importing
a class. If you still want to change the config afterwards, you need to call the
clearClassProxies
method before re-importing a class with an updated config, in order
to apply the config to the newly imported class. - The config may now be reset to its default values using
config.reset()
. - The whole config can now be updated at once using the
config.config
setter.
Added options to set custom sync and async suffixes
Sync and async suffixes may now be set to custom values using the
syncSuffix
and asyncSuffix
config values.
Please note, that these values cannot be equal. If equal values
are set for both values, an error will be thrown inside the specific
setter. These options do not affect standard methods of java classes
like toString
, toStringSync
, toStringAsync
and newInstanceAsync
.
import { importClass, config, clearClassProxies } from 'java-bridge';
// Set the async suffix in order to prevent errors
config.asyncSuffix = 'Async';
// Set the sync suffix to an empty string
config.syncSuffix = '';
// This would do the same
config.syncSuffix = null;
// Clear the class proxy cache
clearClassProxies();
// Import the class
const ArrayList = importClass('java.util.ArrayList');
// Create a new instance
const list = new ArrayList();
// Call the method
list.add('Hello World!');
// Async methods now have the 'Async' suffix
await list.addAsync('Hello World!');
Added an option to importClass
and importClassAsync
in order to override the config
The config for a specific class or class import can be temporarily
overriden by passing a config object to importClass
or importClassAsync
.
This config passed does not apply to any classes transiently imported by this call,
nor does it affect any other imports (even ones of the same class).
import { importClass } from 'java-bridge';
const JavaString = importClass('java.lang.String', {
syncSuffix: 'SyncSuffix',
});
const str = new JavaString('test');
str.containsSyncSuffix('e'); // true
Added support for logging
A special version of the module may be built which includes support for
logging. This requires the module to be built using npm run build:all
.
Refer to the logging section of the readme
for further information on logging.
The settings for logging are located inside the logging
namespace:
import { logging } from 'java-bridge';
logging.initLogger('log4rs.json');
logging.setLogCallbacks(
(out) => console.log(out),
(err) => console.error(err)
);
The full documentation for the module is available through the jsdoc of
the module once it has been built with logging support.
If the current build does not support logging, all methods inside
the logging
namespace will be dummies and print an error message
to stdout
once called (the message will only be printed once per
program execution).
Enhanced stack traces of async method calls
The stack traces returned by errors thrown inside asnyc contexts
now return the full stack trace including the stack trace on
the javascript side. A call like
import { importClass } from 'java-bridge';
const JavaString = importClass('java.lang.String');
await JavaString.newInstanceAsync(null);
will now throw:
Error: java.lang.NullPointerException: Cannot invoke "java.lang.StringBuffer.toString()" because "buffer" is null
at java.base/java.lang.String.<init>(String.java:1446)
at crates\java-rs\src\java\java_env_wrapper.rs:1371
at crates\java-rs\src\java\java_env_wrapper.rs:304
at C:\workspace\test.js:56:13
at Object.<anonymous> (C:\workspace\test.js:57:3)
at Module._compile (node:internal/modules/cjs/loader:1226:14)
at Module._extensions..js (node:internal/modules/cjs/loader:1280:10)
at Module.load (node:internal/modules/cjs/loader:1089:32)
at Module._load (node:internal/modules/cjs/loader:930:12)
at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:81:12)
at node:internal/main/run_main_module:23:47 {
code: 'GenericFailure'
}
What's Changed
- docs: add vc redist info for windows by @MarkusJx in #76
- ci(arm): fix jdk install error by @MarkusJx in #80
- ci: check rust style by @MarkusJx in #79
- refactor: move java-rs package into this repo by @MarkusJx in #82
- fix(toString): allow java object conversions to string by @MarkusJx in #84
- feat(bridge): improve config by @MarkusJx in #85
- feat(bridge): add support for logging by @MarkusJx in #78
- feat(bridge): enhance stack traces of asynchronous method calls by @MarkusJx in #86
Full Changelog: v2.3.0...v2.4.0
Release v2.3.0
Major changes
Moved the typescript definition generator to its own package
In order to reduce the number of dependencies, the typescript definition generator was moved to its own npm package and repository.
In order to install the package, simply run
npm install -g java-ts-definition-generator
The repository can be found here.
What's Changed
- fix(tsDefGen): create methods using the proper
newInstanceAsync
name by @MarkusJx in #67 - feat: allow use of async proxy methods by @sla100 in #68
- refactor: move typescript definition generator to its own package by @MarkusJx in #69
- chore(ci): update workflow dependencies by @MarkusJx in #70
- ci: allow to run asan workflow manually by @MarkusJx in #71
- fix(publish): build packages with lower glibc version by @MarkusJx in #73
- chore(bridge): switch to property with closure by @MarkusJx in #74
New Contributors
Full Changelog: v2.2.3...v2.3.0
Release v2.2.3
Core changes
Allow proxies to be used in a synchronous context (experimental)
Added a new option called java.config.runEventLoopWhenInterfaceProxyIsActive
to enable proxies to be used in a synchronous context.
This is an experimental feature and, in some cases, may cause your program to crash.
java.config.runEventLoopWhenInterfaceProxyIsActive = true;
const proxy = java.newProxy('java.util.function.Function', {
apply: (arg: string): string => arg.toUpperCase();
});
const JavaString = java.importClass('java.lang.String');
const str = new JString('hello');
const res = str.transformSync(proxy);
// prints 'HELLO'
console.log(res);
Allow proxies to be used after they have been garbage collected
Added a new option to newProxy
which allows proxies to stay alive longer than the javascript proxy object they were previously bound to:
const proxy = java.newProxy('java.lang.Runnable', {
run: (): void => {
console.log('Hello World!');
}
}, {
keepAsDaemon: true
});
const TimeUnit = java.importClass('java.util.concurrent.TimeUnit');
const ScheduledThreadPoolExecutor = java.importClass(
'java.util.concurrent.ScheduledThreadPoolExecutor'
);
const executor = new ScheduledThreadPoolExecutor(1);
// 'proxy' will eventually be garbage collected,
// but it will be kept alive due to this option.
executor.scheduleAtFixedRateSync(proxy, 0, 1, TimeUnit.SECONDS);
// Calling proxy.reset won't do anything, in order to destroy a daemon
// proxy, the 'force' argument must be set to true
proxy.reset(true);
// Delete all daemon proxies. This will cause the executor to stop
// due to an exception thrown in the run method since the proxy
// is now invalid
java.clearDaemonProxies();
Auto-generated interface proxy definitions
The typescript definition generator now generates definitions for newProxy
on interfaces:
import { createRunnableProxy } from './java/lang/Runnable';
const proxy = createRunnableProxy({
run() {
console.log('Hello World');
}
});
What's Changed
- fix: avoid deadlock when calling proxy methods synchronously by @MarkusJx in #58
- feat(bridge): allow proxies to be used after they have been garbage collected by @MarkusJx in #60
- feat(tsDefGen): generate interface proxy definitions by @MarkusJx in #59
- feat(ci): add address sanitizer workflow by @MarkusJx in #61
- feat(tests): add test container dockerfile by @MarkusJx in #62
- fix(ci): test container not being pushed by @MarkusJx in #63
Full Changelog: v2.2.2...v2.2.3
Release v2.2.2
What's Changed
- refactor(rewrite): convert null values to option by @MarkusJx in #53
- fix: add fields to objects returned by method calls by @MarkusJx in #54
- refactor: move files to different modules by @MarkusJx in #55
Note: Version 2.2.1
has been skipped due to deployment issues
Full Changelog: v2.2.0...v2.2.2