How to distribute a java package including jython code in one jar? - java

I'm developping several java packages that are then distributed as jar files.
Due to some new requirements, I now have to program several new features in jython; these will probably cover quite a bit of code distributed over a lot of separate jython files.
I would like to continue with the distribution of a single jar file per package. I bit of search provided me with two approaches which are unfortunately both not very good:
1) jythonc: I'm using jython 2.5.1, so jythonc is no longer part of the distribution. Besides, I don't like the restriction this would place on my jython code.
2) Package everything together with the jython.jar file. Unfortunately, this is not possible; all of the people using my code package already have a jython.jar file in their environment (and many of them use different versions). In other words, my package must be distributed without the python core; instead I can rely on it being found in the classpath at the target system.
Now the question remains, is there another way of packaging all my java and jython code within one jar while keeping the jython.jar file untouched?

I finally found a solution for my problem. Maybe this is also of interest for someone else.
Just as a reminder, this is meant for a mixed java/jython package with java on top that will then be delivered to a customer, NOT for a self-contained application.
1) All jython sources are put in a separate folder on the top level within the jar file using the tool "jar" (or any other zip tool); I used the folder "Lib".
2) Access to the jython code from java is done using an object factory class modeled as a singleton (similar to the one described here); access to java from jython works straightforward with just the full package name.
3) In the constructor of the object factory I use
String jarPath = myObjectFactory.class.getProtectionDomain().getCodeSource().getLocation()
.getPath();
to determine the location of the jar file from within the code.
4) I add the "Lib" folder within the jar file to the jython module lookup path using
PySystemState newState = new PySystemState();
newState.path.insert(0,Py.newString(jarPath + java.io.File.separator + "Lib")); Py.setSystemState(newState);
As long as the jython.jar file is included in the classpath, this will work.

Related

How can I load data files in a Jython module?

I have some Jython modules that I'm trying to make work from within a JAR. Everything is set up fine except that some modules expect to open files from the filesystem that are located in the same directory as the Python script itself. This doesn't work anymore because those files are now bundled into the JAR.
Basically I want to know if there's an equivalent of Class.getResourceAsStream() that I can use from within the Python code to load these data files. I tried to use '__pyclasspath__/path/to/module/data.txt' but it didn't exist.
In java Class.getResourceAsStream() uses java's class loading system to find a resource. Python's class loading mechanism is intended to provide some similar capabilities. Most of it is described here and in PEP 302.
A quick summary of this:
when a python module is loaded, it's loader should set the __loader__ attribute
a loader should support additional methods to get data from the same source
The default zipimporter, which is used when python classes are loaded from zip or jarfiles, luckily supports this methods. So if you know a data file is located in the same jar as a python module, you could use it's loader to load it:
import some_module
data = some_module.__loader__.get_data("path/in/archive/file.txt")
Maybe I'm just missing the point, but can't you use getResourceAsStream() on a Java class?
I had the same problem, however I am not certain my circumstances were exactly the same. I did not see the exception concerning the absence of get_data until I pushed my .jar to the web and tried to WebStart it, (WebStarting locally and starting my jar with java -jar worked fine).
Anyway, this is how I solved my problem:
import SomeClass
url = SomeClass.getClassLoader().findResource('path/to/resource.txt')
inputStream = url.openStream()
# ...
SomeClass is a Java class in my .jar file. It happens to be the Java class that I use to start the Jython interpreter, so I know it will always be there.

Java Game refering to files

