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.
Related
I have a jar file that cannot be modified, but I want to use a different .class file in place of one of the members of the jar. How can I tell Java to use the external .class file when the code within the jar attempts to load it?
You could compile another jar file with replacement classes with exactly the same name and put it ahead of the jar file in the class path. For example, this is what the various slf4j bridge jars do to replace calls to log4j or Jakarta Commons Logging in library code with cognate slf4j code; one need not maintain two sets of logging systems and configurations that way.
If you want to override a java... class, you can use some of the command line options to change the boot class path. Look at the -Xbootclasspath options in http://docs.oracle.com/javase/7/docs/technotes/tools/windows/java.html. Heed the warnings.
There is also the lib/endorsed directory if you need to upgrade a third-party jar that Sun uses. Oracle uses other organizations' XML and CORBA libraries; if they release a new version and you need to adopt it, you can.
You can use AspectJ to instrument the code and possibly replace it. An around advice can call the original code if it wants.
You could see if you really need to replace the original code. Some systems provide customization hooks.
You need to make sure the external .class file is loaded first. If a class is already loaded by the class loader then it will not be reloaded. If you are using an application server, then there are ways to configure the preferences for loading classes for class loader. But if you are using a standalone application then you may need to extend the class loader to load the files in the order you want to.
I've created a project that dynamically writes, compiles and instantiates a new java class at runtime and it works just fine when I run this on the command line or within eclipse. Ultimately my goal is to create a technology very similar to JSP; the user provides a "template" file and I translate it into a java class and instantiate that class. My problem is that I can't seem to instantiate the newly compiled class when in the context of a web application.
The core of my problem is that I don't know where to put my compiled classes so that I can immediately instantiate them.
Here are my goals:
This will be a generic tool for other developers so it can't be specific to my filesystem or my java container.
If the user undeploys their webapp from the container it should also remove these generated classfiles.
Here are my thoughts but I have never done anything like this before:
Do I put these generated classes into one of the existing entries of the classpath, if so which one? Should I let the user provide a path and then my library will add this path onto the classpath? Maybe they provide a path and I just use a custom class loader to read them from that path? The user already provides the path of their "templates" (ex. WEB-INF/templates) so should I put my compiled classes with the original templates? My understanding is that translated JSP files are stored in a proprietary place specific to that java container and therefore I can not follow in the footsteps of JSP files.
Ahh! I'm overwhelmed! Maybe there's an open source java library that does something similar and I can study it to determine where it puts it's generated files??
Basically you will need to define your own classloader and do the loading from there.
See How do you change the CLASSPATH within 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.
I am using Matlab with Java integration and am able to link Java JAR files, enabling me to both create Java objects and call methods from within Matlab. The problem is with resources. For example, if I have an XML file located in the root of the JAR I can load it successfully from within a Java app, but not from Matlab.
Does anyone have an idea on how to make Matlab access resources within JAR files?
Thanks.
If you add a jar file to MATLAB's dynamic java classpath (e.g. using javaaddpath) the resources contained in the jar will NOT be visible to any java code. As discussed in this post, items on MATLAB's dynamic classpath are not really on the classpath of the JVM. In order to access the resources in my jar file I resorted to adding the jar to the static classpath. This can be accomplished in MATLAB R2012b by creating a file named javaclasspath.txt in the directory you start MATLAB that contains a list of the jar files you are using. Relevant MATLAB documentation
The normal Java Class.getResource methods should work when called from Matlab. What syntax are you using to try to load the resource in Java and in Matlab? If using getResource, are you calling it on a Class that was loaded from the same JAR that holds the resource?
In Matlab, classes on the static and dynamic classpaths use different ClassLoaders. Resources in a JAR on the dynamic classpath may not be visible to classes on the static classpath. So if your JAR is on the dynamic classpath, you need to make sure getResource is invoked on a class that came from that same ClassLoader.
I am a .Net developer starting Java development for Android and would like to know if it's correct to think of Java packages like .Net assemblies.
No.
The best comparison would be with a Java ARchive (Jar) file. Java uses packages to control the namespace, and is very similar to C#'s Namespaces.
Here is how I'd compare the environments
Java .Net
==== ====
Class Class
Package Namespace
Jar Assembly
No, I think a Java package would be more similar to a namespace
And an assembly would be more like a jar (I'm not so sure about this, as I'm much more familiar with Java than .Net... correct me if I'm wrong)
A Java package is like a namespace in .NET.
The equivalent to an assembly in Java is jar file.
A package in Java usually means just a namespaces for classes and interfaces, which in reality means a specific directory structure. Sometimes a .jar file is also referred to as a package. This is probably the closest you get to an assembly. A .jar file can also contain other data like images, or basically an kind of file since it is just a zip again with some specific content structure.
In any case: Usually when you read "package" in relation to "Java", some kind of namespaces (via folder structure, e.g.: com.mycompany.myproject) is meant. It doesn't help that some build tools refer to the process of building .jar file as "packaging" ;-)
Bear in mind that I'm far from a Java expert, but anyway, there it goes my take on this:
As pointed out by other answers, a package is not the equivalent to an Assembly. However, I don't fully agree with the idea of a .jar being the equivalent to an Assembly.
To me, a Java class (contained in a .class file) is closer to an Assembly than a .jar is. I'm saying this cause while the load unit for the CLR is the Assembly (which means all classes contained in that Assembly get loaded), the load unit for the JVM is a class (when the JVM needs a class, the ClassLoader does not load all the classes in the container jar, it just loads that specific needed class).
You can read more about java class loading here:
When does the JVM load classes?
and here:
http://www.lansa.com/support/notes/p0294.htm