I'm trying to create a Wildfly Module for OpenText Documentum java client. Previously I was packing its jars to the .war file and my app was working, but they weight 23Mb.
In J2SE you usually just add the main jar which is dfc.jar and its dependencies are automatically added, because of Class-Path: entry in dfc.jar/META-INF/MANIFEST.MF. However, it doesn't seem to work in Wildfly 11: I created the module, made my webapp depend on it, but when I try to load the DfException class from the main jar Wildfly fails to find one of the dependencies which are in the same folder:
Caused by: java.lang.NoClassDefFoundError: org/aspectj/lang/Signature
at com.documentum.fc.common.DfException.<clinit>(DfException.java:710)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:264)
at org.foo.PrintClassloaders.printClassloader0(PrintClassloaders.java:50)
Is it possible to create this module without adding all the jars by hand?
Here's what I did:
module add --name=documentum.dfc2 --absolute-resources="C:\Program Files\Documentum\Shared\dfc.jar"
src/main/resources/META-INF/MANIFEST.MF:
Dependencies: documentum.dfc2
PrintClassloaders.java:
Class.forName("com.documentum.fc.common.DfException");
generated module.xml:
<module xmlns="urn:jboss:module:1.1" name="documentum.dfc2">
<resources>
<resource-root path="C:\Program Files\Documentum\Shared\dfc.jar"/>
</resources>
</module>
dfc.jar/META-INF/MANIFEST.MF:
Class-Path: All-MB.jar activation.jar aspectjrt.jar certj.jar commons-
codec-1.3.jar commons-lang-2.4.jar configservice-api.jar configservic
e-impl.jar cryptoj.jar cryptojce.jar cryptojcommon.jar dms-client-api
.jar jaxb-api.jar jaxb-impl.jar jcifs-krb5-1.3.1.jar jcm.jar jcmFIPS.
jar jcmandroidfips.jar jsr173_api.jar krbutil.jar log4j.jar questFixF
orJDK7.jar util.jar vsj-license.jar vsj-standard-3.3.jar xtrim-api.ja
r xtrim-server.jar
aspectjrt.jar is in the same folder. Why isn't it picked by the module classloader?
What you are trying there looks very strange to me. Modules (=Java libraries) belong into the modules folder and deployments should contain a deployment descriptor which lists all modules that it needs. In easiest case you only need the dependencies section inside the jboss-deployment-structure.xml file. See http://docs.wildfly.org/12/Developer_Guide.html#jboss-deployment-structure-file
Each module can contain multiple jar files and depend on other modules. When you take a look into some existing modules.xml files, you will see how it goes. Path names inside module.xml should be relative, otherwise you are not able to deploy them onto another computer with different folder structure.
You do not need any Manifest file for this.
Apparently, to add all the dependent jar files from the manifest Class-Path you have to explicitly create a <resource-root> element for each jar.
For cases when there is too many jars or there's a deep hierarchy I made a tool that parses the manifests recursively and prints the jboss-cli command to create the desired module.
Example:
C:\> java -cp org.foo.modulegen.Modulegen C:\some\main-jar.jar
Output:
--absolute-resources="C:\some\main-jar.jar;C:\some\jar2.jar;..."
https://gist.github.com/basinilya/15db9267ec753941d098cfd2f7ff844d
The tool tries to open each command line argument as a java.util.zip.ZipInputStream, finds and parses MANIFEST.MF with java.util.jar.Manifest and then does the same for each entry in the Class-Path attribute. It also ensures to not open the same jar file twice.
Related
I am using maven for my spring boot application(1.5 version). There are some files in src/main/resources like abc.properties, app.json. Below are some pointer what i want to achieve.
Exclude these files getting into the jar.
When i run my application through intellij these files should be available in classpath.
I looked at related answers on SO but none matches my case. Any suggestion?
you can use the resouce tag in maven pom file:
<resources>
<resource>
<directory>[your directory]</directory>
<excludes>
<exclude>[non-resource file #1]</exclude>
<exclude>[non-resource file #2]</exclude>
<exclude>[non-resource file #3]</exclude>
...
<exclude>[non-resource file #n]</exclude>
</excludes>
</resource>
...
</resources>
For more informations see: https://maven.apache.org/plugins/maven-resources-plugin/examples/include-exclude.html
My understanding is
You want some config file, that is available in classpath during runtime
Such config file will be changed based on environment
The way I used to do is:
Create a separate directory for such kind of resources, e.g. src/main/appconfig/
Do NOT include this in POM's resources (i.e. they are not included in resulting JAR)
In IDE, add this directory manually as source folder (I usually put this in testResource in POM. When I use Eclipse + M2E, testResources will be added as source folder. Not sure how IntelliJ though)
For point 2, I used to do it slightly differently. Instead of excluding, I will include in the result JAR but in a separate directory (e.g. appconfig-template), so that people using the application can take this as reference to configure their environment.
An alternative of 3 is: create a separate profile which include appconfig as resource. Use this profile only for your IDE setup but not building your artifact.
This site:
http://pic.dhe.ibm.com/infocenter/wmqv7/v7r1/index.jsp?topic=%2Fcom.ibm.mq.doc%2Fjm10330_.htm
says that
The manifest of the JAR file com.ibm.mqjms.jar contains references to
most of the other JAR files required by WebSphere MQ classes for JMS
applications, and so you do not need to add these JAR files to your
class path.
So in the MANIFEST of my jar I have the following manifest classpath:
Class-Path: /opt/mqm/java/lib/com.ibm.mqjms.jar
In the com.ibm.mqjms.jar, it contains the following MANIFEST classpath
Class-Path: jms.jar com.ibm.mq.jmqi.jar dhbcore.jar rmm.jar jndi.jar l
dap.jar fscontext.jar providerutil.jar CL3Export.jar CL3Nonexport.jar
My question is: when the com.ibm.mqjms.jar starts looking for the jms.jar (or other jar),
where will it be looking ? (or at least looking first?
In the jar file itself,or on the /opt/mqm/java/lib
It will be looking in the directory where com.ibm.mqjms.jar is present. This makes it easier for the user as one need not know the dependencies of com.ibm.mqjms.jar ... Just ensure that you don't move individual jars out of that directory.
Some more details here: http://docs.oracle.com/javase/tutorial/deployment/jar/downman.html
I'm trying to deploy a small app that uses log4j. The app is deployed as an executable jar with a manifest that contains a Class-Path attribute.
This is accomplished with the Ant jar task. Here is the line that defines the Class-Path
<attribute name="Class-Path" value=" ./ islib islib/commons-lang-2.0.jar islib/commons-logging-1.0.jar islib/log4j-1.2.16.jar" >
The executable jar is deployed and run from C:/ami/bin. log4j.properties cannot be found if it is in C:/ami/bin/islib but is found if it is in C:/ami/bin.
All other jars in /islib are found and the app runs normally.
Does the Class-Path in the manifest define a classpath only for the classes in the jar?
The Classpath defines where the class loader should find classes.
Log4j.properties is NOT read from the Classpath but from the file system, I.e. Relative to the current directory when the program is started.
(Logback looks for its configuration file in the Classpath in case you use slf4j as the logging API)
I create a new jar file. when i run the jar using
java -jar UpdateAvailable.jar com.dao.mysql.UpdateAvailable
I got the following exception.
Exception in thread "main" java.lang.NoClassDefFoundError: org/codehaus/jettison/json/JSONException
Caused by: java.lang.ClassNotFoundException: org.codehaus.jettison.json.JSONException
at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
But I copied all the supporting jars inside the UpdateAvailable.jar. Now what my requirement is run the jar file with out specifying supporting jars, like
java -jar UpdateAvailable.jar com.dao.mysql.UpdateAvailable
Here are some points to remember while you are working with JAR files and ClassPath: -
For making your JVM find class, your classpath should be set till the directory containing the class. In this case you have JAR.
So, you need to give the path till your Jar File Name
Now, since you have your Jar files inside your currently running Jar file, you can't set your classpath till the folder inside a Jar, so basically you won't be able to set classpath for inner Jar Files..
So, clearly JVM won't be able to see classes inside your inner Jar..
So, make sure that your required JAR files are outside of all the JAR files (I mean to say - avoid Nested JAR Files)..
I'm not sure how you are packaging your jar file, but it would sound like you need something like One-Jar to help you package your file and all your supporting libraries into a single jar. One-Jar comes with it's own classloader that allows it to load all the included jars in your executable jar file.
Configuration is fairly straight forward and easy to use. If you are using Maven, you can use the one-jar maven plugin to help you configure which libs you want included.
There are also other similar packages you can use instead of One-Jar, such as JarJar and ProGuard. Also take a quick look at this SO question.
In executable jar couldn't reads any supporting jar files inside a jar. So keep all supporting jars in a folder and place the executable jar in the same directory. And add "Class-Path" as "Supporting jar files separate with space" in "MANIFEST.MF" File. Now run the jar as
java -jar UpdateAvailable.jar com.dao.mysql.UpdateAvailable
I am trying to create an extensible app in Java and chose to use SPI. According to this tutorial I am following, I am supposed to create a specific file in META-INF/services in my jar, but don't know how.
I know how to create jar with META-INF, but can't find a way how to create the services folder and particular file in this folder. (I am using Eclipse)
Thanks for your help.
Since the tutorial is instructing to create it manually rather than using ant or maven or other build tools then just create a folder named META-INF at the root level with a sub-folder named services and a file called MANIFEST.MF.
I am not sure how you plan to execute your jar file, for now you can just put this one line in your MANIFEST.MF:
Manifest-Version: 1.0
For your services folder, you need to create a file named com.example.dictionary.spi.Dictionary with the following one line content as mentioned in the tutorial:-
com.example.dictionary.GeneralDictionary
FYI - META-INF is an internal Java meta directory. Generally, you want to rely on your packaging tool such as ant or maven to build the content of META-INF folder rather than doing it by yourself.
You can see the details on the content of META-INF folder here:-
The following files/directories in the META-INF directory are recognized and interpreted by the Java 2 Platform to configure applications, extensions, class loaders and services:
MANIFEST.MF
The manifest file that is used to define extension and package related data.
INDEX.LIST
This file is generated by the new "-i" option of the jar tool, which contains location information for packages defined in an application or extension. It is part of the JarIndex implementation and used by class loaders to speed up their class loading process.
x.SF
The signature file for the JAR file. 'x' stands for the base file name.
x.DSA
The signature block file associated with the signature file with the same base file name. This file stores the digital signature of the corresponding signature file.
services/
Assuming you are building your jar file with Apache's Ant, you need to add a metainf fileset, or better yet, use a services directive like so
<jar jarfile="pinky.jar">
<fileset dir="build/classes"/>
<service type="javax.script.ScriptEngineFactory"
provider="org.acme.PinkyLanguage"/>
</jar>
If you don't use apache's Ant, then you need to add a file to your jar
jar -uf jarfile.jar META-INF/services/name.of.general.service
which contains the name of the service's implementation
com.mycorp.services.Fooservice
If you are generating the JAR file using Eclipse's "Runnable Jar file export" under the project, select "save as ANT script" and then modify the ant script to pack in the services as described above.