Proper way of defining external jar in manifest files - java

I am having hard time to find out how to define external jar in manifest.mf. When I use class path as shown below jar file does not get executed
Manifest-Version: 1.0
Sealed: true
Main-Class: org.test.MainClass
Class-Path: /Program Files (x86)/Testfolder/testlibrary/hibernate3.jar
/Program Files (x86)/Testfolder/testlibrary/org.springframework.web-3.1.1.RELEASE.jar
When I give proper full class path as shown below, the Main class is not found or loaded
Manifest-Version: 1.0
Sealed: true
Main-Class: org.test.MainClass
Class-Path: D:/Program Files (x86)/Testfolder/testlibrary/hibernate3.jar
D:/Program Files (x86)/Testfolder/testlibrary/org.springframework.web-3.1.1.RELEASE.jar
Does any one have any idea what am I doing wrong?

According to the documentation:
Class-Path Attribute
The manifest for an application can specify one or more relative URLs referring to the JAR files and directories for other libraries that it requires. These relative URLs are treated relative to the code base from which the containing application was loaded.
An application (or, more generally, a JAR file) specifies the relative URLs of the libraries that it requires with the manifest attribute Class-Path. This attribute lists the URLs to search for implementations of other libraries if they cannot be found on the host Java virtual machine. These relative URLs may include JAR files and directories for any libraries or resources needed by the application. Relative URLs not ending with a slash (/) are assumed to refer to JAR files. For example:
Class-Path: servlet.jar infobus.jar acme/beans.jar images/
At most one Class-Path header may be specified in a JAR file's manifest.
Currently, the URLs must be relative to the code base of the JAR file for security reasons. Thus, remote optional packages will originate from the same code base as the application.
Each relative URL is resolved against the code base from which the containing application or library was loaded. If the resulting URL is invalid or refers to a resource that cannot be found, then it is ignored.

I found that I can also define absolute path as
Class-Path: file:///D:/Program%20Files%20(x86)
And this worked fine for me. The error regarding main class not found was related to the error in the class path and using absolute path as shown above will resolve the issue.

Related

Read specific resource from classpath

