Supplying resources outside JAR - java

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

Related

What's the most conventional folder for outputting resources if you need them strictly within build target?

We all know "inputable" resources are by convention in src/main/resources and src/test/resources, but what about the runtime outputted ones? Is it better to use target/ or target/{classes,test-classes}or simply give up and try to use external path even if it complicates things for security reasons? I've been brainstorming a bit regarding that decission as shown following, but need the help of more experienced users that can shed more light.
PROS of target/{classes, test-classes}
If maven engineers architected the convention by moving resources to target/classes instead of target/resources I assume they had a good reason in mind for preferring it
It organizes input and output resources on the same base folder
It makes test and main outputs independent, so no conflict can appear if names are equal
IT makes much conventional and secure to define the relative route of the resource ( by ClassLoadeR().getResource() or etProtectionDomain().getCodeSource().getLocation() [no file globs]
It makes much easy to centralize output behavior, in case our idea is having a function for UPSERTing resources, we need to use resolution for sufolder as they are not in the same path (so prepend /classes/ to the relative route but / for an original resource)
I think due to the previous ones, there can be a bit of confusion when using parent poms, because there is a target for both parent and module, but only one classloader URL -> /target/classes
It works flawlessly if using the classes directory as the base classpath of the app, when executing directly from console.
PROS of target/
When packaging the app as a library, you don't need to deal with an output folder inside the jar.
I have been told that maven doesn't like too much anything strictly outside of target/, but have no further info
A central folder can be used when executing tests in case production code generates files and tests works with them also
Perhaps a single target at parnet pom's level makes files easier to share among different modules
So how do you usually handle these sort if things?
I am sure some of you have a more authoritative question
So typically if you are allowing resources to be pulled in from outside of your Jar you need to either hard-code that relative path or read it from fixed config file. You would then document this when you release your application.
For example, Eclipse has a folder specially for plugins. You can drop new plugins here and know that Eclipse will pick them up and know what to do with them.
In my applications, I usually define a conf directory that sits at the same level as the executable Jar. I'll put any log4j and other such post-compile config files there.
You mention security issues, which is a good thing to think about. When you are pulling in data, always try to do some sort of sanity checking (make sure a directory exists, a zip file isn't corrupt, etc). Since you can't control what comes in, make sure you do as many checks as you can on the program side.

Properly deploying a small Java project

I'm currently working on a small Java Project (~30 Classes, 5 external libs).
The code accesses resources in the folders src/resources and src/test_resources using getClass.getResouce("/resources/any.file").
Most of these resource files will probably never be touched by a user, but there are also some regular configuration files which are intended to be edited by the end users.
My question now is: How should I be deploying such an application?
Exporting everything into a runnable jar doesn't seem to be a good way, as I don't wanna torture my users and let them unzip the jar for editing the configuration files.
Should I export all of the internal stuff into the jar, and copy the resources directory into a Folder side by side with it? How can I access the resources then?
Thank you guys!
You could copy the resources folder. It doesn't necessarily need to be side-by-side with the jar file. The key is that you need to put the parent folder of the resources folder on the classpath.
For example, you could copy it someplace like:
c:\some\directory\resources
Then, when you execute, do something like:
java -cp c:\some\directory;c:\some\path\to\your.jar;... your.main.ClassName

When creating a java web application, are there benefits to having one's code inside a jar vs. inside the classes folder?

In a web-app it is possible to have code in two places:
WEB-INF/lib
WEB-INF/classes
In the lib folder, code has to be packaged as a jar file whereas in the classes folder, code is in a folder structure that matches the package structure.
Are there any benefits to putting one's own code as a jar in WEB-INF/lib vs putting it as classes in WEB-INF/classes?
No, there is no benefit. There even are drawbacks:
creating the jar is one more task to do in your build
most (all?) of the app servers place the classes directory (or allow placing it) before the jars in the webapp's classpath. So placing your classes and resources there makes sure they are loaded in preference to a similar class or resources located in a jar of WEB-INF/lib.
JARs only exist to make it easier to move entire applications from one place to another.
That's very poor idea to paste your own classes inside a Jar unless you want to move/supply your code somewhere. Otherwise keep it as it is(WEB-INF/classes). That saves your time and it is standard recommendation.
Remember the other thing that each time you clean your project, new class files generates.

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

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".

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