Load Python class through Jython - java

I'm trying to load a Python class by embedding Jython in my Java application.
The code I have so far is
String pythonRoot = Main.class.getResource("/python").getPath();
PySystemState state = new PySystemState();
PyObject importer = state.getBuiltins().__getitem__(Py.newString("__import__"));
PyObject sysModule = importer.__call__(Py.newString("sys"));
final PyString pythonPath = Py.newString(pythonRoot);
PyList path = (PyList) sysModule.__getattr__("path");
path.add(pythonPath);
PyModule module = (PyModule) importer.__call__(Py.newString("building.blah.again.blah2.Test"));
PyObject klass = module.__getattr__(Py.newString("Address"));
AddressInterface ai = (AddressInterface) klass.__call__().__tojava__(AddressInterface.class);
The class I'm trying to access can be found in
/python/building/blah/again/blah2/Test.py
And the name of the class is
Address
However, this gives me the exception
Exception in thread "main" ImportError: No module named blah2
If I place some file in the directory above, like so
/python/building/blah/again/Test.py
This gives me the exception
Exception in thread "main" ImportError: No module named again
It's as if he is actively refusing to recognize directories that contains files. What can be the problem here and how might I proceed to get around this?

If you added the path of your module to the Python-path, which you did via path.add(pythonPath);, the import-command expects only the name of the module, not the full path, i.e. PyModule module = (PyModule) importer.__call__(Py.newString("Test"));
Further, you should confirm that actually the right path was added by printing the contents of the path-list. Also note that your class-declaration in Test.py must extend the Address-java-interface for toJava to work (I just mention this because this is also a common source of error).
That said, your way of using Jython appears somewhat cumbersome to me. If I were you, I would do this stuff (adding the path, doing the import) in a python-script, run it via org.python.util.PythonInterpreter (http://www.jython.org/javadoc/org/python/util/PythonInterpreter.html) and retrieve the class-PyObject via the eval or get-method.

Related

Failure to load properly Groovy library into Groovy shell executing script

My software used groovy.lang Java package to execute Groovy scripts from a shell, binding the variables in the script to Java objects.
A typical script looks like:
package packagename
// import Java classes
abstract class MyClass extends Script {
def myfunction() {
}
}
in this example, 'myfunction' will be called from the outside.
The scripts (located at the file system) are loaded by the following sequence from Java -
the code returns GroovyShell class instance:
GroovyClassLoader groovyClassLoader = new GroovyClassLoader(...)
File groovyFile = new File(groovyURL.toURI());
Class<?> groovyClass = groovyClassLoader.parseClass(groovyFile);
CompilerConfiguration groovyConfig = new CompilerConfiguration();
groovyConfig.setScriptBaseClass(groovyClass.getName());
return new GroovyShell(groovyClassLoader, new Binding(), groovyConfig);
My design goal is to add a Groovy library that can be shared between scripts
My preference is to implement a class (adding lines into the existing script seems to be a hack).
I made a simple class representing the library code. Right now, it looks like:
package shared
class MySharedLib
{
static def testFunction()
{
return "test";
}
}
To make sure the class it loaded, I added a call to
groovyClassLoader.parseClass(groovyLibraryFile)
before loading the actual script by:
groovyClassLoader.parseClass(groovyFile);
Now, from the script, I can call the library:
shared.MySharedLib.testFunction()
indeed return the string "test".
However, when trying to do the import via:
import shared.MySharedLib
in the script (before class definition) - I always got an error when loading the script:
Exception in thread "main" org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
script754084858.groovy: 14: unable to resolve class shared.MySharedLib
# line 14, column 1.
Tried to modify the classpath, it did not help. I realize something is wrong with my setup.
Will appreciate any tip how to load a Groovy library in the correct way.
Max
Thanks for comments.
I think I understand the cause.
It turns out that at some point, the "script" is being compiled using
GroovyClassLoader classLoader = new GroovyClassLoader(parentClassLoader);
GroovyCodeSource codeSource = new GroovyCodeSource(code, scriptClassName + ".groovy", "/groovy/script");
CompilationUnit cu = new CompilationUnit(classLoader);
cu.addSource(codeSource.getName(), codeSource.getScriptText());
cu.compile(CompilePhase.CLASS_GENERATION.getPhaseNumber());
The compilation fails when reaching the "import" statement, since the library class is not in the classpath, so it's unreachable.
Calling classLoader.addClasspath(path) with the appropriate path solves the issue.
So the problem was related to compilation - not to execution.

How to instantiate org.eclipse.jdt.core.ICompilationUnit or org.eclipse.core.internal.resources.Workspace?

What I am trying to do
I use the Eclipse JDT API to create the AST of some java project and manipulate it, however, my software is not an Eclipse Plug-in but it's supposed to be a stand-alone desktop application.
Right now in order to use a specific method of the API, I need an instance of org.eclipse.jdt.core.ICompilationUnit.
As far as I understood this code snippet would do that:
IWorkspace workspace = ResourcesPlugin.getWorkspace();
IPath path = Path.fromOSString(stringPath);
IFile file = workspace.getRoot().getFileForLocation(path);
ICompilationUnit compilationUnit =(ICompilationUnit)JavaCore.create(file);
The problem is that ResourcesPlugin.getWorkspace() won't work, I guess because my application is not Eclipse Plug-in. The specific Exception that is raised is the following:
Caused by: java.lang.IllegalStateException: Workspace is closed.
at org.eclipse.core.resources.ResourcesPlugin.getWorkspace(ResourcesPlugin.java:432)
What I need
The solution that I would like to implement involves making the folder in which the source code is contained in an Eclipse Workspace (provisionally).
Therefore, I need a way to get an instance of org.eclipse.core.internal.resources.Workspace given the path of the folder in which the source code is contained, basically:
String path = "./folder/with/source/code";
Workspace workspace = pathToWorkspace(path);
N.B. btw if there is a way get an instance of an ICompilationUnit, without the need of a workspace, that also would solve my problem.
What I have tried
What I have tried to do is create an instance of ResourcesPlugin and make it start with the hope that through BundleContext I would be able to specify the path. Unfortunately, org.osgi.framework.BundleContext is an interface which is specified that is not supposed to be implemented by the consumers and I wasn't able to find a concrete class that implements this interface.
ResourcesPlugin plugin = new ResourcesPlugin();
plugin.start(boundleContext);
What is the specific method you need to use?
You could try:
AST ast = AST.newAST(AST.JLS16, false);
CompilationUnit unit = ast.newCompilationUnit();
then add to the unit:
//with package:
PackageDeclaration pd = ast.newPackageDeclaration();
pd.setName(ast.newSimpleName("example"));
unit.setPackage(pd);
//class:
TypeDeclaration type = ast.newTypeDeclaration();
unit.types().add(type);
//and so on..

Why is java_executable_exec_path giving me a legacy "external" runfiles path

Suppose I've got a minimal Scala WORKSPACE file like this:
workspace(name = "scala_example")
git_repository(
name = "io_bazel_rules_scala",
commit = "e9e65ada59823c263352d10c30411f4739d5df25",
remote = "https://github.com/bazelbuild/rules_scala",
)
load("#io_bazel_rules_scala//scala:scala.bzl", "scala_repositories")
scala_repositories()
load("#io_bazel_rules_scala//scala:toolchains.bzl", "scala_register_toolchains")
scala_register_toolchains()
And then a BUILD:
load("#io_bazel_rules_scala//scala:scala.bzl", "scala_binary")
scala_binary(
name = "example-bin",
srcs = glob(["*.scala"]),
main_class = "Example",
)
And an Example.scala:
object Example { def main(args: Array[String]): Unit = println("running") }
I can run bazel run example-bin and everything works just fine. My problem is that this recent rules_scala PR changed the way the Java binary path is set to use the following:
ctx.attr._java_runtime[java_common.JavaRuntimeInfo].java_executable_exec_path
…instead of the previous ctx.executable._java.short_path.
After this change the Java binary path includes an external directory in the path, which seems to be a legacy thing (?). This means that after this change, if I run the following:
bazel run --nolegacy_external_runfiles example-bin
It no longer works:
INFO: Running command line: bazel-bin/example-bin
.../.cache/bazel/_bazel_travis/03e97e9dbbfe483081a6eca2764532e8/execroot/scala_example/bazel-out/k8-fastbuild/bin/example-bin.runfiles/scala_example/example-bin_wrapper.sh: line 4: .../.cache/bazel/_bazel_travis/03e97e9dbbfe483081a6eca2764532e8/execroot/scala_example/bazel-out/k8-fastbuild/bin/example-bin.runfiles/scala_example/external/local_jdk/bin/java: No such file or directory
ERROR: Non-zero return code '127' from command: Process exited with status 127
It also breaks some scripts I have that expect non-external paths.
Why is java_executable_exec_path giving me this external path? Is there some option I can give bazel to convince it not to do this?
Sorry for the slow reply -- it appears that this is because the Scala rules erroneously used java_executable_exec_path whereas they should have used java_executable_runfiles_path.
I sent a pull request to fix it, then I realized that you already did in https://github.com/bazelbuild/rules_scala/commit/4235ef58782ce2ec82981ea70b808397b64fe7df
Since the latter is now available at HEAD with Bazel, I'll remove the ugly if at least.

Unsure about reason behind NoClassDefFoundError

I have built a DLL which I am attempting to wrap Java code with, however I am having some troubles with running my Java program. I wrote a simple test DLL and Java program and am producing the same error, and although there are plenty of resources regarding NoClassDefFoundError online I can't seem to solve mine with any troubleshooting methods.
Here is my D:\Test1.Java file
public class Test1 {
static {
//System.loadLibrary("HeyLand");
System.load("D://HeyLand.dll");
}
public native void displayHeyLand();
public static void main (String[] args) {
Test1 t = new Test1();
t.displayHeyLand();
}
}
After compiling, attempting to run D:\Test1.classresults in the following:
D:\>java Test1.class
Exception in thread "main" java.lang.NoClassDefFoundError: Test1.class
Caused by: java.lang.ClassNotFoundException: Test1.class
at java.net.URLClassLoader.findClass(URLClassLoader.java:434)
at java.lang.ClassLoader.loadClass(ClassLoader.java:660)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:358)
at java.lang.ClassLoader.loadClass(ClassLoader.java:626)
Could not find the main class: Test1.class. Program will exit.
Why I am stumped :
1. I have set my classpath to be D:\, so I believe my class definition would be in the classpath, and I do not see how my compile-time and run-time classpaths could be any different.
2. I don't see how this could have anything to do with static initialization, and I believe the exception would look different.
Perhaps I'm just missing something incredibly simple, I am very newbie with Java.
Any help is greatly appreciated!
The classpath environmental variable is taking precedence over that in the java run command. You need to specify the class location (as well as removing the .class file extension)
java -cp . Test1
Java normal syntax for executing class file is
Java [<options>....} <class-name> [<arguments>....]
For example
java com.package.name.Test1
here how compiler works
1. Compiler search for complete class name
2. Load that class
3. check for main method - in the same class
4. Call main method with passed arguments in command line string.
Now following are the possibilities why your class may not found main method.
1 - forgot to include package name
I am new developer in java but I found when I run application using eclips or intellJ editor it gives different path and package name and execute code as I noticed it on command line edior. So make sure you are including package name
For example:
java com.package.name.Test1 instead of
java Test1
2. File name or pathname rather then class name
As I noticed output file is in different location. That why class file path was different.
java Test1.class
java com/package/name/Test1.class
3. Typo
also I noticed you are using
static {
//System.loadLibrary("HeyLand");
System.load("D://HeyLand.dll");
}
Is this function ? or constructor? If it is function then where is name of the function? You cant write code without any reference in classs

