Why is the java cookbook depending on so many other cookbooks? - java

I'm trying to run the open-source Java cookbook using chef-solo and although it shouldn't require any other cookbooks, chef keeps saying that a cookbook required to run this one is missing. First it asked me to install apt, then homebrew, then _build_essentials_. It seems like a never ending list of cookbooks. What am I doing wrong?
This is how I'm running the cookbook:
chef-solo -c solo.rb -o recipe[java]
Where solo.rb is a configuration file with the path to the cookbooks folder.
The same thing also happens when I try to run the WAS cookbook.

In short: Chef does not (yet) support conditional dependencies. That's why all cookbooks that provide resources or recipes that might be used need to be declared as dependency.
The Java cookbook uses resources from many other cookbooks to install Java on different systems, e.g., Windows, Linux, MacOS etc. Therefore, it makes use of other cookbooks, that provide resources for e.g. installing a package under Windows, adding an APT repository etc.
In order to allow the cookbook to either include a recipe or use a resource (e.g. apt_repository) from another cookbook, this one has to be specified as dependency so that it is loaded prior to executing the cookbook (e.g. Java). Otherwise, this resource/recipe would not be known to Chef.
So all of these cookbooks will be loaded during the Chef run, but their code will not be executed. While this feels a bit annoying, esp. in your case when you obviously manually download the cookbooks, this isn't so disturbing when you use Berkshelf for dependency resolution. This is highly recommended.

Related

Deploying JARs with Java 9 and above (JDK11 in this case) (JLink confusion?)

I'm a Java veteran, but I've been using JDK8 for a long time. I've decided I finally want to upgrade, so I've been using Java11. I've been enjoying the new features, but I've gotten the point where I need to deploy my software.
In the past I would export a runnable JAR from Eclipse and bundle it with an appropriate JRE. Then I'd use both to run the software from an OS-specific program (e.g. an EXE file that fires up the bundled JRE with the given JAR). Of course, now this isn't really an option because JREs are a thing of the past. Supposedly the new system in its place is much lighter weight and straight forward, the only problem is I can't figure out how to actually use it.
I've been reading about how to deploy programs with JDK9 and above and have seen people mention JLink and link documentation to it, but I can't seem to find a straight answer on how to just simply export a runnable JAR. The thing is - I don't really need all of the module support and don't really want to have to configure it. Is there a tool for simply exporting something I can run? How is this done now?
Sorry if this is a dumb question, I'm just genuinely confused at how this all works and can't really find anything online that lays it out in a clear and concise way. There's a lot of documentation on JLink and what it does, but I haven't really found anything that explains the root purpose for all of it.
TL;DR; how do I export working Java programs with JDK9 and above using Eclipse (latest version)?
Thank you for your time!
...how to just simply export a runnable JAR.
Well, if you're not planning on using modules for your application classes, the JAR part should be the same as before. You basically just have to create your own JRE using jlink, e.g.:
jlink --add-modules java.se --output jre
That would create a jre folder with a runtime image that includes all the java.se modules.
You can then bundle that with your JAR like before.
The interesting part here is that you can pick and choose which modules go into this runtime image. java.se is an aggregator module that transitively includes a bunch of other modules. But you could also specify your own specific list of modules, leaving out some of the ones you don't need, making the final runtime image smaller.
I've spent literally months on trying to figure out how to create a single, clickable executable using Java 9+. I now conclude that it is impossible. Whether you use jlink directly yourself, or indirectly via Maven or Gradle, the result is that jlink produces a full directory structure that you are left to "distribute to your users" (somehow, I guess magically, since nothing in Java 9+ tells you anything about how you're supposed to do this). Then, once your user (somehow) has this directory on their machine, they are forced to invoke runtime-image-directory/bin/your-program-name. As though your user is a programmer who is happy to have to install a directory structure, and drill down to invoke a specific file name, which is buried in a directory with lots of other files, rather than being a user who USED to be able to simply double-click on a .jar file to run it. This makes me really wonder if whomever designed all this thought at all about the "user experience". The fact that there appears, as of Java 9+, to be NO WAY to simply deliver ONE file (such as a .jar) to users, together with the fact that just BUILDING this "runtime image" is fantastically complicated, means that developers are going to abandon Java in droves. It really seems to me that the brainiacs at Oracle simply didn't think this through. They have created a death knell to Java by making something onerous for developers to build and distribute, and onerous for users to invoke. I don't see how this situation can be allowed to remain without Java ultimately dying off. Somebody please correct me if I am missing something here, but I've spent months now trying to figure out how to create a runnable jar in Java 9+, USING MODULES, and it appears there is no way to do it.