I have a maven project and in class-path (resources folder according to maven standard layout) I have several log4j.xml files, like this:
-resources
-log4j.xml
-folder1
-log4j.xml
-folder2
-log4j.xml
How I can read log4j.xml located at root? I think the following code doesn't guarantee that I will get log4j.xml from root:
Thread.currentThread().getContextClassLoader().getResourceAsStream("log4j.xml")
Unless some other jar file is in the classpath of the current thread(s classloader, before yours, and also contains a log4j.xml file at the root, your code will do what you expect it to do.
To get the other one you would use "folder1/log4j.xml" as path.

Can't find bundle for base name /Bundle, locale en_US

I'm using a library that has a dependency on JSF.
When I try to run my project, it show following exception massage..
java.util.MissingResourceException: Can't find bundle for base name /Bundle, locale en_US
at java.util.ResourceBundle.throwMissingResourceException(ResourceBundle.java:1427)
at java.util.ResourceBundle.getBundleImpl(ResourceBundle.java:1250)
at java.util.ResourceBundle.getBundle(ResourceBundle.java:705)
Any ideas ?
The exception is telling that a Bundle_en_US.properties, or Bundle_en.properties, or at least Bundle.properties file is expected in the root of the classpath, but there is actually none.
Make sure that at least one of the mentioned files is present in the root of the classpath. Or, make sure that you provide the proper bundle name. For example, if the bundle files are actually been placed in the package com.example.i18n, then you need to pass com.example.i18n.Bundle as bundle name instead of Bundle.
In case you're using Eclipse "Dynamic Web Project", the classpath root is represented by src folder, there where all your Java packages are. In case you're using a Maven project, the classpath root for resource files is represented by src/main/resources folder.
See also:
Maven and JSF webapp structure, where exactly to put JSF resources
maven-tomcat-plugin
If you start the Project using the maven-tomcat-plugin / maven-tomcat7-plugin, you must place the Bundle.properties, or even the Resource.properties in src/main/webapp/WEB-INF/classes. Dont ask why, its because how the plugin fake a tomcat.
If you are running the .java file in Eclipse you need to add the resource path in the build path .
after that you will not see this error
In my case the problem was using the language tag "en_US" in Locale.forLanguageTag(..) instead of "en-US" - use a dash instead of underline!
Also use Locale.forLanguageTag("en-US") instead of new Locale("en_US") or new Locale("en_US") to define a language ("en") with a region ("US") - but new Locale("en") works.
I had the same problemo, and balus solution fixed it.
For the record:
WEB-INF\faces-config is
<?xml version="1.0" encoding="UTF-8"?>
<faces-config
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd"
version="2.0">
<application>
<locale-config>
<default-locale>en</default-locale>
</locale-config>
<message-bundle>
Message
</message-bundle>
</application>
</faces-config>
And had Message.properties under WebContent\Resources (after mkyong's tutorial)
the pesky exception appeared even when i renamed the bundle to "Message_en_us" and "Message_en". Moving it to src\ worked.
Should someone post the missing piece to make bundles work under resources,it would be a beautiful thing.
In my case I was dealing with SpringBoot project and I got the same exception.
Solution is made by adding env.properties file into classpath (i.e. src/main/resource folder). What was making the issue is that in log4j configuration there was property like
<Property name="basePath">${bundle:env:log.file.path}</Property>
The Bundle.properties file must be in the directory of the .class files. If it is located in the src directory then you need to make sure to copy it to the bin (output) directory in the same package.
Bundle names have to be fully qualified, like if your bundle Bundle.properties
is inside x.y.z package, then you have to write ResourceBundle.getBundle("x.y.z.Bundle");
I had the same problem using Netbeans. I went to the project folder and copied the properties file. I think clicked "build" and then "classes." I added the properties file in that folder. That solved my problem.
I use Eclipse (without Maven) so I place the .properties file in src folder that also contains the java source code, in order to have the .properties file in the classes folder after building the project. It works fine.
Take a look at this post: https://www.mkyong.com/jsf2/cant-find-bundle-for-base-name-xxx-locale-en_us/
Hope this help you.
The problem must be that the resource-bunde > base-name attribute at the faces-config.xml file has a different path to your properties. This happened to me on the firstcup Java EE tutorial, I gave a different package name on then project creation and then Glassfish was unable to find the properties folder which is on "firstcup.web".
I hope it helps.
Make sure you didn't add the properties files in the wrong resources folder as there is one under 'Web Pages' and one under 'Other Sources/...'. They needed to be under 'Other Sources/...'.
I was able to resolve the issue, the resource was in my project directories but when the junit utility tries to load it, it was returning an error of MissingResourceException. And the reason was the resource was in the not on the classpath of the test class package so when I added the cfg/ folder to my classpath path entry in eclipse and set the output directory in the build conf to the same class package the issue was resolved.
When you try this approach just make sure, the classpath conf file shows the classpath entry of the resource directory (eg. cfg/)
In maven, folder resources, create the same package structure where the configuration files are located and copy them there

How to read a directory in webapp folder of Maven web application

I'm working in maven web application. I need to read a directory(For ex: Files) in my webapp folder as follows,
Java.io.File file = new Java.io.File("path");
But I don't know how to specify the path of the directory here.
You shouldn't give local path addresses. Path should be a relative address, e.g. /files/images under your web archive (.war) folder.
To use relative paths properly, I suggest you to add your target folder to the resources definiton of POM.xml, check out these pages
http://www.mkyong.com/maven/how-to-change-maven-resources-folder-location/
http://maven.apache.org/guides/introduction/introduction-to-the-standard-directory-layout.html
You can refer to resources folder easily with something like this:
this.class.getResource("Mydirectory/SubDirectory");
When in doubt how relatives paths work, it's always best to do something like that:
System.out.println(new File("/my/desired/directory").getAbsolutePath());
This will print out the path in which classpath will look for the files.
Assuming:
servlet container webapps dir is located in: /var/lib/tomcat6/webapps
your webapp is called my-webapp.war
You should see the following output: /var/lib/tomcat6/webapps/my-webapp/my/desired/directory
Another pointer: you have mentioned that you are looking for webapp directory. I hope you know that this directory will not end up in *.war - it's contents will.
War files are not always expanded when they are deployed to an app server, so it's possible that a relative path won't exist in a filesystem at all.
Best bets are to use getResource from the class loader, which will return things in the class path (the WEB-INF/lib directory, etc), or to use the getResource() method of ServletContext to find things in the web application itself.

Loading context from within a Jar

I need some clarification; I have a jar that I built and inside of the jar it has a custom application-context.xml file that I need to load. I load the file within a class inside of the jar. When I am setting the url of this application-context.xml, is the directory specific to my jar's classpath, or still the project that is using the jar-'s classpath?
For example --
Jar's classpath:
src > main > META-INF > application-custom-context.xml
Project's classpath:
src > Libraries > myjar.jar > src > main > META-INF > application-custom-context.xml
I know these url's aren't accurate :P -- But, inside of my context creation, which directory structure would I follow. This is all theoretical. Somebody asked me this today, and I have no clue how to answer it. I would think that if you call a class from a jar, the classpath should be relative to the contents of that jar.. But, what I think is far from always right :)
The "path" to the Spring context is relative to the classpath. If the jar is included in your classpath (it's in web-inf/lib for example), then it would be treated just as if it was in your project (web-inf/classes).
In other words, if your context file is in "META-INF\spring\context.xml" inside your jar file, anyone who includes your jar file can reference it in the same manner.

What's the purpose of META-INF?

In Java, you often see a META-INF folder containing some meta files. What is the purpose of this folder and what can I put there?
From the official JAR File Specification (link goes to the Java 7 version, but the text hasn't changed since at least v1.3):
The META-INF directory
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/
This directory stores all the service provider configuration files.
New since Java 9 implementing JEP 238 are multi-release JARs. One will see a sub folder versions. This is a feature which allows to package classes which are meant for different Java version in one jar.
Generally speaking, you should not put anything into META-INF yourself. Instead, you should rely upon whatever you use to package up your JAR. This is one of the areas where I think Ant really excels: specifying JAR file manifest attributes. It's very easy to say something like:
<jar ...>
<manifest>
<attribute name="Main-Class" value="MyApplication"/>
</manifest>
</jar>
At least, I think that's easy... :-)
The point is that META-INF should be considered an internal Java meta directory. Don't mess with it! Any files you want to include with your JAR should be placed in some other sub-directory or at the root of the JAR itself.
I've noticed that some Java libraries have started using META-INF as a directory in which to include configuration files that should be packaged and included in the CLASSPATH along with JARs. For example, Spring allows you to import XML Files that are on the classpath using:
<import resource="classpath:/META-INF/cxf/cxf.xml" />
<import resource="classpath:/META-INF/cxf/cxf-extensions-*.xml" />
In this example, I'm quoting straight out of the Apache CXF User Guide. On a project I worked on in which we had to allow multiple levels of configuration via Spring, we followed this convention and put our configuration files in META-INF.
When I reflect on this decision, I don't know what exactly would be wrong with simply including the configuration files in a specific Java package, rather than in META-INF. But it seems to be an emerging de facto standard; either that, or an emerging anti-pattern :-)
The META-INF folder is the home for the MANIFEST.MF file. This file contains meta data about the contents of the JAR. For example, there is an entry called Main-Class that specifies the name of the Java class with the static main() for executable JAR files.
META-INF in Maven
In Maven the META-INF folder is understood because of the Standard Directory Layout, which by name convention package your project resources within JARs: any directories or files placed within the ${basedir}/src/main/resources directory are packaged into your JAR with the exact same structure starting at the base of the JAR.
The Folder ${basedir}/src/main/resources/META-INF usually contains .properties files while in the jar contains a generated MANIFEST.MF, pom.properties, the pom.xml, among other files. Also frameworks like Spring use classpath:/META-INF/resources/ to serve web resources.
For more information see How do I add resources to my Maven Project.
You can also place static resources in there.
In example:
META-INF/resources/button.jpg
and get them in web3.0-container via
http://localhost/myapp/button.jpg
> Read more
The /META-INF/MANIFEST.MF has a special meaning:
If you run a jar using java -jar myjar.jar org.myserver.MyMainClass you can move the main class definition into the jar so you can shrink the call into java -jar myjar.jar.
You can define Metainformations to packages if you use java.lang.Package.getPackage("org.myserver").getImplementationTitle().
You can reference digital certificates you like to use in Applet/Webstart mode.
Adding to the information here, the META-INF is a special folder which the ClassLoader treats differently from other folders in the jar.
Elements nested inside the META-INF folder are not mixed with the elements outside of it.
Think of it like another root. From the Enumerator<URL> ClassLoader#getSystemResources(String path) method et al perspective:
When the given path starts with "META-INF", the method searches for resources that are nested inside the META-INF folders of all the jars in the class path.
When the given path doesn't start with "META-INF", the method searches for resources in all the other folders (outside the META-INF) of all the jars and directories in the class path.
If you know about another folder name that the getSystemResources method treats specially, please comment about it.
Just to add to the information here, in case of a WAR file, the META-INF/MANIFEST.MF file provides the developer a facility to initiate a deploy time check by the container which ensures that the container can find all the classes your application depends on. This ensures that in case you missed a JAR, you don't have to wait till your application blows at runtime to realize that it's missing.
I have been thinking about this issue recently. There really doesn't seem to be any restriction on use of META-INF. There are certain strictures, of course, about the necessity of putting the manifest there, but there don't appear to be any prohibitions about putting other stuff there.
Why is this the case?
The cxf case may be legit. Here's another place where this non-standard is recommended to get around a nasty bug in JBoss-ws that prevents server-side validation against the schema of a wsdl.
http://community.jboss.org/message/570377#570377
But there really don't seem to be any standards, any thou-shalt-nots. Usually these things are very rigorously defined, but for some reason, it seems there are no standards here. Odd. It seems like META-INF has become a catchall place for any needed configuration that can't easily be handled some other way.
If you're using JPA1, you might have to drop a persistence.xml file in there which specifies the name of a persistence-unit you might want to use. A persistence-unit provides a convenient way of specifying a set of metadata files, and classes, and jars that contain all classes to be persisted in a grouping.
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
// ...
EntityManagerFactory emf =
Persistence.createEntityManagerFactory(persistenceUnitName);
See more here:
http://www.datanucleus.org/products/datanucleus/jpa/emf.html
All answers are correct. Meta-inf has many purposes. In addition, here is an example about using tomcat container.
Go to
Tomcat Doc and check
" Standard Implementation > copyXML " attribute.
Description is below.
Set to true if you want a context XML descriptor embedded inside the application (located at /META-INF/context.xml) to be copied to the owning Host's xmlBase when the application is deployed. On subsequent starts, the copied context XML descriptor will be used in preference to any context XML descriptor embedded inside the application even if the descriptor embedded inside the application is more recent. The flag's value defaults to false. Note if the deployXML attribute of the owning Host is false or if the copyXML attribute of the owning Host is true, this attribute will have no effect.
You have MANIFEST.MF file inside your META-INF folder. You can define optional or external dependencies that you must have access to.
Example:
Consider you have deployed your app and your container(at run time) found out that your app requires a newer version of a library which is not inside lib folder, in that case if you have defined the optional newer version in MANIFEST.MF then your app will refer to dependency from there (and will not crash).
Source: Head First Jsp & Servlet
As an addition the META-INF folder is now also used for multi-release jars. This is a feature which allows to package classes which are meant for different Java version in one jar, e.g. include a class for Java 11 with new features offered by Java 11 in a jar also working for Java 8, where a different class for Java 8 with less features in contained. E.g this can be useful if a newer Java version is offering enhanced, different or new API methods which would not work in earlier version due to API violations. One will see a sub folder versions then.

Categories

Resources