How I can specify directories in war file? - java

I am new to servlet . I use the following code in servlet.then deployed to Jboss 4.1 . backup_database_configuration_location is location of properties file.But it can't be find. how I can specify directories in war file ?
Thanks all in advance
try {
backupDatabaseConfiguration = new Properties();
FileInputStream backupDatabaseConfigurationfile = new FileInputStream(backup_database_configuration_location));
backupDatabaseConfiguration.load(backupDatabaseConfigurationfile);
backupDatabaseConfigurationfile.close();
} catch (Exception e) {
log.error("Exception while loading backup databse configuration ", e);
throw new ServletException(e);
}

If it is placed in the webcontent, then use ServletContext#getResourceAsStream():
InputStream input = getServletContext().getResourceAsStream("/WEB-INF/file.properties"));
The getServletContext() method is inherited from HttpServlet. Just call it as-is inside servlet.
If it is placed in the classpath, then use ClassLoader#getResourceAsStream():
InputStream input = Thread.currentThread().getContextClassLoader().getResourceAsStream("file.properties");
The difference with Class#getResourceAsStream() is that you're not dependent on the classloader which loaded the class (which might be a different one than the thread is using, if the class is actually for example an utility class packaged in a JAR and the particular classloader might not have access to certain classpath paths).

Where is your properties file located? Is it directly somewhere in your hard drive, or packaged in a JAR file?
You can try to retrieve the file using the getResourceAsStream() method:
configuration = new Properties();
configuration.load(MyClass.class.getResourceAsStream(backup_database_configuration_location));
(or course, replace MyClass by your current class name)

Related

Deployed WAR can't access a file

I have a spring application, and i'm trying to access a json file with the following code :
try (FileReader reader = new FileReader("parameters.json")) {
Object obj = jsonParser.parse(reader);
parameterList = (JSONArray) obj;
}
I have put the parameter.json file in the project folder and I'm accesing the file data from an angular app through a rest api, and that works fine when I run the application on local machine, but when I deploy the war file on tomcat, my application can't load the file, should I put parameter.json file somewhere else on tomcat or what is the best solution for it.
Your question states you are attempting to access a file called parameter.json, while your code excerpt shows parameters.json. Perhaps that discrepancy indicates a typo in your source code?
If not, there are various ways to access a file from the classpath in Spring, with the first step for each being to ensure the file is in the project's src/main/resources directory.
You can then use one of the Spring utility classes ClassPathResource, ResourceLoader or ResourceUtils to get to the file. The easiest approach, though, may be to put your properties in a .properties file (default file name application.properties) and access the values using Spring's #Value annotation:
#Value("${some.value.in.the.file}")
private String myValue;
You can use other file names as well by utilizing #PropertySource:
#Configuration
#PropertySource(value = {"classpath:application.properties",
"classpath:other.properties"})
public class MyClass {
#Value("${some.value.in.the.file}")
private String myValue;
...
}
Make sure your parameters.josn filename is exactly same in the code.
Move you parameters.json file in the resources folder and then use the classpath with the filename.
try (FileReader reader = new FileReader("classpath:parameters.json")) {
Object obj = jsonParser.parse(reader);
parameterList = (JSONArray) obj;
}
Try to put the file under resources folder in your spring project. You should be able to access the file from that location.
FileReader is looking for a full-fledged file system like the one on your computer, but when your WAR is deployed, there just isn't one, so you have to use a different approach. You can grab your file directly from your src/main/resources folder like this
InputStream inputStream = getClass().getResourceAsStream("/parameters.json");

Java: Getting resource path of the main app instead of jar's

A lot has been discussed already here about getting a resource.
If there is already a solution - please point me to it because I couldn't find.
I have a program which uses several jars.
To one of the jars I added a properties file under main/resources folder.
I've added the following method to the jar project in order to to read it:
public void loadAppPropertiesFile() {
try {
Properties prop = new Properties();
ClassLoader loader = Thread.currentThread().getContextClassLoader();
String resourcePath = this.getClass().getClassLoader().getResource("").getPath();
InputStream stream = loader.getResourceAsStream(resourcePath + "\\entities.properties");
prop.load(stream);
String default_ssl = prop.getProperty("default_ssl");
}catch (Exception e){
}
}
The problem (?) is that resourcePath gives me a path to the target\test-clasess but under the calling application directory although the loading code exists in the jar!
This the jar content:
The jar is added to the main project by maven dependency.
How can I overcome this state and read the jar resource file?
Thanks!
I would suggest using the classloader used to load the class, not the context classloader.
Then, you have two options to get at a resource at the root of the jar file:
Use Class.getResourceAsStream, passing in an absolute path (leading /)
Use ClassLoader.getResourceAsStream, passing in a relative path (just "entities.properties")
So either of:
InputStream stream = getClass().getResourceAsStream("/entities.properties");
InputStream stream = getClass().getClassLoader().getResourceAsStream("entities.properties");
Personally I'd use the first option as it's briefer and just as clear.
Can you try this:
InputStream stream = getClass().getClassLoader().getResourceAsStream("entities.properties")

