Inherit only some properties or some plugins from parent poms - maven

We have Oracle ADF and SOA projects that are built using custom Ant scripts, instead of normal Maven build. The same Ant plugin is configured differently for ADF and for SOA. The file structure isn't driven by the type of the project, but can be mixed, meaning:
- parent pom
- ADF
- SOA type1
- SOA type2
How can we set in the pluginManagement different versions of Ant plugins, and the children to pick whatever type of Ant plugin they want. As I know you can only pick what plugins you want, but not what flavor of same plugin.
I don't want to complicate my inheritance structure just for this. I need the structure to remain as it is, for release purposes.
The same I want with properties, I want to have some types of properties in central places, and a project to be able to use them, but also inherit the parent pom (for release purposes). Sort of like inherit from multiple parents.
I don't want to be tight by the need of properties and plugins (which are general for all projects, not just mine). I need to keep my pom structure clean, for release purposes.

You could try using profiles. They allow for the ability to customize a particular build for a particular scenario.
You can define multiple profiles in your parent pom each containing their own ant <plugin> section. Each profile would also have activation section. Then in your child modules you would have them activate the appropriate profile.
I'll try and give an example using some sudo code:
parent pom
<profile>
<id>adf-project</id>
<build>
<plugins>
<plugin>
<!-- adf specific ant plugin config -->
</plugin>
</plugins>
</build>
<activation>
<property>
<name>adfBuild</name>
<value>true</value>
</property>
</activation>
</profile>
<profile>
<id>soa-project</id>
<build>
<plugins>
<plugin>
<!-- soa ant plugin specific config -->
</plugin>
</plugins>
</build>
<activation>
<property>
<name>soaBuild</name>
<value>true</value>
</property>
</activation>
</profile>
Then in your soa module pom you would have the following:
<project ...>
<properties>
<soaBuild>true</soaBuild>
</properties>
</project>
This will then automatically activate that profile and use the correct ant plugin configuration.
Another option would be to define the plugin as normal but with multiple executions (one execution for soa and one for adf) and then in the child poms override each execution with a phase of none for those executions that you do not want to run. It should be noted that this latter approach is not recommended. See my answer here for more details on this.

Related

In a Maven multi-module project, how can I run a full build and run a specific plugin on one child?

I have a multi-project maven project. One child only has a specific plugin and I want it to be optional (so not bound to a specific phase).
How can I run a full clean install on the entire project and additionally run a project's specific plugin?
I've encountered this post but it looks like an overkill, and it is not so easy in my specific case.
Your best option is to use maven build profiles.
In example, use this snippet in child module:
<profiles>
<profile>
<id>only-in-child-module</id>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
<build>
<plugins>
....
</plugins>
</build>
</profile>
</profiles>
This build profile will not be active unless you explicitly ask maven for it like:
mvn clean install -Ponly-in-child-module

Maven. Build only module that have deploy profile

Context:
I have a rather large system with several maven module formed in a hierarchy. When I need to develop I can go to the root and build using a specific profile -Pdeploy
The problem with this is that, my entire project is built (which takes a while) when I only in truth need to build a dozen lightweight modules that just deploy.
How should I got into improving the team's efficiency when deploying?
Basic Idea: You may not skip building modules but you may skip some of your plugin executions contained.
Usually your repository will already have build module artifacts present, so the overall speed should already be better once a previous build have been run and module artifacts can be pulled from there.
The idea is that you add a profile setting that defines skip-properties according to what you may want to omit when doing a deploy profile build only.
<profiles>
<profile>
<id>default</id>
<activation>
<activeByDefault />
</activation>
<properties>
<skip.documentation>false</skip.documentation>
<skip.sign>false</skip.sign>
<skip.sources>false</skip.sources>
<skip.checks>false</skip.checks>
<skip.reports>false</skip.reports>
<skip.installer>false</skip.installer>
</properties>
</profile>
<profile>
<id>deploy</id>
<properties>
<skip.documentation>true</skip.documentation>
<skip.sign>true</skip.sign>
<skip.sources>true</skip.sources>
<skip.checks>true</skip.checks>
<skip.reports>true</skip.reports>
<skip.installer>true</skip.installer>
</properties>
</profile>
</profiles>
Your pom than might contain
<plugin>
<artifactId>maven-checkstyle-plugin</artifactId>
<version>${version.maven-checkstyle-plugin}</version>
<configuration>
<skip>${skip.checks}</skip>
</configuration>
</plugin>
This method can be applied on a project pom level (pluginDependencies) or overridden in each module.

Spring Set Production / Development level JDBC properties