I have started getting into game programming.
My question is, that when I am working with files, either parsing data, writing to files, etc. Should I be using relative path names, or absolute pathnames, or something else which is better. I've heard about using jar files, but I am not sure
1. how that works
2. if it is a good way to do it.
So when developing a game that will be cross platform, what is the best method for managing files that the program will need to read from and write to.
there are several ways in which you can ship your code as a product. the most common are
packaging everything in one executable jar file.
having a set of folders where you place all necessary resources.
minecraft, for example, is written in java and distributed as a single executable jar file that contains all necessary class files and resources. to run the game (assuming you have java installed) all you need to do is double-click the jar file.
read this short tutorial about how to add a main class to a jar file.
either way, always treat classes and resources in your code as if they're in your classpath. for example, if you have a my.properties file on the root of the source tree then load it by using 'my.properties'. if you put it under a 'conf' folder then use 'conf/my.properties'.
i think it is the safest way not to get lost.
are you using maven?
The jar file is a zip of all your compiled *.class files and your resources. You can safely load your resources and even default data FROM a jar if you package your program, but you can NOT safely write data back to the jar. This detail is answered in depth already at
How can an app use files inside the JAR for read and write?
For information on how to package a jar see
http://docs.oracle.com/javase/tutorial/deployment/jar/

Matlab Compiler MCC errors on imports for Java classes from dynamic Java classpath

How can I get mcc to recognize imports from user-provided Java libraries, or to simply ignore unresolvable imports?
I have a Matlab codebase that I'm building with the Matlab Compiler, but the build is breaking because mcc is erroring out when it encounters import statements for Java classes that were in JARs on Matlab's dynamic classpath. I am including all the JAR files on the classpath with the mcc -a option. The code works in the IDE, and I think it will work in the deployed app, if it will only allow me to build. (Works under R2009b, which ignores these imports in non-MCOS classes.)
Here's a simple repro. This file is in the same dir as guava-11.0.1.jar from Google Guava.
%file hello_world_with_import.m
function hello_world_with_import
import com.google.common.base.Stopwatch;
disp('Hello, world!');
end
Running it in Matlab works fine. But building it fails. (The javaaddpath here is not strictly necessary in the example, because bad imports by themselves are not an error in plain Matlab. Just showing how it works in practice, and how I wish mcc picked up on it.)
>> javaaddpath('guava-11.0.1.jar');
>> hello_world_with_import()
Hello, world!
>> mcc -m -a guava-11.0.1.jar hello_world_with_import
Error: File: C:\Temp\import_test\hello_world_with_import.m Line: 3 Column: 8
Arguments to IMPORT must either end with ".*"
or else specify a fully qualified class name: "com.google.common.base.Stopwatch" fails this test.
Unable to determine function name or input/output argument count for function
in MATLAB file "hello_world_with_import".
Please use MLINT to determine if this file contains errors.
Error using mcc
Error executing mcc, return status = 1 (0x1).
This is in Matlab R2011b on Windows.
Some background on my environment. My app has about 40 JARs on the dynamic classpath which are a mix of third party libraries and our own Java code. It's deployed to 50+ users on a mix of single-user and multi-user Windows machines. And there are other groups that may be deploying other MCR apps to the same users and machines. On any machine, different MCR apps may be run concurrently by the same or different users. We do weekly releases, and (mostly due to changes in our own Java code) at least one JAR file changes about every other release. I need a mechanism that will work in this environment.
Any suggestions? Anybody know a good way to get mcc to add stuff to its java classpath in the compilation step, or just ignore bogus imports? My fallback plan is to go through the codebase and remove all the imports for Java classes, which is kind of a pain.
UPDATE 12/2/2012: I heard from MathWorks that this is fixed in Matlab R2012b. (But I'm no longer using Matlab so can't personally verify it.)
UPDATE 12/09/2014: I'm using Matlab again (R2014b), and the Matlab Compiler now includes JARs that are on the dynamic classpath in the compiled program's dynamic classpath. It doesn't seem to automatically include the JAR files in the archive, though; you must manually include them using an mcc command line switch, or adding them as "additional included files" in the Matlab Compiler app.
The code executing in the MATLAB IDE works because the guava jar file has been added to the "dynamic" classpath via the javaaddpath method. However, when you use MCC to invoke the MATLAB Compiler, it does not rely on the dynamic java classpath, but the "static" java classpath which is defined in:
$MATLABROOT/toolbox/local/classpath.txt
If you add an entry for your JAR file here, then MCC will be able to resolve the IMPORT line in your M-File.
So to test this, I downloaded the guava jar file and tried the steps above. Works like a charm.
Also, If you read the "Troubleshooting" section for the MATLAB Compiler, this exact situation is documented:
http://www.mathworks.com/help/toolbox/compiler/brtm1xm-8.html
Quoting from the link: "The import statement is referencing a Java class () that MATLAB Compiler (if the error occurs at compile time) or the MCR (if the error occurs at run time) cannot find.
To work around this, ensure that the JAR file that contains the Java class is stored in a folder that is on the Java class path. (See matlabroot/toolbox/local/classpath.txt for the class path.) If the error occurs at run time, the classpath is stored in matlabroot/toolbox/local/classpath.txt when running on the development machine."
You just have to put import statements in a separate .m file.
so from:
javaaddpath 'c:\some.jar';
import com.something.Element;
...interesting stuff...
There will be a do_imports.m:
import com.something.Element;
And in original .m:
javaaddpath 'c:\some.jar';
do_imports
...interesting stuff...
And then it will compile and work. No need to mess around with system-wide classpaths.
Here is an extract from the link
http://blogs.mathworks.com/desktop/2009/07/06/calling-java-from-matlab/
MATLAB maintains a path for Java classes separate from the search path. That means even if you have a .class or .jar file on the MATLAB path, unless you use javaaddpath you will not be able to use it. To see what is currently on the path use javaclasspath. Running this command you will show you a long list of files that ship with matlab called the Static Class Path and then you'll see the Dynamic Class Path. The dynamic class path is where classes added to the path with javaaddpath will be placed. They can be removed with javarmpath and have to actively reloaded each session of matlab.

