I am using maven for my spring boot application(1.5 version). There are some files in src/main/resources like abc.properties, app.json. Below are some pointer what i want to achieve.
Exclude these files getting into the jar.
When i run my application through intellij these files should be available in classpath.
I looked at related answers on SO but none matches my case. Any suggestion?
you can use the resouce tag in maven pom file:
<resources>
<resource>
<directory>[your directory]</directory>
<excludes>
<exclude>[non-resource file #1]</exclude>
<exclude>[non-resource file #2]</exclude>
<exclude>[non-resource file #3]</exclude>
...
<exclude>[non-resource file #n]</exclude>
</excludes>
</resource>
...
</resources>
For more informations see: https://maven.apache.org/plugins/maven-resources-plugin/examples/include-exclude.html
My understanding is
You want some config file, that is available in classpath during runtime
Such config file will be changed based on environment
The way I used to do is:
Create a separate directory for such kind of resources, e.g. src/main/appconfig/
Do NOT include this in POM's resources (i.e. they are not included in resulting JAR)
In IDE, add this directory manually as source folder (I usually put this in testResource in POM. When I use Eclipse + M2E, testResources will be added as source folder. Not sure how IntelliJ though)
For point 2, I used to do it slightly differently. Instead of excluding, I will include in the result JAR but in a separate directory (e.g. appconfig-template), so that people using the application can take this as reference to configure their environment.
An alternative of 3 is: create a separate profile which include appconfig as resource. Use this profile only for your IDE setup but not building your artifact.
I can see many posts regarding environment specific properties, but none of them is quite solving my problem.
I'm working on my spring boot app, which will have say two profiles dev/live.
I want my project to have the following structure:
--deployment
--dev
--myapp.properties
--live
--myapp.properties
--src
--main
--java
--resources
--test
--java
I know that if I had two application.properties in my resources folder, say application-live.properties and application-dev.properties I'd be able to tell maven which one to pick at application start time using:
Dspring.profiles.active=profile_name
But I don't like name of this generic properties file. So I found this way to tell the application where to look for profile specific properties in /deployment/<profile>/.
I did it using Maven build task configuration:
<build>
<resources>
<resource>
<directory>deployment/${environment}</directory>
<includes>
<include>*.properties</include>
<include>*.xml</include>
</includes>
</resource>
</resources>
</build>
This is going to search for resources in deployment/<profile> and include them. Good thing is that Maven finds the correct environmental property files, but unfortunately it includes them in target/classes/myapp.properties which seems invisible for Spring Boot? How can I tell Maven to place it in the same directory as application.propertiesor alternately how can I tell Spring Boot to find it where it is at the moment?
Thanks a lot!
How can I tell Maven to place it in the same directory as application.propertiesor alternately how can I tell Spring Boot to find it where it is at the moment?
1) you don't need to modify Maven settings because it places config file to the right place: target/classes is the root of the classpath, because all files from this directory will copied into the WEB-INF/classes directory of you WAR/JAR file.
2) to change name of the properties file from you can use spring.config.name property by explicitly passing it as -Dspring.config.name=myapp or as environment variable SPRING_CONFIG_NAME=myapp. More information you can find in the Change the location of external properties of an application chapter of the official documentation.
Why does maven keep resources in a separate "source folder" from the Java sources?
From my experience, in Java the resource files are mostly treated like Java source files which, when "compiled", just need to be copied as-is with the classes, and eventually packaged in the jar, and accessed by the classloader's methods getResource/getResourceAsStream, via the classpath.
Personally I find it a useless complexity to keep resource files separate from Java sources.
What do you think?
Is there a good reason why maven keeps resources separate from sources?
Is there any counter indication in not using src/main/resources and src/test/resources and keeping
resources in src/main/java and src/test/java using maven?
One point that hasn't been brought up yet is that you are obviously used to seeing projects with only java sources in them. however, if you throw in some other source file types, i think the organization makes more sense, e.g.:
src/main
resources
java
groovy
each sub-dir has a specific classification of files:
java -> things that are compiled as java files
groovy -> things that are compiled as groovy scripts
resources -> uncompiled data used for whatever... (also, these may be filtered to add compile-time info)
also (as i've noted in some comments already), i don't usually make the resources directory flat. files may be nested into a package-like structure or into other sub-directories as appropriate (to my sense of organization).
for simplicity and easier access we keep some resources as well in the java source path. This makes it convenient for us when developing on the GUI level as velocity templates and such are close to the Controller Java Code. But you have to tell maven to include non java stuff which is in src/main/java by adding something like this to your pom file.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.1.1</version>
<configuration>
<webResources>
<resource>
<directory>src/main/java</directory>
<targetPath>WEB-INF/classes</targetPath>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
<include>**/*.htm</include>
<include>**/*.html</include>
<include>**/*.css</include>
<include>**/*.js</include>
</includes>
</resource>
<resource>
<directory>src/main/resources</directory>
<excludes>
<exclude>**/log4j.xml</exclude>
</excludes>
</resource>
</webResources>
</configuration>
</plugin>
What do you think?
I think that the guys behind Maven should exercise a little "separation of concerns". The number one reason to use Maven is for dependency management, but why should a blender tell me how to peel my fruit? It makes no sense to me at all.
Is there a good reason why maven keeps resources separate from sources?
No. In a java project, the duplication of package structure, not once, but three times, adds unnecessary work to the project, increasing the risk for errors and reducing the agility of the code.
I try to give an answer by myself.
What do you think?
It's a useless additional complexity. Thus is wrong: see below.
Is there a good reason why maven keeps resources separate from sources?
The only reason I might think of, is that for some platform this might be a good practice. For example in Mac OSX application, resources are packaged separately (in a different sub folder) than the binaries.
I think that "external" resources and configuration files, the ones that don't get packaged inside the final artifact (jar file) can have a good reason to be kept separate from the source files. So, when maven packages the jar, he knows that those files don't have to be included, because for example, we want them outside the jar in order to allow the user to edit those files as configuration.
But, for the things that are packaged together in the jar (like translation strings, and xml metadata, such as hibernate mappings and spring configuration) there is no good reason to have them in a separate location, unless we expect our users to change them manually after the deployment, as part of the configuration process.
Resources can be organized with the same package structure as for the classes, so if you have a class in the package x.y.z you may want to have the resources it depends on in the same package, as they represent the same "logical unit": in this case, having them in two separate folders leads to additional attention required during package refactoring and reorganization, since you want to keep the things in sync. The ClassLoader also provides the possibility to specify relative paths in the getResourceAsStream() method. So if you have the class x.y.z.MyClass, you can do getClass().getResourceAsStream("foo-bar.properties"), and the resources will be loaded from the same package "x.y.z". So it's very useful to keeps things together when they have a tight dependency.
For the external resources that needs to be kept separate also in the deployable artifact, it's a good thing to keep them separate, but in this case I don't see why maven treats the src/main/resources as a "java source folder" (maven-eclipse-plugin) since they actually must not be in the classpath but accessed through the filesystem as plain files, and especially you don't want those file to be included inside the jar during the maven build. This is the case of application icons, configuration files that you might want to place in /etc directory, and so on.
In conclusion, there's something wrong in how maven handles resources, in my opinion: if they are "external" resources, then there's no reason why maven packages them in the final artifact (jar). If they are not "external", then there is no reason to keep them in a separate "source folder".
Is there any counter indication in not using src/main/resources and src/test/resources and keeping resources in src/main/java and src/test/java using maven?
I don't know.
Most of the time I've used the default maven layout to play with resources, but in a couple of times I didn't; taking the precaution to declare the non-standard resources directory location in the pom (see resources and super-pom).
It is possible to alter the maven project's directory structure specifying that in the pom:
<build>
<directory>target</directory>
<outputDirectory>target/classes</outputDirectory>
<finalName>${artifactId}-${version}</finalName>
<testOutputDirectory>target/test-classes</testOutputDirectory>
<sourceDirectory>src/main/java</sourceDirectory>
<scriptSourceDirectory>src/main/scripts</scriptSourceDirectory>
<testSourceDirectory>src/test/java</testSourceDirectory>
<resources>
<resource>
<directory>src/main/resources</directory>
</resource>
</resources>
<testResources>
<testResource>
<directory>src/test/resources</directory>
</testResource>
</testResources>
</build>
And I didn't find particular problems with it.
I would like that maven guys think again about this convention, as having a simpler project structure helps the developer to concentrate more on the development and less on finding things around several folders in the project structure while browsing the application code.
The way I distinguish between the two is that the java folders default to allowing nothing to be built in the resulting jar, except the file types I list (e.g. *.class, *.html, *.properties if you're using Wicket), whereas all the stuff in resources will be copied in the build except the few exceptions I list.
Of course that's just my private convention, adhered to by myself.
1) What do you think?
I thinks, it's an excellent convention.
2) Is there a good reason why maven keeps resources separate from sources?
Yes. You follow the convention. Everyone, who has got your project code's access will know where to look for code and where for everything else. And certainly, where for test cases. And what will happen to which file when that plugin will be executed.
3) Is there any counter indication in not using src/main/resources and src/test/resources and keeping resources in src/main/java and src/test/java using maven?
There isn't a counter indication. It's matter of convention, nothing's wrong with the way you arrange your own code. In fact, if you ever created a Wicket project, you will see your HTML and your Java code stays side-by-side in Java package. But, it is just Wicket where you know the HTML is going to be by the side of Java files. But everything else goes in resources folder.
Maybe I'm the only one here who does not come from a Java background. I think that mixing resources and code is very messy. Separation of concerns make your project cleaner and easier to understand/maintain as it grows.
I try to apply my own directory convention to all my software development projects:
bin: final binaries used by user
build: intermediate binaries, they may be deleted after build
lib: external libraries
src: ONLY source code (in this case, Java source files)
resources: all resources (configuration files, xmls, images, html, etc)
docs: documentation
Rarely I've found a development context when I needed to change this directory structure.
Using Maven, if you want to make a quick setup, use the defaults. If you want to use your directory convention, you just need to change settings in the pom.xml as explained before. Be aware, however, that some Maven plugins consider you use default Maven directories for resources/source/output binaries and you'll need to adjust some plugin settings if you change these directories.
I think that code/resources separation is often useful:
Packages must follow Java specification rules, for example reserved word, like 'int', is not allowed. Having illegal packages in source code folder would be confusing.
Resources has instance nature, classes has, well, classes nature. For example you may have classes Continent and Country in the same package but resources better organize as tree:
africa/
morocco.txt
kenya.txt
europe/
poland.txt
Resources structure, in my opinion, is more stable than code structure. Code refactoring happens often, classes move from package to package for better readability. Obligation to move resources on refactoring discourages developer from refactor.
If separated resource folder is required even only for 1% of resource files, is reasonable to move remaining 99% to that folder and keep resources in single place only.
However, there are cases when keeping resources and java code together is useful. For example unit tests compares input and output - nice to have file with input and output in the same folder as unit test code.
I have two projects A and B.
B is dependant on A.
A has some resource files.
When using mvn install on B, it uses the resources that were packaged in A.jar (as that was built previously)
I would like the resources to be packaged in B so I could edit them easily. (Especially since B is deployed as WAR)
Copying the resources to project B might not help since the code in A uses the following to retrieve info
InputStream stream = this.getClass().getResourceAsStream(
"/resourceFile.properties");
do I need to change the path to relate to project B? if so how should one do it?
What is the best approach for handling this?
Easiest way I've found
it to add this to your B project POM
<build>
....
<resources>
<resource>
<directory>src/main/resources</directory>
</resource>
<resource>
<directory>../A/src/main/resources</directory>
</resource>
</resources>
...
</build>
You could use the maven-shade-plugin's shade mojo to repackage select artifacts from your project A into B. I haven't entirely looked at the jarjar-maven-plugin, but it could also assist you in doing that.
Look at the "Relocating classes" section of the shade plugin documentation in particular to understand how to do it. It should work equally well with resource files in theory.
Your code will work as it always does - it does not matter whether the resource being loaded is in the same jar or in a different jar in the B's classpath or inside B's WEB-INF/lib as long as it's in the classpath and referred by the right path in your code.
It's good that you didn't consider moving the property file into B project's codebase - had you done that, A would no longer be self-contained.
As long as project B is in the same classpath as project A, that code will continue to work.
It may be clearer, however, to use ClassLoader.getResoucreAsStream rather than Class.getResourceAsStream. The method on Class by default looks for resources relative to the package name of the Class. You have provided an absolute path (leading '/'), indicating that the package relative logic is not needed.
I'm using NewRelic for monitoring. I want Maven to package both newrelic.jar and newrelic.yaml files into my WEB-INF/lib inside the war file. With the newrelic.jar there is no problem since it's a simple dependency, but newrelic.yaml is a resource file. It resides in resources directory. I want Maven (war plugin) to copy it to WEB-INF/lib when packaging the war.
Thanks.
Alex
While I agree with #matt b that this is odd, here's what you can do:
Try changing the configuration of the maven war plugin to include a webResource:
<configuration>
<webResources>
<resource>
<directory>pathtoyaml</directory>
<includes>
<include>**/*.yaml</include>
</includes>
<targetPath>WEB-INF/lib</targetPath>
</resource>
</webResources>
</configuration>
The directory is relative to the pom.xml. See the plugin's documentation for more info.
You can also specify most configuration for the New Relic agent including the location of the config file via flags passed to the java command. In this case, it's something like:
-Dnewrelic.config.file=/etc/newrelic.yml
(ok, it's exactly like that, but you need to specify whatever path you need if it's not that.)
You should try adding .yaml file to newrelic.jar's resources, later
you can access it via classpath.
Or try changing/overriding build.xml build target by adding something like < copy file=".yaml"
todir="WEB-INF/lib" />
Try googling for more info on changing build.xml.