Alloy API resulting in java.lang.UnsatisfiedLinkError

I'm currently using the Alloy Analyzer API to build a program, and getting some peculiar behavior. Specifically, if I open a file and parse it (using CompUtil.parseEverything), then make a new Command and call TranslateAlloyToKodkod.execute_command on the parsed file and newly created command using MiniSat with UNSAT core, it runs fine. However, later in execution, my program parses a second input file (also using CompUtil.parseEverything), gets another world, makes a new command, and then I try to call TranslateAlloyToKodkod.execute_command again, it throws the following error:
ERROR: class edu.mit.csail.sdg.alloy4.ErrorFatal: The required JNI library cannot be found:
java.lang.UnsatisfiedLinkError: no minisatproverx5 in java.library.path
edu.mit.csail.sdg.alloy4compiler.translator.TranslateAlloyToKodkod.execute_command(TranslateAlloyToKodkod.java:390)
Does anyone have any idea why this is thrown the second time, but not the first?
To summarize, I have something similar to the following:
Module someWorld = CompUtil.parseEverything_fromFile(rep, null, "someFile.als");
//For the following, "sig" is a sig in someWorld.getAllReachableSigs();
Command command = sig.not();
A4Options options = new A4Options();
options.solver = A4Options.SatSolver.MiniSatProverJNI;
A4Solution ans =
TranslateAlloyToKodkod.execute_command(rep, someWorld, command, options);
//No thrown error
Module someOtherWorld = CompUtil.parseEverything_fromFile(rep, null, "someOtherFile.als");
//For the following, "sig" is a sig in someOtherWorld.getAllReachableSigs();
Command commandTwo = sig.not();
A4Solution ansTwo =
TranslateAlloyToKodkod.execute_command(rep, someOtherWorld, commandTwo, options);
//Thrown error above. Why?
I tried to reproduce this behavior, but I couldn't. If I don't add MiniSat binaries to the LD_LIBRARY_PATH environment variable, I get the exception you mentioned the very first time I invoke execute_command. After configuring LD_LIBRARY_PATH, the exception doesn't happen.
To configure LD_LIBRARY_PATH:
(1) if using Eclipse, you can right-click on one of your source folders, choose Build Path -> Configure Build Path, then on the "Source" tab make sure that "Native library location" points to a folder in which MiniSat binaries reside.
(2) if running from the shell, just add the path to a folder with MiniSat binaries to LD_LIBRARY_PATH, e.g., something like export LD_LIBRARY_PATH=alloy/extra/x86-linux:$LD_LIBRARY_PATH.
Here is the exact code that I was running, and everything worked
public static void main(String[] args) throws Exception {
A4Reporter rep = new A4Reporter();
A4Options options = new A4Options();
options.solver = A4Options.SatSolver.MiniSatProverJNI;
Module someWorld = CompUtil.parseEverything_fromFile(rep, null, "someFile.als");
Command command = someWorld.getAllCommands().get(0);
A4Solution ans = TranslateAlloyToKodkod.execute_command(rep, someWorld.getAllReachableSigs(), command, options);
System.out.println(ans);
Module someOtherWorld = CompUtil.parseEverything_fromFile(rep, null, "someOtherFile.als");
Command commandTwo = someOtherWorld.getAllCommands().get(0);
A4Solution ansTwo = TranslateAlloyToKodkod.execute_command(rep, someOtherWorld.getAllReachableSigs(), commandTwo, options);
System.out.println(ansTwo);
}
with "someFile.als" being
sig A {}
run { some A } for 4
and "someOtherFile.als"
sig A {}
run { no A } for 4
I use alloy4.2.jar as a library in my eclipse plugin project.
A4Reporter rep = new A4Reporter();
Module world = CompUtil.parseEverything_fromFile(rep, null, "civi.als");
A4Options options = new A4Options();
options.solver = A4Options.SatSolver.SAT4J;
options.skolemDepth = 1;
When I use SAT4J, the default solver, the problem mentioned here will not show up. But another exception comes out. The reason is that my civi.als file need Integer model, which located in alloy4.2.jar under the folder /models/util/. But when I run the application, it tries to find the file util/Integer.als directly. That causes the exception. Is it possible to fix that problem?
Besides, I also tried to put the alloy4.2.jar in eclipse plugin project and run my application as an eclipse application (running my application as a plugin). With the default solver, the application has no problem at all. But when I switch to MiniSatProverJNI, the problem mentioned here comes out (I have set the alloy4.2.jar as classpath).

Categories

Resources