How to validate sets of properties files in Maven - maven

I think I've a fairly generic problem that I expecting Maven to solve, but I can't find the appropriate plug-in...
Background
Like most reasonably sized projects I've got a requirement to deploy my application in several different environments. Let's say they are called "development", "qa" and "production". In each of these environments my application will talk to a different back end server and save it's data to a different data base. Rather then hard code all the setting in my application I'm going to create a Java properties file for each environment and just deploy the right one with the application. In my source code will look something like:
<root>
|-- conf
| |--develop
| | \-- application.properties
| |--qa
| | \-- application.properties
| \--production
| \-- application.properties
\-- pom.xml
The problem
If the developer is adding a new setting to the project it's too easy to update conf\development\application.properties file but forget to update the other files. If the setting is missing this typically causes errors a run time, which on a production server could be disastrous.
The Question
Is there a Maven plug-in that could be used to ensure that all three versions of application.properties contain the exactly same set of keys. If one (or more) key is missing from any of the files the build should be failed.

I'd develop a Maven plugin:
with an appropriate parameter, e.g. files.
See this answer for examples how to implement multiple values parameters.
that reads the three .properties files and fills a Map<String, Integer> (where: String key, Integer count).
If any of the Integer is not equal to the number of files given in the end throw an org.apache.maven.plugin.MojoFailureException. The same applies if one of the values is invalid, e.g. empty or otherwise syntactically wrong.
I'd bind the plugin's goal to the generate-resources phase.

Related

Spring Boot application.properties configuration order

I'm working on a SpringBoot (2) application. I'm looking at our properties files which have become a bit convoluted and I'd like to tidy it a little.
In deployment we have a small main/resources/application.properties file which contains a few defaults and an external property file which contains a lot of other properties. This works well... and I'm trying to replicate this in dev and failing and I'm hoping I'm doing something silly which someone can point out painlessly.
As I understand it by default, Spring Boot will look in various places for the properties, in this order...
classpath root
/config in classpath
in the current directory
/config subdirectory of the current directory
Using Intellij I can't get SpringBoot to pick up 2 locations though. If I put all properties in main\resources\application.properties then that's fine. If I use -Dspring.config.name=dev and add a dev.properties with all properties this works well but I can't seem to configure a split in debug between defaults in main\resources\application.properties and a simulation of the external file somewhere else in the project (so that it won't get packaged in the jar).
Is there a simple way to do this, or any good documentation somewhere that I've missed that would explain it well enough that I might be able to simulate it in the dev environment ?

Should the generation of documentation be done in the parent or the modules?

I am still fairly new to Maven and am unsure of the correct roles of the various components.
I have been using the following Maven-project structure for developing microservices:
service-parent
+-- rest-service-module
+-- frontend-js-module
+-- ...
The service definition is done using Swagger and the yaml file is stored in the parent project.
I would now like to setup a site which should include documentation and reports. It seems logical to me to store the site in the parent and gather javadocs, surefire reports etc from the child modules. For example, I added swagger2markup-maven-plugin to the parent pom to generate documentation from the swagger yaml.
The first problem I have had is that the parent pom executes the swagger2markup-maven-plugin and generates HTML. However, it executes the same goal on the child modules and fails.
It seems that I am not understanding the roles of parent and child poms which leads to this problem. The Swagger documentation only needs to be generated once - not from each child module - so the parent seems the obvious choice.
So why is the plugin in the parent being executed for each child and how can I prevent that? I'm still in the early phase of the project so I can reorganise the module structure, if appropriate.
I have tried the solution suggested in https://stackoverflow.com/a/14653088/11249 but couldn't get it to work for me.
You can use -N switch to not to recurse into the subprojects when generating documentation. Execute the following command (or any other you like) on your service-parent pom.xml. (It will only be executed for this pom)
mvn -N swagger2markup:convertSwagger2markup

Spring Relative Path File Resource In Application Context

I have a quick question about getting spring to read a file from the application context that is external to the project. I have two projects; 1) Project A 2) Project Database. Project A has the following structure;
ProjectA
|-src
|-main
|-webapp
|-WEB-INF
|-config
|-spring
Project Database has the following structure:
Project Database
|-db
|-scripts
|-deltas
In the spring directory of Project A I have a dao-context file. In this I have configured an embedded database, however I want to initialize the database with scripts from project database. Specifically in from directory deltas.
I know the embedded database config should like the following:
<jdbc:embedded-database id="dataSource" type="H2">
<jdbc:script location="someSchema.sql"/>
</jdbc:embedded-database>
However I am trying to determine the best way to reference the scripts in Project Database. In other words would should be the value of location if I want to use scripts in locations. A few details:
Both projects would be checked out together on the same hierarchy.
Furthermore this database would only be used to run the tests, not the actual production code. So what ever the solution it should be compatible with my build script when I run tests tasks.
Lastly I want to avoid an absolute file path, because this will be run on multiple machines.
Any ideas?
Cheers
EDIT: Both projects are just folders and not jars. Neither projects are in each others classpath. Other than the fact that they are in the same directory there is no relation.
EDIT 2: Another scenario (and likely to happen) is that the db scripts could be in the same project as ProjectA , but not in the classpath. For example the directory structure could look like this:
ProjectA
|-db
|-scripts
|-deltas
|-src
|-main
|-webapp
|-WEB-INF
|-config
|-spring
If this was the case how would I access the scripts in the 'deltas' directory from the 'spring' directory?
I thing I have (more or less) understood what your asked, but there are many caveats.
First, when developping apps, there are 3 categories of paths :
source paths containing java sources (will be compiled), and other configurations or data files (will be copied)
target paths generated from the previous ones that are assembled in jars, or wars (or ...)
data paths that may contain data files, or file databases outside of a jar or war.
A web application is normally executed independantly of its source path, eventually on another machine : you build the war and deploy in on a servlet or JEE container.
What you can do is use an environment variable, a system property or a property value to set the root of a data path in the web application. Spring is kind enough to allow environment variable to override property values when using a PropertySourcesPlaceholderConfigurer to set ${...} values in an application context. Then you use that value to get access to your datas outside of the project.
In your example, you define such a property for the db location, and access all your database configuration relatively to that location.