Structuring a jar?

NOTE: yes, minecraft has a specific coder pack, but it doesn't work for mac or linux (something to do with the python script portability)
While attempting to mod the main java jar file (minecraft.jar) i noticed it has an unusual structure, which im unsure on how to build. It contains all the objects (or the classes which are frequently called) at the top of the [name for structure of jar], and these, when decompiled, didnt belong to any packages. Whereas the files which were executed did belong to packages.
so my question is, how do i structure a jar file like this myself, with an IDE (eclipse/intelliJ)?
I think all you need to do is create some classes in the default package (no package declaration in the .java file).

How to load a library that depends on another library, all from a jar file

I would like to ship my application as a self-contained jar file. The jar file should contain all the class files, as well as two shared libraries. One of these shared libraries is written for the JNI and is essentially an indirection to the other one (which is 100% C).
I have first tried running my jar file without the libraries, but having them accessible through the LD_LIBRARY_PATH environment variable. That worked fine.
I then put the JNI library into the jar file. I have read about loading libraries from jar files by copying them first to some temporary directory, and that worked well for me (note that the 100% C library was, I suppose, loaded as before).
Now I want to put both libraries into the jar, but I don't understand how I can make sure that they will both be loaded. Sure I can copy them both to a temporary directory, but when I load the "indirection" one, it always gives me:
java.lang.UnsatisfiedLinkError: /tmp/.../libindirect.so: /libpure.so: cannot open shared object file: No such file or directory
I've tried to force the JVM to load the "100% C" library first by explicitely calling System.load(...) on its temporary file, but that didn't work better. I suspect the system is looking for it when resolving the links in libindirect.so but doesn't care about what the JVM loaded.
Can anyone help me on that one?
Thanks
One way would be to spawn another Java process from the first, generating the appropriate invocation script.
The jar is invoked by the user
The libraries are extracted to a temp directory
A (bash) script is written to the temp directory
this sets/exports the necessary environment variables
this launches the second JRE instance
The code makes the script executable
The code invokes the script
I know, spawning two JRE instances to launch one app would not be my first choice either.
If you are using Eclipse IDE, then this answer might help you.
I had same problem in eclipse windows that I couldn't added dependant .class files from the JNI.
After searching for a while I came to know that "Its a known bug inside Eclipse", In order resolve the same, I ported all the code to NetBeans IDE.
Can not add all the classes files from the JNI folder in Eclipse (JAVA, Windows 7)

Categories