py4j / py4j

Py4J enables Python programs to dynamically access arbitrary Java objects

Home Page:https://www.py4j.org

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Implementing in streamlit with custom java functions -

wyuill opened this issue · comments

Hi,

I'm attempting to call a Java function from a streamlit app deployed on a server (Posit Connect). I've been able to use the built in jvm functions successfully which suggests I am able to connect to and use Java but I am having difficulty using custom functions (addition application used as a demo). I'm reasonable sure the issue is that I'm not specifying the gateway correctly but I'm struggling to figure out the right way to do so.

I have tried (or at least tried to try):

  • creating a new gateway connection vs using the same gateway connection
  • adding the java function to the gateway2.entry_point (i.e. gateway2.entry_point.addition()
  • removing the random number section and only using addition
  • adding auto_field=TRUE based on this example

Any advice would be much appreciated


Code

app.py:

import streamlit as st

st.title("This app explores combining Java and Python")

from py4j.java_gateway import *
port = launch_gateway()
gateway = JavaGateway(gateway_parameters=GatewayParameters(port=port), callback_server_parameters=CallbackServerParameters(port=0))

st.header("Random number from Java utils")
random = gateway.jvm.java.util.Random()
n_rand1 = random.nextInt(10)
n_rand2 = random.nextInt(10)
html_str_rand = f"""<p>Random numbers from Java are {n_rand1} & {n_rand2}</p>"""
st.markdown(html_str_rand, unsafe_allow_html=True)

st.header("Calling custom Java functions")
gateway2 = JavaGateway(gateway_parameters=GatewayParameters(port=port, auto_field=True), callback_server_parameters=CallbackServerParameters(port=0))
addition_app = gateway2.entry_point
value = addition_app.addition(n_rand1, n_rand2)
html_str_sum = f"""<p>Sum of two random numbers is: {value}</p>"""
st.markdown(html_str_sum, unsafe_allow_html=True)

AdditionApplication.java:

import py4j.GatewayServer;

public class AdditionApplication {

  public int addition(int first, int second) {
    return first + second;
  }

  public static void main(String[] args) {
      AdditionApplication app = new AdditionApplication();
      GatewayServer gatewayServer = new GatewayServer(new StackEntryPoint());
      gatewayServer.start();
  }

}

Output

This app explores combining Java and Python
Random number from Java utils
Random numbers from Java are 0 & 8

Calling custom Java functions

Py4JError: An error occurred while calling t.addition. Trace: py4j.Py4JException: Target Object ID does not exist for this gateway :t at py4j.Gateway.invoke(Gateway.java:279) at py4j.commands.AbstractCommand.invokeMethod(AbstractCommand.java:132) at py4j.commands.CallCommand.execute(CallCommand.java:79) at py4j.GatewayConnection.run(GatewayConnection.java:238) at java.base/java.lang.Thread.run(Thread.java:829)
Traceback:
File "/opt/rstudio-connect/mnt/app/python/env/lib/python3.11/site-packages/streamlit/runtime/scriptrunner/script_runner.py", line 552, in _run_script
    exec(code, module.__dict__)
File "/opt/rstudio-connect/mnt/app/app.py", line 22, in <module>
    addition_app = gateway.entry_point.addition()
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/rstudio-connect/mnt/app/python/env/lib/python3.11/site-packages/py4j/java_gateway.py", line 1322, in __call__
    return_value = get_return_value(
                   ^^^^^^^^^^^^^^^^^
File "/opt/rstudio-connect/mnt/app/python/env/lib/python3.11/site-packages/py4j/protocol.py", line 330, in get_return_value
    raise Py4JError(

Details

  • py4j==0.10.9.7
  • Python version: '3.11.2'