Migrating project to Servlet - properties file - servlets

I am migrating a project to a servlet.
I put the jars in the lib directory, the compiled classes in classes directory.
However, I have some files (properties, a wsdl file) that I am loading and reading in my application. For example this is how I am loading my properties:
try {
InputStream in = new BufferedInputStream(new FileInputStream("my.prop"));
myConfig.load(in);
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
Where do those files that I am loading go?

They usually go straight in the classpath so that you aren't dependent on the current working directory of the local disk file system. But you've got to change the way how you're getting an inputstream:
InputStream in = Thread.currentThread().getContextClassLoader().getResourceAsStream("my.prop");
See also:
Where to place and how to read configuration resource files in servlet based application?
getResourceAsStream() vs FileInputStream

Related

Vaadin Flow 14, Jetty embedded and static files

I'm trying to create app based on Jetty 9.4.20 (embedded) and Vaadin Flow 14.0.12.
It based on very nice project vaadin14-embedded-jetty.
I want to package app with one main-jar and all dependency libs must be in folder 'libs' near main-jar.
I remove maven-assembly-plugin, instead use maven-dependency-plugin and maven-jar-plugin. In maven-dependency-plugin i add section <execution>get-dependencies</execution> where i unpack directories META-INF/resources/,META-INF/services/ from Vaadin Flow libs to the result JAR.
In this case app work fine. But if i comment section <execution>get-dependencies</execution> then result package didn't contain that directories and app didn't work.
It just cannot give some static files from Vaadin Flow libs.
This error occurs only if i launch packaged app with ...
$ java -jar vaadin14-embedded-jetty-1.0-SNAPSHOT.jar
... but from Intellij Idea it launch correctly.
There was an opinion that is Jetty staring with wrong ClassLoader and cannot maintain requests to static files in Jar-libs.
The META-INF/services/ files MUST be maintained from the Jetty libs.
That's important for Jetty to use java.util.ServiceLoader.
If you are merging contents of JAR files into a single JAR file, that's called a "uber jar".
There are many techniques to do this, but if you are using maven-assembly-plugin or maven-dependency-plugin to build this "uber jar" then you will not be merging critical files that have the same name across multiple JAR files.
Consider using maven-shade-plugin and it's associated Resource Transformers to properly merge these files.
http://maven.apache.org/plugins/maven-shade-plugin/
http://maven.apache.org/plugins/maven-shade-plugin/examples/resource-transformers.html
The ServicesResourceTransformer is the one that merges META-INF/services/ files, use it.
As for static content, that works fine, but you have to setup your Base Resource properly.
Looking at your source, you do the following ...
final URI webRootUri = ManualJetty.class.getResource("/webapp/").toURI();
final WebAppContext context = new WebAppContext();
context.setBaseResource(Resource.newResource(webRootUri));
That won't work reliably in 100% of cases (as you have noticed when running in the IDE vs command line).
The Class.getResource(String) is only reliable if you lookup a file (not a directory).
Consider that the Jetty Project Embedded Cookbook recipes have techniques for this.
See:
WebAppContextFromClasspath.java
ResourceHandlerFromClasspath.java
DefaultServletFileServer.java
DefaultServletMultipleBases.java
XmlEnhancedServer.java
MultipartMimeUploadExample.java
Example:
// Figure out what path to serve content from
ClassLoader cl = ManualJetty.class.getClassLoader();
// We look for a file, as ClassLoader.getResource() is not
// designed to look for directories (we resolve the directory later)
URL f = cl.getResource("webapp/index.html");
if (f == null)
{
throw new RuntimeException("Unable to find resource directory");
}
// Resolve file to directory
URI webRootUri = f.toURI().resolve("./").normalize();
System.err.println("WebRoot is " + webRootUri);
WebAppContext context = new WebAppContext();
context.setBaseResource(Resource.newResource(webRootUri));

JavaFX jar doesnt read .properties file

I have developed a javafx application that reads the database configuration properties from a ".properties file".When i run the app in eclipse everything works fine.The problem is when running the app from the generated executable jar,it throws me a NullPointerException because it cant read the ".properties file".
The code is :
FileInputStream fis=new FileInputStream("resources/META-INF/db/db.properties");
Properties properties = new Properties();
properties.load(fis);
I searched about this and i saw some examples of using InputStream :
Properties pp = new Properties();
InputStream is = getClass().getClassLoader().getResourceAsStream("errors.properties");
pp.load(is);
But still doesnt work.Any idea?strong text
Try creating a folder that you always have with you Jar. The folder name should be resources. This folder should have a folder named META-INF. META-INF should have a folder named db. Finally, db should have the db.properties file in it.

How to rename a jar file inside another jar file?

I have jar foo.jar which contains jar foo/config/baar-temp.jar.
What is the best method to rename baar-temp.jar to baar.jar?
Actually, jar format is based on zip and can be operated on as a file system using for example ZipFileSystemProvider available in Java7. That allows us to do a rather simple manipulation with the insides of one:
private void renameStuffInsideJar(String jarFilePath){
URI uri = URI.create("jar:file:"+jarFilePath);
try {
FileSystem jarFile = FileSystems.getFileSystem(uri)) {
Path pathInJarfile = jarFile.getPath("foo/config/baar-temp.jar");
Files.move(pathInZipfile,pathInZipfile.resolveSibling("baar.jar"));
} catch(IOException e){
//TODO
}
}
Alternatively, if it's not code you want, you could just open your jar file in your preferred archive manager like 7zip or WinRar and rename it using that.

How to load a MANIFEST.MF file into a JAR properly?

I don't want to create a 'default manifest file', I just want to load the Manifest file(which I already created as per my requirements) into the JAR as it is. I used the command JAR uf, the MANIFEST.MF is not even loaded into the JAR. And then I tried JAR cvf, the MANIFEST.MF file was loaded with modified data(probably default manifest). What is the correct command to load MANIFEST.MF file into a JAR?
Also, the other files in JAR are .xml, .data, .properties which are all loaded successfully.
For Jar:
JarInputStream jarStream = new JarInputStream(stream);
Manifest mf = jarStream.getManifest();
From servlet its possible to use also:
try(InputStream in = servletContext.getResourceAsStream("/META-INF/MANIFEST.MF")) {
return ....;
} catch (IOException e) {
throw Throwables.propagate(e);
}

log4j configuration in jar which is used by another application already using log4j

My problem is that i'm trying to set up log4j to log into a file from my jar. This jar is used by an application which already uses log4j. My jar is made as maven package shipped with log4j. I'm trying to initialize log4j from property file as such:
"log4j.properties"
log4j.appender.FileAppender=org.apache.log4j.RollingFileAppender
log4j.appender.FileAppender.File=${user.home}/.myproject/myproject.log
log4j.appender.FileAppender.layout=org.apache.log4j.PatternLayout
log4j.appender.FileAppender.layout.ConversionPattern=%d{yy-MM-dd HH:MM:ss,SSS} [%t] %-5p %c %x - %m%n
log4j.appender.FileAppender.MaxFileSize=5MB
#myproject is full package name
log4j.logger.myproject=,FileAppender
I've included this property file into resources of my jar. I'm loading it with code:
try {
InputStream inputStream = this.getClass().getClassLoader()
.getResourceAsStream("log4j.properties");
Properties properties = new Properties();
properties.load(inputStream);
inputStream.close();
PropertyConfigurator.configure(properties);
} catch (NullPointerException e) {
BasicConfigurator.configure();
throw new MyprojectException("log4j.properties not found", e);
} catch (IOException e) {
throw new MyprojectException("log4j.properties could not be loaded", e);
}
This code is working flawlessly when my jar is not used by an application which uses log4j. But it is, i get an empty log file or for some cases in some applications, no log file is created at all.
I've tried to add an appender manually, not with propertyconfigurator like this:
static org.apache.log4j.Logger logger = org.apache.log4j.Logger.getLogger(Myproject.class);
SimpleLayout layout = new SimpleLayout();
FileAppender appender = new FileAppender(layout,"C:/out.log",true);
logger.addAppender(appender);
logger.setLevel(Level.DEBUG);
This seems to be working fine, but i'd really want to configure log4j from properties file instead.
I've read lots of threads about how log4j handles multiple instances. I've found out that i cannot alter log4j configuration loaded by properties once it's done by one application. Some have suggested i shall ship my own log4j jar and config and configure with propertyconfigurator, that's what i've tried and as you can see it didn't work. I'm curious why my second example is working and the first is not. How can i solve this problem?
notes:
I do not want to alter the log4jconfigs of the applications that use my jar file.
I've also found out that there is -Dlog4j.configuration system property that could be used, but my jar is not an executeable jar file, it gets loaded by Class.forName
Any help is appreciated,
Thanks in advance

Resources