Overriding WAR classes directory - java

If you use the Ant to create your WAR via the war task, then (as explained here) it will automatically create a WEB_INF/classes/ directory in the WAR. I would like to change the name of this generated classes/ directory to, say, classpath/ and can't figure out how.
If this is possible, would someone provide a code example as well as a reference to the documentation that shows how to do this (I'm curious!). Thanks!

You shouldn't change the name of the classes to something else.
The directory structure of a WAR file is standard and defines a WEB-INF\classes for all the .class files of your application

Related

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 import a file in a jar?

I have this project that it has this structure
Home
graphics
field.txt
example.java
I need to load field.txt in my example.java in jar and I use:
getClass().getClassLoader().getResource("field.txt").toUri();
but this code it give me "Null Pointer exception" .Anyone can help me?
example.class.getResource(“/graphics/field.txt“);
The class should belong to the same jar. For Class.getResource a relative “field.txt“ is possible (same package). With ClassLoader an absolute path for all classpaths is sought: “graphics/field.txt“.
To immediately read (never write) use getResourceAsStream or the URI of the getResource. One can use a Path on the URI. Files.copy(...).
One cannot at least should not) write a resource file (as it can reside in a jar jar:file://...; and jar might even be sealed; and resources might be cached by the jvm). Keep it as read-only template. Never File.
One technique is to create an application named directory in System.getProperty("user.home") and copy the template there.
To read the file it must be in classpath, you can put the file in the folder containing .class files or add it to the classpath with java -cp option.
The issue is not so much your code, but how you build and package your jar file. You will have to clarify how you are currently building your jar (using ant, maven, eclipse, etc ?).
Many articles will also advise you to separate out your resources from your source code (.java), and many IDE will support this separation direclty by allowing you to mark a folder as a resource folder. Even maven will allow you to customize this.
See following articles:
How to package resources in Jar properly
Using maven and netbeans, it is real simple: https://coderwall.com/p/d_cvrq/how-to-package-non-java-code-files-resources-in-a-jar-with-maven, or
use maven to pack javascript files in Jar?

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

Tomcat - won't load my META-INF\services\javax.servlet.ServletContainerInitializer file?

I have a web project that has a \META-INF\services\javax.servlet.ServletContainerInitializer file with its content pointing to the fully qualified name of a class that implements the ServletContainerInitializer interface. I basically followed the example given here: http://nullhaus.com/2011/03/using-servlets-3-0-servletcontainerinitializer/
I put debug lines in my class that implements the ServletContainerInitializer interface and it never makes it there. Not even the default constructor...
My application folder structure is as follows:
\MyApp
\META-INF\services\javax.servlet.ServletContainerInitializer
\WEB-INF\classes\
... [list of classes and packages go here]
Any ideas what I need to check for??
Note 1: My Tomcat publishes from an exploded external folder that contains my application
Note 2: I started my Tomcat from Eclipse - if that makes a difference!
Well, I think that you'll need to wrap your initializer class (and it's services-related META-INF directory) into a separate *.jar and put it in the WEB-INF/lib.
This is a JAR service, so I guess it could have something to do with problems with discovering services in a *.war file. Moreover, it doesn't even help if you put your META-INF directory inside WEB-INF/classes and set unpackWAR=false in your Tomcat's server.xml.
HTH.
The first thing to check is that you are actually using Servlet 3.0 and not an earlier version. For Tomcat, this means that you must be using Tomcat 7.0.22
Second, make sure that the \META-INF\services\javax.servlet.ServletContainerInitializer file actually exists in the exploded war file.
Third, when in doubt, configure and start Tomcat directly (not from Eclipse) - I've seen developers have endless problems with configuration of Tomcat using the Eclipse plugin.
For tomcat to load the META-INF directory , it has to be in classes folder . If you are using maven project , just put the META-INF directory inside src/main/resources directory .. on mvn package the same will be copied to classes directory .. No need of separerate jar .. if jar is prefered you can use
HandlesTypes annotation ..
I would like to quote some good explanation from Mark Thomas <markt#apache.org> given on the user mailing list of Tomcat:
Service files are loaded by class loaders from the META-INF/services
directory.
*.jar!/META-INF/services
and
*.war/WEB-INF/classes/META-INF/services
are visible to class loaders
*.war!/META-INF/services
is not.
The servlet expert group recently discussed WAR vs JAR in the context of
Java 9 and mutli-version JARs. The conclusion was (I'm paraphrasing)
that WARs are not a specialised form of JAR and while they share a
common format a feature that is available to a JAR is NOT automatically
available to a WAR unless the Servlet spec (of Java EE spec) explicitly
states otherwise.
Containers are free to add container specific extensions if they wish
but they come with the usual (lack of) interoperability warnings.
http://mail-archives.apache.org/mod_mbox/tomcat-users/201808.mbox/

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