Web application build process: Keep config files in WEB-INF/classes? - java

Some projects, as part of their build process, clean up the classes folder in WEB-INF, while others keep some of their config files in the classes folder. The latter group might use a temporary folder somewhere else to build their project and then copy the generated class files from this temporary folder to the WEB-INF/classes, thus keeping their config files safe.
Is there any best practice regarding web application builds about this? I use ant.

User-accessible config files are better stored outside of /classes, e.g. in /WEB-INF/config. I differentiate config files that site admins can touch (they are placed under WEB-INF) and those, kind of 'static' ones, that are meant for developers/deployment configurators only (stuff like sql scripts, XML/XSLT templates, i18n etc).
It is preferred practice to clean up WEB-INF/classes during builds - some classes get deleted/renamed, so are resource files.
Other config files, under WEB-INF, but not in /classes or /lib, have to be treated as upgradable resources: either replace old ones only when there is a new one, or use specifically designed upgrade classes to add missing config tags or lines.
There are tricky situations, like log4j.properties is sometimes stored into /classes root. It is a bit of a different story how to properly handle it, but in most instances it falls under "delete all classes and copy everything anew".

Related

Supplying resources outside JAR

A lot of manuals say that canonical way to store resources is under resources folder in a project. The problem is that after assembling a project all of the resources are getting inside JAR. In my case resources are SQL scripts and I would like avoid assembling a new JAR if any SQL script changes. So I wish to supply resources in addition to JAR file. It will be tricky to access those files using typical methods for resources so the only way I can think of is considering them just as regular files in the file system (not resources as such).
Is is the right way to move forward? What are the possible alternative solutions.
It's possible to use SQL scripts as resources and ship them in a separate folder instead of JAR but probably it does not make sense. Since in such case it's much more reasonable to siply use files in the file system.
If, however, someone wants to do this trick then you need to
Add that folder into CP so that you can access files as resources
https://www.scala-sbt.org/1.x/docs/Classpaths.html
https://docs.huihoo.com/sbt/0.12.4/Detailed-Topics/Classpaths.html
Exclude resources from JAR
sbt-assembly: How do I exclude the configuration files in src/main/resources

Preferred File Location for Static Files in Maven WAR Project

I am trying to access some WSDLs and XMLs files from WebApp which i built in Maven as a WAR. Now I knew that the resources folder was the default location for these types of files, but when I checked the war package, I found that the files ended up inside the /WEB-INF folder, which is of not much use. Just wanted to know where do I put these files so that I can access them via URL:
https://server:port/Context/File_Path
I tried to make a folder inside webapp but outside WEB-INF, it did seem to do the trick. But just wanted to know if that the right approach.
Maven has a concept of standard directory layout
So, yes, in order to work with something that can be packaged into WAR with maven-war-plugin you should follow the convention and place the files into the relevant folders (of course you can change these defaults if you wish).
When it comes to the static resources, indeed there is a special src/main/webapp folder. So you're right

How to configure a maven webapp project to have the same structure that we have in the source code?

When we deploy an application to an application server like Wildfly, Tomcat, etc, it puts all of our source code on a folder named classes inside the WEB-INF folder.
Using Eclipse, we can change this folder destination on the Deployment Assembly menu, inside the project properties menu.
But I would like to do an configuration to use the same structure that we have in the real project (not in the deployed one). For example, on a maven project, we have an structure like
myproject/src/main/java/com/mydomain/myproject/model/controller/mb/IndexMB.java
So, how can we have a structure like
myproject.war/WEB-INF/src/main/java/com/mydomain/myproject/controller/mb/IndexMB.class
in the deployed project?
Looks like the files destination could be achieved changing the destinations on the Deployment Assembly menu, but unfortunally the managed bean could not be instantied or called.
How can we perform this?
Motivations
Or OCDs =)
I'm creating a class, named Router, that will be very important and essential to the system. This class will provide the routes for all system folders and packages. I will use this class to configure database connections, log4j, prettyfaces, and so on. So, for example, if I put the log4j.properties file in src/main/resource/configuration/logger/log4j.properties, I will use the Router class like new File(Router.getInstance().get('src.main.resource'),'configuration/logger/log4j.properties'). This class will be essential and a workaround could be done, to find the files even on a deployed or non-deployed system, but keep the things with the same hierarchy would be awesome.
I would like to keep the things organized and I would like to control where each created file will be put and find a way to use it programatically, if needed. Just put all files on the root folder (even on the non deployed version) looks very messy to me. For example put the log4j.properties in the root, etc.
Change the default behavior. If I have a source folder, that not contains java classes, like images, properties files, json files; these aren't classes, so, these should not be in the classes folder. I think the best way is to configure to each file to be deployed on a proper folder and the system learns how to get and operate with it.
The Router class will be used on application servers (that see the deployed folders) and in java applications and junit tests, so keep it together will be prefereable.