Java load jar files from directory

I currently develop an open-source project where people may add their own .jar to extend the included features. However, I'm stuck with how to load the classes in the jar.
I have an abstract class which has an abstract method onEnable() and some getter that provides some objects to work with the application. The plugin needs the subclass my plugin-class BasePlugin. The jar should be added to /plugins and thus I want all *.jar files in the /plugins folder to be loaded when the application starts.
The problem I'm running to now is that, of all the approaches I found, I need to declare a classpath of the classes in the jar file, which I do not know. Neither do I know the name of the jar file. Thus, I need to scan the /plugins folder for any *.jar file and load the corresponding class inside the jar which implements BasePlugin and invoke the onEnable() method.
The basic idea is too...
Read all the files in a specific directory
Convert the File reference to a URL for each result
Use a URLClassLoader, seeded with the URL results to load each result
Use URLClassLoader#findResources to find all the match resources with a specific name
Iterate over the matching resources and load each one, which should give, at least, the "entry point" class name
Load the class specified by the "entry point" property
For example...
public List<PluginClass> loadPlugins() throws MalformedURLException, IOException, ClassNotFoundException {
File plugins[] = new File("./Plugins").listFiles(new FileFilter() {
#Override
public boolean accept(File file) {
return file.getName().endsWith(".jar");
}
});
List<URL> plugInURLs = new ArrayList<>(plugins.length);
for (File plugin : plugins) {
plugInURLs.add(plugin.toURI().toURL());
}
URLClassLoader loader = new URLClassLoader(plugInURLs.toArray(new URL[0]));
Enumeration<URL> resources = loader.findResources("/META-INFO/Plugin.properties");
List<PluginClass> classes = new ArrayList<>(plugInURLs.size());
while (resources.hasMoreElements()) {
URL resource = resources.nextElement();
Properties properties = new Properties();
try (InputStream is = resource.openStream()) {
properties.load(is);
String className = properties.getProperty("enrty-point");
PluginClass pluginClass = loader.loadClass(className);
classes.add(pluginClass);
}
}
return classes
}
nb: I've not run this, but this is the "basic
SpigotMC uses JAR files as plugins as well, inside the jar is a plugin.yaml file that stores extra information about the plugin including the classpath. You don't need to use a YAML file, instead you could use something like JSON or even a plain text file.
The YAML file is inside the jar and can be accessed by using some of the methods explained here. You can then get the classpath property and then load the jar using the methods explained here. Extra information can be stored about the plugin such as the name, version, and dependencies.
Java already has a class for this: ServiceLoader.
The ServiceLoader class was introduced with Java 6, but the “SPI jar” concept is actually as old as Java 1.3. The idea is that each jar contains a short text file that describes its implementations of a particular service provider interface.
For instance, if a .jar file contains two subclasses of BasePlugin named FooPlugin and BarPlugin, the .jar file would also contain the following entry:
META-INF/services/com.example.BasePlugin
And that jar entry would be a text file, containing the following lines:
com.myplugins.FooPlugin
com.myplugins.BarPlugin
Your project would scan for the plugins by creating a ClassLoader that reads from the plugins directory:
Collection<URL> urlList = new ArrayList<>();
Path pluginsDir = Paths.get(
System.getProperty("user.home"), "plugins");
try (DirectoryStream<Path> jars =
Files.newDirectoryStream(pluginsDir, "*.jar")) {
for (Path jar : jars) {
urlList.add(jar.toUri().toURL());
}
}
URL[] urls = urlList.toArray(new URL[0]);
ClassLoader pluginClassLoader = new URLClassLoader(urls,
BasePlugin.class.getClassLoader());
ServiceLoader<BasePlugin> plugins =
ServiceLoader.load(BasePlugin.class, pluginClassLoader);
for (BasePlugin plugin : plugins) {
plugin.onEnable();
// etc.
}
An additional advantage of using ServiceLoader is that your code will be capable of working with modules, a more complete form of code encapsulation introduced with Java 9 which offers increased security.
There is an example here it may be helpful. Also, you should take a look at OSGi.

Get resources from a jar file

