Missing jar file error - java

I am developing an application with many functionality, where one functionality requires a jar file which is only commercially available. When I release it for public use for free, I have to remove this jar file from my source. When I run this application in Eclipse IDE with the jar file removed, it gives me "Errors exist in required Project". I would like to avoid this warning.
Only the users using the library should be able to access its corresponding functionality (The application has many functionality.)
Users who don't include this jar file should be able to access other functionality without any error/warning.
Requirement:
Gray out the functionality based on the absence of the jar file.
Avoid the warning message when I run the Main.java
Any help appreciated. Thanks!

What you need indeed is dynamic class loading, isn't it?
To enable this feature, you have some options:
Implement your own classloader.
Use OSGI.

Additional to yanana's solution, you can simply leave the commercial JAR file in your Eclipse project. When creating your setup you can create one setup for commercial use (including the JAR) and one for the open source version (without the JAR).
But you should be carefully separate the usage of the commercial classes into one or more package/module. At runtime you can check the presence of one class which is part of the commerical JAR file via reflection before accessing code dependent on the commercial JAR.
Your integration tests should contain some corresponding test cases with and without the commercial JAR in classpath.

Related

Include library for JAXB into JAR file without using Maven

I have a Java project in Eclipse that uses javax.xml.bind.JAXB classes.
Starting the application from inside Eclipse works perfectly.
However, when I export the project as (runnable) jar file and run it using java -jar myfile.jar it terminates with a java.lang.NoClassDefFoundError: javax/xml/bin/JAXBException.
Also playing around with the three options for Library handling in Eclipse Runnable JAR File Specification (extract, package, sub-folder) does not solve the problem - in fact, no libraries are exported in any case.
It seems that the library for JAXB (it seems to be rt.jar) is not considered as required library to be included into the jar file. However, when running the jar file, it is not found nevertheless.
I have read that the library must be added to the classpath but this seems strange to me as rt.jar is part of the standard libraries. Is there something special about this library?
Currently, I do not use Maven or something similar for dependency and build management and if possible I want to avoid it for the future. I think, there also must be a way without Maven.
I found several posts here on SO and in Google but was not able to work out a solution for me.
Thank you very much!
As remarked in the comments, Eclipse probably uses a different Java version than your system (by default). The JAXB API and implementation is not available in JRE 11.
To work on all versions of Java, your best option is:
Download the JAXB RI distribution. Nowadays I'll choose version 3.0 (which is binary incompatible with the one in Java 8, since it uses jakarta.xml instead of javax.xml for the packages name) as in Juliano's answer:
https://repo1.maven.org/maven2/com/sun/xml/bind/jaxb-ri/3.0.0/jaxb-ri-3.0.0.zip
Copy the 4 files jakarta.activation.jar, jakarta.xml.bind-api.jar, jaxb-core.jar and jaxb-impl.jar from the mod folder into the library folder of your project (let's say lib),
Add the 4 libraries to the project's "Build Path",
Make sure you use JAXB 3.0 throughout your code (the packages of the annotations and classes start with jakarta.xml)
Run the application once in Eclipse, so it updates the Run Configuration (or update the classpath of the Run Configuration yourself),
Export the project to a JAR file.
Among the three export options proposed by Eclipse: "extract required libraries" will create a so-called fat jar (everything in one JAR-file). It works, but it deletes the licence notices in the JAXB jars (so it can not be distributed). "copy required libraries" is your best option, but then you have to move the jar file together with the subfolder. _". "package required libraries" will not work, since jars in a jar are not read by the JVM (unlike JARs in a WAR package).
Edit by the author of the question:
The above worked for me well except that I experienced small differences how the two libraries (javax.xml in Java 8 and jakarta.xml in version 3.0) handle #XmlAttribute annotations. In javax.xml, I could place an annotation without further arguments on the public getter-method, e.g.
#XmlAttribute
public String getDescription() {
return "";
}
And this worked when the attribute name in the xml file is description. However, with jakarta.xml I had to add the name of the attribute:
#XmlAttribute(name="description")
public String getDescription() {
return "";
}
Just in the case, that others experience the same problem.
I thought about this myself too, since I am new to java.
There is a description of a Extension Mechanism in the java tutorials (SE), but it is no longer used since deprecated by Oracle. See, just to know of what I am talking about: https://docs.oracle.com/javase/tutorial/ext/index.html
What was this Extension thing in a nutshell: just drop your jar files inside the jdk lib and you could use the import keyword in all your classes to use the new jar file.
However, others had to do the same thing in their computers to run a class which imported your own update to the jdk.
Maven do something like the above. It searches on the pom file which other jar files it should include in your jar when you build an application. Hence, it may run anywhere.
Another way of looking into this is the answer which you should try to do.
A clunckier way of doing what Maven does without its pom structure is to create a new folder inside your src folder and copy the jakarta.xml.bind-api.jar. Just like when you create an object (aJavaBean) and need to use it in another class.
The file you need to include in your library is available at:
https://repo1.maven.org/maven2/com/sun/xml/bind/jaxb-ri/3.0.0/jaxb-ri-3.0.0.zip
Finally, extract the classes inside this newly created folder and use the import keyword in the classes that depend on it just like when you create your own classes.
Another thing you should try is to use the manifest file when making your jar.
https://docs.oracle.com/javase/tutorial/deployment/jar/manifestindex.html
This tutorial shows how to include a classpath to the files you need to run as a dependency. Make sure that everything you need is inside the newly created jar file.
Also, set the entry point in the manifest, so your application can run just using
java -jar MyJar.jar
in the command line.
The easiest way is to use JDK 8 (or older JDK) that has embedded the required jaxb library. The hard way requires that you set your CLASSPATH variable pointing to each required jaxb jar file.
From spec at https://javaee.github.io/jaxb-v2/doc/user-guide/release-documentation.html#a-2-3-0, the following jars are required using a java version 11 or above.
jaxb-api.jar
jaxb-core.jar
jaxb-impl.jar
A good article on this question is https://www.jesperdj.com/2018/09/30/jaxb-on-java-9-10-11-and-beyond/

AEM 6.1 Sightly Java class does not update on build

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

Create sources jar for shrunk classes in a module via proguard

There is a business module - say kilo-business in one of the applications. Now there are some APIs in this module that is to be used by another application (locally within the organization - say kilo-client1). I have used Proguard (via its maven plugin) to only extract the classes relevant to the API and make a JAR out of it - the shrunk API JAR called kilo-business-apis. kilo-client1 uses this kilo-business-apis dependency and invokes the service. As a policy, we always include sources along with any artifact that we share between applications (for debugging ease and additional documentation).
In this case, is there a way that one can have Proguard also give out the (probable) source files (belonging to kilo-business module) from where it has sourced the classes for the kilo-business-apis using which a sources JAR can be conjured? Actually, we don't shrink the JAR to the extent of removing unused methods/variables from the class, so giving out the source java files would also suffice.
I understand that one can use jd-eclipse or some other decompiler in eclipse to aid debugging even if we don't publish it, but wanted to check if we can generate the sources first class whereby documentation needs are also addressed.
One thought is to break up kilo-business itself into a separate module for kilo-business-apis where only the API definitions reside and both kilo-business and kilo-client1 can use it, but unfortunately I can't do it for legacy reasons.
Thanks in advance!
ProGuard optionally writes out information about kept entry points (-printseeds), unused code (-printusage), and obfuscation mapping (-printmapping), but nothing related to source files. If you don't obfuscate the code, you can simply list the .class names in the processed output, and find the corresponding .java files.

How to load a resource from compound JAR?

I have the following problem:
I am writing an application that uses some of the JARs from the Netbeans Platform. To be exact, I am only using the Netbeans Visual Library for creating some graphs. This can be done without using the Netbeans Platform by extracting 3 JARs from the platform. This is all working well, except for 1 problem.
Some Background
I am using the Java Simple Plugin Framework (JSPF) to handle my plugin management. So I have an application that basically consists of a skeleton framework, and then depending on which plugin JARs it finds, it can do various things, one of which is drawing graphs. The JAR plugin for this functionality has all it's dependant libraries inside. This is done by exporting the JAR as an artifact in IntelliJ, which will unJAR all the dependant libraries and reJAR them inside yours (so everything you need is there).
The Problem
What seems to be happening though, is that when it tries to start use the classes from the embedded libraries, it works fine, but when it needs resources (.png specifically in my case), it complains that it cannot find it.
My Thoughts
The only thing I can think of why it is not working, is that it could be since the plugin JAR is not in a classpath. Could this be it?
Is there anyway to specify a classpath directory in the MANIFEST maybe? Otherwise must I create my own ClassLoader and manually load all the JARs in the plugins directory?
Thank you!
UPDATE:
I have subsequently pinpointed that it is indeed a problem with the classpath. If I place my compound library on the classpath, everything works perfectly. The problem I experience now though is:
If I copy the library to /Library/Java/Home/lib/ext/ it works fine. If I execute the application with java -cp "/path/to/plugins/myLib.jar" -jar Application.jar it does not work.
How can I load all the jars in the plugins directory into my application so the resources inside them can be used?
Thanks again!
So I have finally figured out what was happening. When creating a executable jar, the MANIFEST.MF file overrides any classpath you specify in the command-line, which basically renders it useless if you want to specify external jars. This seems to be a general problem that has been logged since Java 1.3 already.
My simple solution is to simply not create a executable jar, and then launch the application with a script:
java -cp App.jar:plugins/* my.package.structure.App
which works perfectly.
The default classloader's do not load classes in nested jars. You'll need to write your own classloader to get the classes in the nested jars.
You can check out this jspf article...
"I forgot: Adding dependencies as JARs inside JARs is not possible, because it would not work in all scenarios (e.g., applets); IIRC also tools like Eclipse would have problems if you used classes with unresolved (read: runtime-resolved-dependencies). To my knowledge there is no established way yet to gracefully handle nested JARs in all circumstances."
http://code.google.com/p/jspf/wiki/UsageGuide

Whats best way to package a Java Application with lots of dependencies?

I'm writing a java app using eclipse which references a few external jars and requires some config files to be user accessable.
What is the best way to package it up for deployment?
My understanding is that you cant put Jars inside another jar file, is this correct?
Can I keep my config files out of the jars and still reference them in the code? Or should the path to the config file be a command line argument?
Are there any third party plugins for eclipse to help make this easier? I'm using an ant build file at the moment but I'm not sure I know what I'm doing.
Is there an equivelent of the deployment projects in Visual studio, that will figure out everything you need and just make an installer? I've used install4j before, and it was powerful if no where near as automated as .Net deployment projects.
Cheers.
There is no one 'best way'. It depends on whether you are deploying a swing application, webstart, applet, library or web application. Each is different.
On point 2, you are correct. Jar files cannot contain other jar files. (Well, technically they can, its just that the inner jar file won't be on your classpath, effectively meaning that jar files do not contain jar files).
On point 3, you certainly can reference config files outside the jar file. You can typically reference a config file as a file or a resource. If you use the resource approach, it typically comes from the classpath (can be in a jar). If you use a file, then you specify the filename (not in a jar).
In general, most Java developers would use Apache Ant to achieve deployment. Its well documented, so take a look.
(1) An alternative to ant that you may wish to consider is maven.
A brief intro to maven can be found here.
For building a JAR, maven has the jar plugin, which can automate the process of ensuring all dependent jars are listed in your jar's manifest.
If you're using eclipse, then download the maven integration as well.
(2) Another alternative is to use OneJar (disclaimer: haven't tried this myself).
The answers vary depending on what kind of thing you're building.
If you're building a library, it's best to distribute your work as a jar file. It's possible to refer to your jar dependencies via the Class-path attribute in your jar manifest, although I generally think that's uncool. That attribute was designed for applets and it's used infrequently enough in libs that when this technique pulls stuff into the classpath (particularly common stuff the user might already be using), you can get unexpected version conflicts. And it's hard to track down why you're seeing them.
Publishing a jar to a Maven repo with pom info to track dependencies is an excellent choice for libraries as well. If you do that, please publish your Maven coordinates in your docs!
If you're building an app, the two popular choices are to distribute a zip/tar/whatever of a deployment structure OR to use an installer program. If the program is a server-ish kind of thing, the former is far more common. The latter is more common for clients. Generally, the installer program is just going to lay out the deployment structure and maybe do some extra tasks like installing in OS-specific locations.
To build your deployment structure (aka "kit") you'll want to create a repeatable process in whatever build system you're using. Ant has copious examples of this and Maven has the assembly plugins that can help. Generally you'll want to include a jar of your code, any dependencies, scripts to start the program, maybe a JRE, and any other resources you might need.
If you want to create an installer, there are many options both free and commercial. Some folks I know have recently had good experiences with the free IzPack but check out your options.
You should try FatJar. It's an Eclipse plugin that with just a right click at the Project can build a JAR file with all you need to run the application, including the necesary third party JAR.
We use it everyday, in conjuction with JSmooth to create the executables, to deploy our software packages to our customers, and works like a charm.
Well, if you are speaking of deployment of a standalone desktop application:
Before we switched to web start we have been creating three deployment archives, one for windows, one for mac and one for other platforms.
On windows we have successfully used the Nullsoft Scriptable Install System (known for it's usage by the older winamp versions) and its ant task, although some drawbacks are:
It is only usable on windows AFAIR
You have to do some work by hand, i.e. customizing the wizard-created script AFAIR
It can create a windows installation with start menu entries on the other hand. There also exists an eclipse plugin for integrated NSIS shell script editing.
On Mac OS X there is an ant task to create an .app file from your java files so that you can start it like a native os x application. But beware of not writing any setting to your home dir and using the the application dir instead.
For others you have to expect they are in a un*x env and deploy your app with a shell script to start the application.
In any case you may have to deploy your custom policy file to get access rights for your application.
If you want to get rid of all the packaging and stuff you should seriously consider using web start. We have saved much time since switching to it, i.e. simplified our deployment process, takes care of updates etc.
Update 2014
Use maven assembly plugin, see section "Creating an executable jar"
Ant. It's not the best thing in the world, but it's standard, it's apache, and it works.
There's some good examples on the web how to make a simple build.xml for any, and it's got some features like the 'war' task that knows how to put all the basic stuff (classes, web.xml etc) in the jar file for you.
You can also tell it to pick up other config files and jars and it will happily do it.
It's also really smart about what to compile. You give it a directory, and it finds all the java files and builds them only if their classfile is out of date, so you get some of the traditional make functionality for free without much effort.
You could look at other java projects (e.g. JMeter, SquirrelSQL, JEdit, Cernunnos, etc.). Each package their applications slightly differently, so consider your goals when you review these.

Categories

Resources