I have a large project with multiple modules, which is deployed to glassfish using an EAR bundle (I'm using the Eclipse IDE).
One of the modules is an EJB project, which depends on a JAR library that depends on a some native libraries (DLLs). The DLLs are included in the jar
The problem I'm having is that the native libraries are not found. It seems that java.library.path doesn't contain the folder I configured in project Properties -> Java Build Path -> Libraries -> the jar -> Native library location.
Is there something I'm missing?
I haven't found a solution, but I found 2 workarounds.
Embed the DLLs into the JAR / EAR / WAR, and load them using this loader, which basically gets the DLL using the Class.getResourceAsStream method, copies it in a temporary directory, and loads it from there (this is the method I chose).
Add the DLLs to system $PATH. Either put the folder where they are located in the $PATH environment variable, or copy them in a folder that is in $PATH.
Related
I have created a JavaFX application using NetBeans IDE and below is my folder structure.
I want to a build a single jar file including all dependencies for this jar to work properly.
This jar requires testplanner and batch folder from project root directory and files inside dist folder to work properly.
How can I package all this to a single jar file?
Theoretically JAR files cannot contain dependencies within, as java does not support it out of the box. WAR and EAR archives can. What You want to do is not standard, but is named fat jar. Fat jars are used i.e. by spring-boot maven plugin, but you could try this:
https://dzone.com/articles/how-build-fat-jar-using
And some more explanation:
NetBeans - deploying all in one jar
Use tecreations Deploy. Put all your sources into a path declared as Tecreations.getProjectPath(), run BuildAll to create your corresponding classes, put your jars in projectpath/jars and select the appropriate settings, whether to include jars, sources or classes. Select your main class and click Deploy. Unsigned and signed output jars are produced in user/Documents.
Download: https://tecreations.ca/java/downloads/release.
How should I add JAR libraries to a WAR project in Eclipse without facing java.lang.ClassNotFoundException or java.lang.NoClassDefFoundError?
The CLASSPATH environment variable does not seem to work. In some cases we add JAR files to the Build Path property of Eclipse project to make the code compile. We sometimes need to put JAR files inside /WEB-INF/lib folder of the Java EE web application to make the code to run on classes inside that JAR.
I do not exactly understand why CLASSPATH does not work and in which cases we should add JARs to Build Path and when exactly those JARs should be placed in /WEB-INF/lib.
The CLASSPATH environment variable is only used by the java.exe command and even then only when the command is invoked without any of the -cp, -classpath, -jar arguments. The CLASSPATH environment variable is ignored by IDEs like Eclipse, Netbeans and IDEA. See also java.lang.ClassNotFoundException in spite of using CLASSPATH environment variable.
The Build Path is only for libraries which are required to get the project's code to compile. Manually placing JAR in /WEB-INF/lib, or setting the Deployment Assembly, or letting an external build system like Maven place the <dependency> as JAR in /WEB-INF/lib of produced WAR during the build, is only for libraries which are required to get the code to deploy and run on the target environment too. Do note that you're not supposed to create subfolders in /WEB-INF/lib. The JARs have to be placed in the root.
Some libraries are already provided by the target JEE server or servletcontainer, such as JSP, Servlet, EL, etc. So you do not need put JARs of those libraries in /WEB-INF/lib. Moreover, it would only cause classloading trouble. It's sufficient to (indirectly) specify them in Build Path only. In Eclipse, you normally do that by setting the Targeted Runtime accordingly. It will automatically end up in Build Path. You do not need to manually add them to Build Path. See also How do I import the javax.servlet / jakarta.servlet API in my Eclipse project?
Other libraries, usually 3rd party ones like Apache Commons, JDBC drivers and JEE libraries which are not provided by the target servletcontainer (e.g. Tomcat doesn't support many JEE libraries out the box such as JSF, JSTL, CDI, JPA, EJB, etc), need to end up in /WEB-INF/lib. You can just copy and paste the physical JAR files in there. You do not necessarily need to specify it in Build Path. Only perhaps when you already have it as User Library, but you should then use Deployment assembly setting for this instead. See also ClassNotFoundException when using User Libraries in Eclipse build path.
In case you're using Maven, then you need to make absolutely sure that you mark libraries as <scope>provided</scope> if those are already provided by the target runtime, such as JEE, Servlet, EL, etc in case you deploy to WildFly, TomEE, etc. This way they won't end up in /WEB-INF/lib of produced WAR (and potentially cause conflicts with server-bundled libraries), but they will end up in Eclipse's Build Path (and get the project's code to compile). See also How to properly install and configure JSF libraries via Maven?
Those JARs in the build path are referenced for the build (compile) process only. If you export your Web Application they are not included in the final WAR (give it a try).
If you need the JARs at runtime you must place them in WEB-INF/lib or the server classpath. Placing your JARs in the server classpath does only make sense if several WARs share a common code base and have the need to access shared objects (e.g. a Singleton).
If you are using Maven:
Open the project properties, and under Deployment Assembly click Add...
Then select Java Build Path Entries and select Maven Dependencies
Resolved by setting permissions.
Had related issue using PySpark and Oracle jdbc. The error does not state that the file cannot be accessed, just that the class cannot be loaded.
So if anyone still struggles, check the permissions. Some might find it obvious tho'.
I want to give the answer for the folowing link question ClassNotFoundException oracle.jdbc.driver.OracleDriver only in servlet, using Eclipse
Ans: In Myeclipse go to Server-->left click on Myeclipse Tomcat7-->Configure Server Connector-->(Expand)Myeclipse Tomcat7--> Paths-->Prepend to classpath-->Add jar (add oracle14 jar)-->ok
I have a JAR library that needs a native DLL library to work properly (Scriptom/Jacob).
I added the JARs to my classpath in ANT. But I do not know how to add a DLL file so my compiled Java/Groovy files finds them (neither in a generated JAR, nor in an ordinary execution by java Main.class). They are all located in a project subdirectory libs.
How do I have to alter my ANT build file that DLLs are recognized by my application?
PS:
As it works properly in a configured Eclipse environment: Is it possible to extract a fully working ANT build file from an Eclipse Run Configuration?
You can't use DLL files when they're still packaged in the jar.
I suggest you create an application folder where your .jar will be located at and next to the .jar, put your DLL files there. In your application you will need to load your DLLs from that location.
I need to find \jre\lib\ext under the java folder to add libraries. And I am not sure how to find it
Use String extDir = System.getProperty("java.ext.dirs"); to get the extensions dir path as you want (more info about system properties can be found here), set the path and write the jar files to that directory (be carefull to capture any IOException that could be raise in the writing process because this folders are usually write-protected or require root/admin privileges)
As quoted in the comments, this is something that should only be done in exceptional cases
As most comments say don't do so, the alternative.
Most applications have an app.jar and a lib folder in which all library jars reside. In the application jar there is a META-INF/MANIFEST.MF with a class path including the lib jars.
As a developer I use maven (like ant, ivy) for the build infra structure and it does it just so. The jars are taken from the local maven repository else from the remote ones. Also maven uses a local repository of all jars in different versions. Jars missing in the remote repositories, like own programming, can be installed there.
BTW /usr/lib/jvm/ contains the java versions (do which java, which javac).
I have a Java application and created a JAR file and deployed it.
The App uses external JARs such as the Log4J JAR. When creating my JAR file, how do I include all external dependent JARs into my archive?
In order to get my App working, I'm having to copy the Log4J JAR into the same directory as my own JAR which kinda defeats the purpose of the jar. Wouldn't it be more elegant to have 1 single JAR file to deploy?
If you use Eclipse, You can extract all included files into one runnable jar like this:
Right click on your project name from Package Explorer and select Export.
In Export screen, select Java -> Runnable JAR file and Next.
Fill in the Runnable JAR File Spec screen and Finish.
You can choose whether to package dependency jars as individual jar files or extract them into the generated JAR.
You could use something like One-JAR to package your Java application together with its dependency into a single executable Jar file (One-JAR uses a custom classloader to make JARs nesting possible).
You have to expand the library jars into the same place where your compiled classes go, then make a jar from that. Depending on how your build process is set up, there may be multiple ways to achieve this. It's not rocket science - a jar is just a zip archive with a META-INF directory at the root level.
Keeping JAR separate is better as it is easy to upgrade only the specific JARs to its new versions without touching any other configuration. As of your issue of having to copy each file to same location as of your JAR, you can always use Java CLASSPATH and include any JAR to your application's class path.
A JAR is not itself capable of nesting other JARs, as you discovered.
Traditionally, one would distribute a ZIP archive or other installer that would unwind the application JAR (yours) as well as any support JARs in the appropriate location for classpath access. Frequently, then, the application was invoked through a script that invoked the primary JAR and created a classpath that listed the support JARs.
As other posters have noted, you have some options to create a super-JAR if that's what you want.
You can use Maven + assembly plugin (http://maven.apache.org/plugins/maven-assembly-plugin/)
BTW, probably that's not the easiest way, if you did not work with maven.