i want my jar file to access some files from itself. I know how to do this for BufferedImage but this doesn't work for other files. All i want is to extract some zips from my jar. i made a class folder in eclipse, put the zips inside and used
public File getResFile(String name){
return new File(getClass().getResource(name).getFile());
}
to get the File instance and extract it. it works fine in eclipse, but as soon as i export it to a jar it says
Exception in thread "main" java.io.FileNotFoundException: file:\C:\Users\DeLL\Desktop\BoxcraftClient\ClientInstaller.jar!\client.bxc (The filename, directory name, or volume label syntax is incorrect)
at java.util.zip.ZipFile.open(Native Method)
at java.util.zip.ZipFile.<init>(ZipFile.java:220)
at java.util.zip.ZipFile.<init>(ZipFile.java:150)
at java.util.zip.ZipFile.<init>(ZipFile.java:164)
at Launcher.install(Launcher.java:43)
at Launcher.main(Launcher.java:33)
Im working to fix this already something like 6 hours and can't find a solution. Please help!
There is a reason why getResource() returns a URL, and not a File, because the resource may not be a file, and since your code is packaged in the Jar file, it's not a file but a zip entry.
The only safe way to read the content of the resource, is as an InputStream, either by calling getResourceAsStream() or by calling openStream() on the returned URL.
first check your class path using java System.out.println("classpath is: " + System.getProperty("java.class.path")); to see if the classpath has your jar file.
And then use the getclass().classloader.getResourceAsStream(name). See if the returned URL is correct. Call the method isFile() on the URL to check if the URL is actually a file. And then call the getFile() method.
Use one of these methods, from the class Class
- getResource(java.lang.String)
- getResourceAsStream(java.lang.String)
this.getClass().getResource(name);
this.getClass().getResourceAsStream(name);
Warning: By default it loads the file from the location, where the this.class, is found in the package. So if using it from a class org.organisation.project.App, then the file need to be inside the jar in the directory org/organisation/project. In case the file is located in the root, or some other directory, inside the jar, use the /, in from of the file name. Like /data/names.json.
Use Spring's PathMatchingResourcePatternResolver;
It will do the trick for both launching the package from an IDE or from the file system:
public List<String> getAllClassesInRunningJar() throws Exception {
try {
List<String> list = new ArrayList<String>();
// Get all the classes inside the package com.my.package:
// This will do the work for both launching the package from an IDE or from the file system:
String scannedPackage = "com.my.package.*";
// This is spring - org.springframework.core; use these imports:
// import org.springframework.core.io.Resource;
// import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
PathMatchingResourcePatternResolver scanner = new PathMatchingResourcePatternResolver();
Resource[] resources = scanner.getResources(scannedPackage.replace(".", "/"));
for (Resource resource : resources)
list.add(resource.getURI().toString());
return list ;
} catch (Exception e) {
throw new Exception("Failed to get the classes: " + e.getMessage(), e);
}
}

How do I access a config file inside the jar?

I'm using FlatPack to parse and load data from flat files. This requires loading a config file that stores mappings of the columns of the flat file.
I have a constant to define the location of the mapping file:
private static final String MAPPING_FILE = "src/com/company/config/Maping.pzmap.xml";
I have a parse(File dataFile) method that actually does the parsing:
private void parse(File dataFile) throws FileNotFoundException, SQLException {
Parser parser;
log.info("Parsing " + dataFile.getName());
FileReader mappingFileReader = new FileReader(MAPPING_FILE);
FileReader dataFileReader = new FileReader(dataFile);
parser = DefaultParserFactory.getInstance().newFixedLengthParser(mappingFileReader, dataFileReader);
parser.setHandlingShortLines(true);
DataSet dataSet = parser.parse();
//process the data
}
When I jar up everything and run it as a jar - it bombs out on FileReader mappingFileReader = new FileReader(MAPPING_FILE); with a FileNotFoundException. That file is inside the jar though.
How do I get to it?
I've looked at this question and this question about accessing files inside jars and they both recommend temporarily extracting the file. I don't want to do that though.
if it's inside a JAR, it's not a File, generally speaking. You should load the data using Class.getResourceAsStream(String), or something similar.
I think it is solved just here:
http://www.velocityreviews.com/forums/t129474-beginner-question-how-to-access-an-xml-file-inside-a-jar-without-extracting-it.html
If I remember correctly, getResourceAsStream() can behave differently depending on which web server your webapp is deployed, for instance I think it can be a problem when deployed as a war on a Websphere instance. But I'm not sure if this applies to you.
But I'm not sure you're trying to solve the "proper" problem : if it's a config file, that means is data dependant right ? Not code dependant ( your jar ) ? When the flat file will change, your config file will need to change as well, right ? If this is true, it sounds like the config should be better stored elsewhere, or even passed as a parameter to your jar.
But maybe I haven't fully understood your problem...
Use Apache Commons Configuration, then you can read/write XML, auto update, find config file in path or jar, without a lot of hassles.
Below code works for me:
Imports:
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
Code:
Properties properties = new Properties();
InputStream in = MyCLassName.class.getClassLoader().getResourceAsStream(configFilePath); //pass the config.properties file path with file name
try {
properties.load(in);
properties.getProperty("username"); //here put the key from config.properties
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

Categories

Resources