I have created a few classes in Java and have combined them into a single package in the 'org' namespace. How do I access them from RingoJS?
Must I copy the package into the 'src/org' directory in Ringo or do I have to modify the classpath dynamically from the script?
I finally figured out how to access custom Java classes in RingoJS. I must have been really stupid to have never seen it right in front of my eyes before.
In Rhino, to access custom Java classes you need to add them to your Java classpath. This can be tedious, especially when an end user without any knowledge about programming tries to install a CommonJS package which requires specific Java classes to be in the classpath. Correct me if I'm wrong. Package managers like Tusk might be able to do that for you, and I would really appreciate it if you would notify me about such a feature. However, as far as I know it's the end users responsibility to add the Java classes and/or jar files to the classpath.
RingoJS simplifies this a great deal. It provides a global function addToClasspath(pathName) which adds a JAR file or directory to the classpath. Thus we may have a Java package or JAR file in the root directory of the CommonJS package and use the addToClasspath function in the JavaScript file itself to automatically add it to the classpath. In addition, all JAR files in the RingoJS lib directory are included in the classpath by default. This simplifies matters a great deal.
For programming purposes you may add JAR files to the RingoJS lib directory. However, I wouldn't recommend it. To reduce coupling and keep the RingoJS lib directory clean (preventing future namespace problems); and to make installation for the end user easier, I suggest using the addToClassPath function. Perhaps it should be implemented in other Rhino-based CommonJS implementations as well.
Related
I've looked here and the wider web to find a solution to this. There's related material, but I've been unable to find anything useful about my specific question.
I'm working on some Java software that needs to accept plugins. I don't want to use a fancy framework like OSGi, and ServiceLoader seems to offer the right level of support. I've basically got it working but am having a problem with classpaths. My directory structure is as follows:
progfolder
|___________ plugintest.jar
|___________/plugins
|________ plugin1.jar
|________ plugin2.jar
If I run plugintest.jar with java -jar plugintest.jar then it doesn't find the plugins even if I add ./plugins/ (or variations of this) to the Class-Path: in the manifest. Reading suggests that this only works for classes, not jars, so I've tried putting the classes from the two plugins inside plugins both directly and within their full path of directories, but with no success.
I'm not allowed to add -cp plugins/* to add the plugins folder to the classpath if I'm using the -jar option. To get round this, I can run using java -cp plugintest.jar;plugins/* com.plugin.test.Main and this works as expected - the two plugins are detected and accessible via code, but the command line is a bit clunky, although I could live with it, if it's the best option.
I found another solution where I create a classloader for jars found in plugins, which works in this simple case, but reading suggests I might run into security issues in a more complex application.
Is there a way to fix things so I can simply run with java -jar plugintest.jar without having to do my own class loading or is this just the way it is?
Ok, so at least a partial answer, following more experimentation. Putting the class files in the plugins directory does work, after all, but you have to remember to include the META-INF directory and META-INF/services. The file in the services directory has to include references to all the plugins.
It would be nice if there was a solution that allowed the plugin jar files to be used directly, but creating a class loader seems to be the only way to do this (that I've found, at least), and this may cause security issues, as previously noted.
last time I faced with similar problem [1]. I found answer in java documentation [2]:
Note: The Class-Path header points to classes or JAR files on the local network, not JAR files within the JAR file or classes accessible over Internet protocols. To load classes in JAR files within a JAR file into the class path, you must write custom code to load those classes. For example, if MyJar.jar contains another JAR file called MyUtils.jar, you cannot use the Class-Path header in MyJar.jar's manifest to load classes in MyUtils.jar into the class path.
[1] https://github.com/narvi-blog/01-exec-jar#dependency-jar-files-within-an-executable-jar-are-not-so-easy
[2] https://docs.oracle.com/javase/tutorial/deployment/jar/downman.html
I have recently started using Sightly in AEM 6.1, which allows the Java files to be located in the same folder as the component and use the WCMUse class. However, I am noticing that whenever I do a Maven build that involves a change to one of those Java files that the page functionality operates as if the Java class had not been changed, though the Java file in the crx does include the changes. As a workaround I have been been able to modify the Java file in the crx, save it, then modify it back and save again in order to update the functionality, but I do not have that capability on all of my instances.
Anybody have an idea how to force the recompile of the Sightly Java within the components either during or following the build?
A few things to validate:
1- Do you change the version of the software when doing a maven build/deploy? Sometime if your zip or jar does not have -SNAPSHOT in it AEM won't update the code when maven deploys.
2- there a /var/classes/sightly in CRX/DE that you can delete compiled classes, I think even in the system console there is an entry
Hope this help.
Bambara actually helped me get to the answer that I needed. It turns out the /var/classes folder holds the compiled sightly files, but it doesn't naturally recompile on build. Deleting that folder on build, then running a page that uses the sightly code forces a recompile and shows the new functionality.
Hopefully others can answer why this happens and how to avoid it. Having faced this a number of times, I'm beginning to think placing Java code into the component folders is not a very good idea. Using a maven multi-module project with a Services/Core bundle, then all Java code could go there. Calling it from the view just requires using the fully qualified classname (including the package). Placing the Java into the services bundle has the following benefits
Allows the classes to be extended. For some reason compilation was unpredictable when extending classes from component folders.
Easier IDE setup. Java classes in component folders in the view module have a Sling specific folder structure, so getting IDE's to provide code assist requires extra effort.
Sling folder conventions follow URI practices and might have dashes, Java packages cannot have dashes... import apps.my-cool-project.components.pages.base.Header; // won't compile
I need to access some resources (for a contextual help system) which may be located either in a directory tree (somewhere in the filesystem) or contained into a specific .jar.
Resources in the filesystem should take precedence over "packed" ones.
I should provide a runtime (not a compile-time action) command to migrate all resources from filesytem directory tree to the .jar package.
I want to build a separate .jar to contain just those resources. I don't want/need to modify code. I need to deliver a product with minimal help and allow the costomer to refine it and update need to recompile. Customer will then distribute the "improved" version.
What is the best way to implement this?
I'm interested specifically in the "migration" part, since I should be able to code the resource access part, but comments are always welcome.
There are various ways this can be implemented but re-using Java's ability to read resources from a directory on the classpath looks the easiest to me.
Deliver the application with a zip-file containing the updatable help-resources. At application start, extract this zip-file to apphome/help-resources but do not overwrite newer/modified files. Use the technique in this answer to add the apphome/help-resources directory to the class-path. From then on resources can be loaded as if they are in a jar-file on the classpath (no special code needed).
The customer can update the files in apphome/help-resources and using a runtime-command the zip-file can be updated/recreated with the files in the apphome/help-resources directory. Or if the customer has 7-zip or something similar, just create the zip-file using the zip-tool.
Well, maybe it's convoluted, anyway...
I'm not very experienced with java, though I've dabbled in creating some Minecraft mods and Android apps.
My question is: I have a .jar that contains code that I don't have a lot of control on (I don't have the source code though I do have some infos about the classes in it), and when this jar is run it itself load some code from other external libraries and classes, and consolidate everything.
My question is then, how do I, without touching/modifying the jar, make a java program that runs the jar, let it do its consolidating from other jars and external classes, then get the results (a few objects) of that consolidating into my own java program ? Is that even permitted in the java security model ?
I've heard of URLclassloader that I think is to load load classes from a jar. It can't seem to make it work, and I'm not even sure that would work ? I know roughly which classes are entry point in the jar in order to run it and make it load the external libraries. But I always run into exceptions left and right.
First you should make sure all 3rd partyd dependencies (e.g. libraries that your jar needs) are ~visible~ to your application (e.g. reside on classpath and/or -Djava.library.path). Next, you should just instantiate classes/call methods from your jar file normally and operate with returned objects as its been locally created by your Java application. jar file is just an external library that becomes the part of your application upon loading.
I'm beginning to play with Clojure a bit and my Java experience is pretty limited. I'm coming from the dynamic world of Ruby and OO, so the functional side of things is very interesting!
Anyway, as I discover libraries and various tools for use (and the tutorial files for the Pragmatic Clojure Book), everything typically calls for placing files in the CLASSPATH in order for Clojure to see the library for use.
Is there such thing as good CLASSPATH practice? Would I ever want to only have a CLASSPATH with just the external libraries of files I need or can I go ahead toss any library or file I would ever need in a directory and simply define it as my CLASSPATH and only require what's needed?
If it helps, I'm an OSX and Emacs user (Using slime and swank-clojure).
I recommend using leiningen and lein-swank to manage this. You can start a REPL in the directory and connect to it from Emacs.
Personally, I'm using a variant of a clojure-project elisp function by Phil Hagelberg, see source in this post to the Clojure group. It sets up the classpath appropriately for the project you'll be working on, then launches SLIME. (EDIT: You'll need to change the value which gets assigned to swank-clojure-jar-path to point to clojure.jar. I'm using (expand-file-name "~/.clojure/clojure.jar") as the default.)
To answer the question about having everything on the classpath all the time vs only throwing in what's needed: to the best of my knowledge, nothing will actually break if you take the first approach (I know I do that for experimental purposes), but apparently things might break with the first approach (see cjstehno's comment below) and in a proper project I find the second to be cleaner. At some point it'll be necessary to determine what libs are being used (and which versions of them), if only to tell leiningen (or maven) about it -- why not keep tabs on it as you go.
We are using Clojure and use a number of infrastructure tools, especially Eclipse (IDE) (http://en.wikipedia.org/wiki/Eclipse_%28software%29) and maven (http://en.wikipedia.org/wiki/Apache_Maven). maven manages libraries and jar dependencies so if you have a number of these and they are likely to grow start using maven.
In answer to your original question you can just put your jars in one directory and you can access them by name every time you run. But you will benefit from the tools...
If you are just exploring then Eclipse will probably manage your jar files fairly painlessly. You can add these to the project as required through the Build Path -> Configure Build Path option.
As your work progresses you will possibly wish to split it into Projects which Eclipse supports so you can add your (or other projects) to your Build Path.
If you use external Clojure libraries look to see if they have been packaged as maven projects (they will have a pom.xml file). The POM will give a list of dependencies.
#
The usual CLASSPATH practice for Java is to put only the jar files needed for a project into this projects class path, which means to have potentially different class paths for diffent projects. This is usually managed by the IDE as part of it's project properties.
Since you are using Emacs and thus probably don't have or use something like projects it might be more convinient for you to set up and use a single global class path for all your clojure related stuff or maybe even simply put all the needed jar files into the java2se/jre/lib/ext directory of your java installation.
The two main problems that could arise from having unneded jar files in your class path are: 1. it has a minor negative impact on the start up time of the JVM and 2. it becomes more difficult to make sure that you are not having classes with different versions in the same class path (i.e. different classes with the same package and name in different jar files).
Since Java SE 1.6 (or JDK 1.6) you can include class path entries by wildcard. If your class files live in .\bin, and your library jar files live in .\lib, then on Windows you could define your class path like this:
set CLASSPATH=bin;lib\*;
This will let you add jar files into the .\lib directory and they will automatically be added to the class path for new instances of the JRE.
See this link for details: Setting the class path
Prior to JDK 1.6 you had to add each jar file onto the ClassPath individually.
I just discovered this bit which I need to give a shot:
(setq swank-clojure-extra-classpaths (list "/class/path/1" "/class/path/2" "/class/path/3" "etc"))
clojure-contrib/launchers/bash/clj-env-dir has an interesting property that you can point it at a directory and it will basically include anything in there. In the past I've had a ~/classpath directory which I would dump any jars into and link any commonly used directories and it worked great. Very simple way to dump and use. Now I tend to use Maven clojure-maven-plugin and that works well also though can be a bit tedious when you just want to muck around with some ideas.