Function newProxy

  • Create a new java interface proxy. This allows you to implement java interfaces in javascript.

    Pass an object as the second argument with the names of the methods you want to implement as keys and the implementations as values in order to expose these methods to the java process. Any arguments will be converted to javascript values and return values will be converted to java values.

    When the java process tries to call any method which is not implemented by the proxy, an error will be thrown.

    Examples

    Implement java.lang.Runnable

    import { newProxy, importClass } from 'java-bridge';

    // Define the interface
    const runnable = newProxy('java.lang.Runnable', {
    run: (): void => {
    console.log('Hello World!');
    }
    });

    // Note: You can't do something like this:
    // runnable.run();

    // Pass the proxy to a java method instead:
    const Thread = importClass('java.lang.Thread');
    const thread = new Thread(runnable); // <- Pass the proxy here

    // NOTE: You don't have to call this asynchronously
    // as this call instantly returns.
    thread.startSync();

    Implement java.util.function.Function to transform a string

    const func = newProxy('java.util.function.Function', {
    // Any parameters and return types will be automatically converted
    apply: (str: string): string => {
    return str.toUpperCase();
    }
    });

    // Import the string class
    const JString = java.importClass('java.lang.String');
    const str = new JString('hello');

    // Pass the proxy.
    // NOTE: You must call this method async otherwise your program will hang.
    // See notes for more info.
    const transformed = await str.transform(func);

    assert.assertEquals(transformed, 'HELLO');

    Which is equivalent to the following java code:

    Function<String, String> func = new Function<>() {
    @Override
    public String apply(String str) {
    return str.toUpperCase();
    }
    };

    String str = "hello";
    String transformed = str.transform(func);
    assert.assertEquals(transformed, "HELLO");

    Throwing exceptions

    Any exceptions thrown by the proxy will be converted to java exceptions and then rethrown in the java process. This may cause the exception to again be rethrown in the javascript process.

    const func = newProxy('java.util.function.Function', {
    apply: (str: string): string => {
    throw new Error('Something went wrong');
    }
    });

    const JString = java.importClass('java.lang.String');
    const str = new JString('hello');

    // This will re-throw the above error
    const transformed: never = await str.transform(func);

    Notes

    • Keep this instance in scope to not destroy the interface proxy.
    • Call JavaInterfaceProxy.reset to instantly destroy this instance. Please note that calling JavaInterfaceProxy.reset is not necessary, the proxy instance will be automatically destroyed when it is garbage collected. Calling JavaInterfaceProxy.reset will just speed up the process.
    • If any method is queried by the java process and not implemented in here, an exception will be thrown in the java process.
    • Any errors thrown in the javascript process will be rethrown in the java process.

    Possible deadlock warning

    When calling a java method that uses an interface defined by this, you must call that method using the interface asynchronously as Node.js is single threaded and can't wait for the java method to return while calling the proxy method at the same time.

    If you still want to call everything in a synchronous manner, make sure to enable running the event loop while waiting for a java method to return by setting JavaConfig.runEventLoopWhenInterfaceProxyIsActive to true. This may cause application crashes, so it is strongly recommended to just use async methods.

    Keeping the proxy alive

    If you want to keep the proxy alive, you must keep this instance in scope. If that is not an option for you, you can manually keep the proxy alive by setting the InterfaceProxyOptions.keepAsDaemon option to true.

    const proxy = 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);

    This will keep the proxy alive internally, thus the instance can be moved out of scope. However, this will also keep the JVM alive, so you should only use this if you are sure that you want to keep the JVM alive.

    If you want to destroy the proxy, you must call clearDaemonProxies. This will destroy all proxies which are kept alive by this option. Calling JavaInterfaceProxy.reset will not destroy a proxy kept alive by this option unless the force option is set to true.

    See also

    Type Parameters

    Parameters

    • interfaceName: string

      the name of the java interface to implement

    • methods: T

      the methods to implement.

    • Optional opts: InterfaceProxyOptions

      the options to use

    Returns JavaInterfaceProxy<T>

    a proxy class to pass back to the java process

Generated using TypeDoc