Maven generating two different WAR files for same project

I have a maven web-service project consisting of two different service classes testClass1 and testClass2 . I want to have two different WAR files for both classes of same project. Presently I am generating single WAR file for both services .
How can I generate two different WAR file for same project ?
Thanks In Advance.
General Considerations
As per doc says, what you try to achieve is a bad pratice :
Producing Multiple Unique JARs from a Single Source Directory
As many people that complain about not being able to spread out their sources into multiple source directories seem to complain about not wanting to spread anything out, producing several unique artifacts from a single directory using includes and excludes.
Why isn't this recommended?
This practice can be confusing and risky.
You may end up building two JARs that include the same classes - this indicates that the common functionality should have been abstracted into a separate dependency.
You may end up introducing a dependency between the two JARs that you didn't realise, and often a circular dependency. This indicates that the classes are in the wrong JAR, or perhaps that everything should just be a single JAR.
Solutions that fit the maven best pratices
You should consider splitting you project into two differents ones, having each one a pom, and so each one generating an artifact, here a war.
Two simples projects
You may achieve that by using either two simple projects :
service1-simple-webproject
|-- src
`-- pom.xml
service2-simple-webproject
|-- src
`-- pom.xml
This is quite simple, but you may not be able tho share easily properties / dependencies / relations between them.
Just split your own code into separates directory, and try to make it work as two independant projects.
If you think that there is some code to share between them (utilities, configuration, ...), see next section about multi module.
Multi module structure
Or you can use an appopriate multi-module hierarchy :
parent-multimodule-project
|-- service1-simple-webmodule
| |-- src/
| `-- pom.xml
|-- service2-simple-webmodule
| |-- src
| `-- pom.xml
`-- pom.xml
This will allow you to have relations between projects, share configuration at a higher level, ...
Ta ke a look to this documentation :
Maven Official doc : http://maven.apache.org/guides/mini/guide-multiple-modules.html
Sonatype fantastic doc : http://www.sonatype.com/books/mvnex-book/reference/multimodule.html
I will probably lead you to create a third project, probably named core, or util, that would produce a jar which will contains common classes to both web project.
This is really the best way !
Functionnal solutions but strongly not advised ones
I would only give you some information, because I'm even sure it could work in this case.
Maven Assembly Plugin allow you to generate different format of package (zip, jar, war, other, ...) based on xml description files.
Here documentation : http://maven.apache.org/plugins/maven-assembly-plugin/
Once again, I strongly advise you to NOT use this kind of workaround.

Maven Variables are not replaced into installed pom file

We are using Maven(3.0.3) as build tool and we need to have different version for different environments (DEV , TEST, QA ) . If we pass version property value during build time based on environment , the installed POM doesn't have the passed property values instead it still has the ${app-version} string.
I saw already there is a bug for this http://jira.codehaus.org/browse/MNG-2971
Is there any other alternative ,because we cannot different POM file for different environments ,which will be hard to maintain..
Thanks
Vijay
Create different artifacts for the environments and use the parameter as a classifier. The pom is the same for all three artifacts but the classifier separates them.
Apparently Maven does not make any variable/property substitution when installing the POM. It is installed as is, that is the principle. You'd better not read any properties from POM (unless this is e.g. version number), bout you should configure your properties in external file (one per stage, e.g. dev.properties, test.properties, ...) and then configure Maven profiles (again, one per stage) and invoke Maven like mvn -Pdev depending on what you want to build. In profile you can package your final application with whatever properties you like (e.g. with the help of build-helper-maven-plugin:add-resource or maven-antrun-plugin + copy rule).
Alternatively you can filter your resources. For example, you can filter your Spring context XML file, which refers the properties file (so you package all property files, but Spring will refer only some specific). Or you can filter another properties file from which you will learn what is the "main" properties file to use (double indirection).
You should create the archives for your different targets within a single build and use as already mentioned the classifier to separate those artifacts from each others.

Resources