I have a JDBC.properties file that contains db connection information
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.dialect=org.hibernate.dialect.MySQLDialect
jdbc.databaseurl=jdbc:mysql://127.0.0.1/mydb
jdbc.username=root
jdbc.password=
Now when I use it in the server my info changes
jdbc.username=root
jdbc.password=mypassword
What I do now is manually change this information before making war file and upload it to the server.
Now I was wondering if there is any way I could set this information so that i don't have to change this information every time before upload
How to do this??
Don't put your properties inside your war file. Externalize them. Put them somewhere in a well known path (/etc/myapp/jdbc.properties).
You shouldn't be creating different artifacts for your production,development and test environment. It should be the same. Recreating the artifact means a new version which (in theory) means new testing. Even if you use maven profiles.
The approach I tend to use is to put some defaults in an internal properties file and optionally load a file from outside the war. That way you provide your users with the possibility to override the default configuration.
<context:property-placeholder location="classpath:/jdbc.propertes,file:/etc/myapp/jdbc.properties" igonre-resource-not-found="true" />
That way your defaults are inside the application and users can override it by specifying other properties in the /etc/myapp/jdbc.properties file.
You could use spring profiles. This blog post should give you the idea: http://spring.io/blog/2011/02/11/spring-framework-3-1-m1-released/
You should use a build tool like Maven and do this with resource filtering and profiles.
Doing it through Spring profiles is probably one way, but in my opinion it makes more sense to be handling it through the build.
Consider the following with Maven:
src/main/resources/jdbc.properties:
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.dialect=org.hibernate.dialect.MySQLDialect
jdbc.databaseurl=${jdbc.databaseurl}
jdbc.username=${jdbc.username}
jdbc.password=${jdbc.password}
pom.xml:
<project ...>
...
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
...
<profiles>
<profile>
<id>dev</id>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
<properties>
<jdbc.databaseurl>jdbc:mysql://127.0.0.1/mydb</jdbc.databaseurl>
<jdbc.username>username</jdbc.username>
<jdbc.password>password</jdbc.password>
</properties>
...
</profile>
<profile>
<id>prod</id>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
<properties>
<jdbc.databaseurl>jdbc:mysql://212.123.45.6/mydb</jdbc.databaseurl>
<jdbc.username>username</jdbc.username>
<jdbc.password>secret-password</jdbc.password>
</properties>
...
</profile>
</profiles>
...
</project>
For development, invoke:
mvn clean package ... -Pdev
Likewise for production:
mvn clean package ... -Pprod
Maven filtering allows you to replace properties in your .properties resources based on properties defined in Maven via <properties/> (either in a profile, or not).
References:
- Resource filtering
- Profiles

Maven: filtering seam components.xml in target directory

I'm trying to convert an Ant project to Maven. The existing build uses Ant-style properties in src/main/webapp/WEB-INF/components.xml, which is a Seam file.
I'm able to get the properties expanded in the actual resulting war file, via the maven-war-plugin. But I can't seem to get the properties expanded in target/myproject/WEB-INF/components.xml.
This means that when I try to run the Jetty plugin, it doesn't see the expanded properties.
I tried defining the properties in both an external file, and also right in the build. My profile section looks like the following:
<profiles>
<profile>
<id>dev</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<build>
<filters>
<filter>src/main/filters/components-dev.properties</filter>
</filters>
</build>
<properties>
<debug>true</debug>
<jndiPattern>FOO</jndiPattern>
</properties>
</profile>
</profiles>
When you run mvn jetty:run it executes the lifecycle up through test-compile. The web resources don't get filtered until the war plugin runs as part of package. I found a question on stackoverflow that seems similar, does that solution work for you?

How to generate a combined Maven site from unrelated projects?

I would like to create a general overview of several Maven projects in the form of a website generated with the Maven site goal. The projects are part of different products, some have a parent-child relation, some have dependencies on others.
The site should combine the information from all projects and include JavaDoc, Checkstyle/PMD checks, test results and code coverage metrics.
I've created a POM file that aggregates each existing project as a module, with each project available in subfolder, but then the output is not combined into a single site.
You can do this by setting project.build.directory on all of your projects to a common folder. This can be accomplished by passing in the path as a parameter to the build. You can then run the site goal on the common target folder. If you run maven from in a continuous integration environment, you can do this by setting targetpath in your maven task. Otherwise you would have to specify it on the command line.
<project>
<build>
<directory>${targetpath}/${project.artifactId}</directory>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-site-plugin</artifactId>
<version>2.3</version>
<configuration>
<inputDirectory>${targetpath}</inputDirectory>
</configuration>
</plugin>
</plugins>
</build>
</project>
mvn clean deploy -Dtargetpath=Path/To/Build/Output
To keep the build the same for your developers, you could create a profile that is activated when targetpath is not provided by the command line.
<profiles>
<profile>
<id>dev</id>
<activation>
<property>
<name>!targetpath</name>
</property>
</activation>
<properties>
<targetpath>target</targetpath>
</properties>
</profile>
</profiles>

Resources