Deploy Jar With Java?

I was wondering how to include Java itself with a jar file so that people don't have to have Java installed already. Is it possible and if so, how do you do it?
To execute the jar in the first place you'd need to have java installed. So it would be best to include a JRE installer in a separate file if you'r including one. Also, you'd have to have a different installer for each target platform so this would be somewhat impractical for general distribution because of the inflated file size.
This is like asking "Can we include the chicken that lays the egg, in the egg?". Answer, no.
As to solving the bigger problem though, there is at least one strategy that might work well for applets, JWS apps. and (possibly) single Jars of desktop apps. that are launched from a link (I've never tried that, though). This approach uses JS to check for the right JRE before providing a link to the Jar.
In order to get a computer to do something, you need to have code that the operating system knows how to handle. Most modern operating systems do not know how to handle Java code unless you install a Java Runtime Engine - to them JAR files are just ZIP files.
Hence you need some code which can be executed directly (without Java) and the simplest is just to use a Java launcher. Many exist - see Java packaging tools - alternatives for jsmooth, launch4j, onejar - but e.g. launch4j is maintained and supports the <path> tag to specify a relative path to an included JRE. Those are unfortunately rather large, but you could provide two versions. One with the JRE, and one without (which then prompts the user to install a JRE).

Problems generating ant scripts for java when linking to Rhino

When I try to build my project using ant, I get:
"java.lang.NoClassDefFoundError: sun/org/mozilla/javascript/internal/Scriptable"
This stems from my usage of Rhino (the bundled java-script that comes with Oracle JDK)
When I build the project with eclipse, everything works fine.
The ant file I am using was generated by eclipse, and works fine except for the java-script dependencies.
These dependencies are located in the RT.jar that comes with the oracle JDK.
I have tried both jdk6_0_u41 and jdk7, and both give the same results: success in eclipse, fail with ant.
I have tried to build on both ubuntu 10, and 12
I have seen two other suggestions which seem unacceptible to me:
One thread suggested copying RT.jar into the project lib directory. (RT is entire java runtime! )
Another thread suggested that I shouldn't use:sun/org/mozilla/javascript/internal. But since I am doing advanced manipulation (Calling object methods, registering callbacks, etc) I see no alternative to using the sun.org.mozilla.javascript.internal family of classes.
A comment from Oracle's site:
Users should not write code that depends on internal JDK implementation classes. Such classes are internal implementation
details of the JDK and subject to change without notice.
This is not a compiler issue. javac is behaving correctly, according
to the information provided in ct.sym.
The issue belongs with those who decide what should be available with
(and what should be hidden by) ct.sym
You may suggest to include Rhino's jar to your project and repoint it on original's Rhino classes where 'internals' are not hidden from users

Is there anything like VirtualEnv for Java?

Is there anything similar to Python virtualenv for Java or JVM Languages?
From what I understand, virtualenv enables you to have separate library installation paths, effectively separate "virtual" Python installations.
Java doesn't have the concept of a "system-wide installed" library(*): It always searches the classpath for the libraries to be loaded. Since the classpath can be (and needs to be!) defined for each application, each application can pick-and-choose which libraries and which versions it wants to load.
If you go down one level deeper and have a single application that somehow needs two different versions of the same library at the same time, then you can do even that with some classpath trickery. It can get complicated, but it's definitely possible (OSGi is one example where this is supported, even Tomcat with two separate webapplications does this).
I've seens some references to security in the virtualenv description: Java has a pretty thorough security system built in. In server applications it's often turned off because it's just easier to configure this way, but you can easily configure what exactly a Java application is allowed to do.
(*) Almost, there are extensions or extension libraries, but they aren't used a lot and even those can easily be loaded from arbitrary directories.
Build tools like Ant, Maven, and gradle are the the closest thing to pip or easy_install.
The concept of virtualenv is done by the classpath. So there is no real need of virtualenv for Java
Yes(see http://www.jenv.be/), like many other languages (Ruby, Python, Go, R, Php, etc. etc.).
I know this may be a little late , but Groovy/Java has gvm http://gvmtool.net/ which is the Groovy version of Ruby's renv.
I would respectfully agree with Gautam K, luthur. Dependency and package version management for projects is not the same as an isolated self-contained virtual environment to maintain different project.
My 2 cents
-W
I have also been looking for a similar solution to simplify switching context between projects that use different Maven versions/settings and/or Java SDKs without having to modify M2_HOME and JAVA_HOME settings every time.
To this end, I developed a solution that helps execute mvn commands with the appropriate configuration based on per-project settings (stored in a .mvn folder).
See: https://github.com/AlejandroRivera/maven-env
Be aware that this only helps if you're using Maven to build and/or run your project.
I'm confused by the assertion that "Java doesn't have the concept of a 'system-wide installed' library". What would you call the jar files in $JAVA_HOME/jre/lib and $JAVA_HOME/jre/lib/ext?
Regardless of whether or not Java "needs" a tool like virtualenv, it seems that something that allowed you to quickly switch between different Java environments (e.g. Java 6 with such-and-such security extensions, Java 7, etc.) would be handy - even if all it was actually doing under the covers was manipulating the PATH, JAVA_HOME, and CLASSPATH env variables.
Maven, you can explicitly specify which packages you would use in a java project
Java as a language does not need the sandboxing features of virtualenv but a JVM Language like Jython can have VirtualEnv to use different environments without any conflict.
It is outlined in this blog post
Quote:
Get virtualenv installed for Jython. Just type "jeasy_install
virtualenv". Once that finishes you should have a 'virtualenv' tool in
the Jython installation's bin folder.
So when using Jython different frameworks and packages can be used without any conflict with global packages.

$CLASSPATH and -cp with Java

In this post, using -jar option ignores all the -cp and $CLASSPATH.
In this post, using -cp option also ignores the $CLASSPATH.
Is there any good reason for them?
It's to avoid clashes in the classpath whenever you distribute your application to run on different environments. In most of the cases you'd like your application to be independent from the platform specific configuration. If the $CLASSPATH contains references to classes with (either unawarely or awarely) the same package and classname, it would get precedence in classloading before the classes which you included in your application's classpath. This may lead to unexpected application behaviour or potential security holes.
jar is supposed to be a standalone program with self-contained libraries. If you want to include other classpaths, you may need to do something like
java -cp jar1:jar2:$CLASSPATH some.class.with.main
BalusC answered the other question.
In both cases, the reason for the restrictions it to avoid1 accidental or wanton / ill-considered overriding of the effective classpath.
If you really want an application to be launchable using "-jar" and to also pick up classes via the user's $CLASSPATH environment variable, you should be able to do this by having the application create its own classloader, or using a custom launcher. (You could even make your application look for a "-cp" argument after the "-jar" argument.)
Likewise, you could modify the behavior in the first case.
However, I think it would be bad idea to do that. The main point of executable JAR files is to isolate the application from the vagaries of the environment in which the user happens to launch the application.
If you want to do hacky things with your application classpath, a simpler approach is to create a wrapper script that assembles the effective classpath however you want to, then launches the application with a "-cp" option. You could even pull the "Class-path" out of various JAR files' manifests and incorporate that ...
1 - Clearly, it doesn't stop someone changing the classpath entirely. But stopping that would be a bad idea, and probably isn't technically possible if we assume that the user can get local admin privilege, etcetera.
There are several reasons why the environment variable CLASSPATH is (and should be) ignored:
A global CLASSPATH for all projects makes no sense at all. It can't be the same for all projects, and you don't want one massive one that's reapplied to all projects.
You can't count on it being set, so depending on it is a bad idea. Code that works on one machine suddenly doesn't work when it's moved. How do you communicate the necessary environment settings? Better not to use them.
Java EE app servers all have their own conventions (e.g., all JARs in WEB-INF/lib and all .class files in WEB-INF/classes are automatically in the CLASSPATH for a web app).
Java EE app servers all ignore global CLASSPATH. They don't count on it.
Java IDEs all have their own conventions for setting a project CLASSPATH. Learn them.
All Java IDEs ignore global CLASSPATH. They don't count on it.
I don't have a global CLASSPATH on any machine that I use. It's not necessary. I'd recommend learning how CLASSPATH works and stop relying on environment variables.
Correct or not, I long for a -jar-cp flag. That would be obvious and direct enough to not be a security risk or break current behavior.
With APIs like java.util.ServiceLoader, it is entirely reasonable to wish to add/remove services from the classpath. You shouldn't have to loose that functionality because you used Main-Class in your manifest.
There is no sane enough reason to explain this apparent "absurdity", in my words. From one of the bugs in the Sun bug database, one can only infer that a developer did not account for the fact that the classpath could be specified via the CLASSPATH environment variable, or via the -cp option. By the time the issue was found, the release was more or less public, with the effect that the fix would cause backward compatibility issues.

Categories