How are dependencies in multiple log4j.properties files managed under Maven?

I have a maven project with several dependencies and use log4j.properties to control output. In some cases the same class may be referenced in different property files with different parameters. Is there a defined protocol for "overriding" properties or does it depend on the order in which packages are loaded?
(I am locating all log4j.properties directly under src/main/resources - is this the correct place?)
UPDATE:
I have accepted #Assen's answer as it makes sense though it doesn't make the solution easy. Essentially he recommends excluding log4j.properties from the jar. In principle I agree, but it puts the burden on the user to control the output and most of my users don't know what Java is, let alone properties files.
Maybe there is a way of renaming the properties files in each jar and using a switch (maybe with -D) to activates the properties.
I often have similar discussions on projects. I thing log4j.properties is typically something you want to keep out of the application, and not pack it in a war and deliver it together with the code. Logging configuration:
is environment specific. When you write the application, you simply can't define the appenders that will be desired, file locations etc.
its lifecycle is totally different than the application's. After an application is deployed, logging properties can be changed several times a day. Redeploying the application shouldn't override your last logging settings.
Why package logging configuration together with your code then? I usually keep somewhere a configuration folder, with soubfolders like 'dev', 'test-server-01', 'macbook-john' etc. Each subfolder contains list own copy of log4j.properties. None of them is included in the build artifact - jar or war.
When deploying, one of thuse subfolders is delivered separately. For the test server 1, this would be the content of test-server-01 subfolder. Dependng on the application server used, thers is a different trick tu put some files on the classpath.
When developing, I take care to set one of those subfolders on the path. When John develops on his macbook, he might want to put 'macbook-jihn' on the classpath, or create a new one. He can change logging settings and commit without conflicts.

Java distribuion as jar file containg config, libs and deps

I am developing a framework that needs a lot of stuff to get working. I have several folders inside of my Eclipse project that are needed
[root]
- config
- src
- lib
- serialized
Also there are important files like the log4j.properties and the META-INF dir inside the src directory.
I wonder if there is a way to distribute one JAR containing all essential files so my gui will just have to import one jar. I guess that I have to exclude the config folder in order to make the framework configurable.
I also wonder, if there is a way to move for example the log4j.properties to the config dir so that I have one config folder containg all needed configurations?
Thanks for help and advise on this matter!
Marco
Yes, but not really. You can take all your dependencies, unpack them and simply merge them into a bigger jar. This is what the maven jar plugin does if you make a jar with dependencies. The only problem is that this might result in conflicting files (suppose two of your dependencies contain a log4j.properties). This is one of the problems when doing the above with some of the spring libraries for instance.
I think someone actually wrote a classloader that allows you to bundle the whole jar inside of your jar and use it as is. I'm not sure how mature that is though and can't at the moment recall the name.
I think you're better off distributing all your dependencies separately. Setting up the classpath is a bit of a pain but surely java programmers are used to it by now. You can add dependencies to the Class-Path header in your manifest file, in simple cases. Bigger libraries have to rely on the classpath being set up for them though.
As to the second part of your question, probably dropping the conf/ directory under META-INF is enough for its contents to be picked up. I'm not sure about this. I'm fairly sure it will always be picked up if you put its contents at the top level of the jar. In any case, this is a distribution problem. You can easily have a conf/ directory inside your source tree and have your build scripts (whatever you might be using) copy the files in it to wherever is most convenient.
As to your users configuring. Try to establish some conventions so they have to configure as little as possible. For things that must be configured, it's best to have a basic default configuration and then allow the user to override and add options through his/her own configuration file.
In terms of the resources, it is possible except that if you do that you are not going to be able to load resources (non class files) from the filesystem (via a file path).
It's likely that you're currently loading these resources from the file system. Once in the jar you need to load them as class path resources via the class.getResourceAsStream or similar.
As for the dependent jars you may have, it's common practice for these to be placed as extra jars on the classpath. I know it's complicates things but developers are used to doing this. The nature of the java landscape is that this is inevitable. What the spring framework for example does is supply a bundled zip file with the core jar and the jar dependencies included.
Is your library going to be used in an EE context or an SE context? If it is an EE context then you really don't have to worry about configuration and class path issues as the container takes care of that. In an SE context it is a lot more tricky as that work has to be done manually.

Categories