Maven - Querying a dependency for information at compile time - java

I am using Maven for one of our projects. We have a compile-time plugin, jasperreports-plugin, that is built using jasperreports 6.1.1. However, we have another dependency (which we control), jasper-including-artifact, that uses jasperreports 6.1.0. This requires us to manually override the version of the jasperreports in the section for the jasperreports-plugin so they match up. What the POM ends up looking like:
<dependencies>
<dependency>
<groupId>com.my.application</groupId>
<artifactId>jasper-including-artifact</artifactId>
<version>4.1.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>com.alexnederlof</groupId>
<artifactId>jasperreports-plugin</artifactId>
<version>2.2</version>
<dependencies>
<dependency>
<groupId>net.sf.jasperreports</groupId>
<artifactId>jasperreports</artifactId>
<version>6.1.0</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
This works, but to make it more maintainable we'd ideally like to be able to read a value from our jasper-including-artifact dependency and use that to set the version of the overriding dependency in jasperreports-plugin, so we don't need to make manual modifications to the POM when the version of jasperreports in jasper-including-artifact is changed. So something like this (obviously fake):
<dependencies>
<dependency>
<groupId>com.my.application</groupId>
<artifactId>jasper-including-artifact</artifactId>
<version>4.1.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>com.alexnederlof</groupId>
<artifactId>jasperreports-plugin</artifactId>
<version>2.2</version>
<dependencies>
<dependency>
<groupId>net.sf.jasperreports</groupId>
<artifactId>jasperreports</artifactId>
<version>${jasper-including-artifact.jasper-version}</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
Note that it's not the version of the jasper-including-artifact we're interested in, but the version of jasperreports contained inside it. We control jasper-including-artifact so we can make changes to the POM for that if required.
Is this a capability that Maven offers?

Related

module-info when one of my external libraries doesn't have a module-info

I am a beginner in Java coding, I am teaching myself JavaFX and making a project that uses JPA through Hibernate (I have no knowledge on Spring yet).
The problem I find myself having is that an essential external library doesn't have a module-info for me to refer to in my project.
I can have either JavaFX or mysql-connector-java working, but not both at the same time.
The connector I am using is: https://mvnrepository.com/artifact/mysql/mysql-connector-java version 8.0.19
When I exclude my module-info my JPA works, when I use my module-info my FX works
I asked my teacher for help but he doesn't seem to have an idea yet on how I can use my JavaFX and JPA in the same project. Does anyone have a good suggestion on how I can fix this issue?
My POM
<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.tumblr.calscodingcorner</groupId>
<artifactId>dnd5e_database_maker</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<release>11</release>
</configuration>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.2</version>
</plugin>
<plugin>
<artifactId>maven-failsafe-plugin</artifactId>
<version>2.22.2</version>
</plugin>
<plugin>
<groupId>org.openjfx</groupId>
<artifactId>javafx-maven-plugin</artifactId>
<version>0.0.3</version>
<configuration>
<mainClass>com.tumblr.calscodingcorner.application.App</mainClass>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.6.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.6.0</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.19</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-core -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.4.12.Final</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.openjfx/javafx -->
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx</artifactId>
<version>11</version>
<type>pom</type>
</dependency>
<!-- https://mvnrepository.com/artifact/org.openjfx/javafx-controls -->
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
<version>11</version>
</dependency>
</dependencies>
My module.info
module dnd5e.database.maker {
requires javafx.controls;
requires java.persistence;
requires mysql.connector.java;
exports com.tumblr.calscodingcorner.application;}
Thanks in advance for any advice
Answering the title:
module-info when one of my external libraries doesn't have a module-info
You need to require (in module-info.java) the automatic module name corresponding to the name of the dependency jar (without the version), or to the Automatic-Module-Name declared in the jar's MANIFEST (if exists). Then maven will automatically add the jar to --module-path.
If you don't require the jar inside module-info, it will be added to --classpath in which case it will become part of the unnamed module and won't be visible by your module (only by automatic modules).
You can add -X to maven to see which dependencies are added to -classpath and which to --module-path
See the spec
[...] A named module cannot, in fact, even declare a dependence upon the unnamed module. This restriction is intentional, since allowing named modules to depend upon the arbitrary content of the class path would make reliable configuration impossible

Making an executable jar out of spring boot MVC project serving content using JSP and a custom parent set in POM

I had a Spring MVC project that I'm converting to spring boot. This project of mine cannot be given spring-boot-starter-parent as parent because I need to keep a custom parent.
I solved this first issue by injecting spring-boot-dependencies in dependencyManagement.
I also need my project to embed a tomcat, so I've used spring-boot-starter-web. I need to use JSP so i've added the dependencies to jstl and jasper.
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.1.4.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-loader -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-loader</artifactId>
<version>2.1.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-core</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
<!-- ... -->
</dependencies>
Compiling the jar and launching the server using
mvn spring-boot:run
correctly works. Now I'd like to make it work as executable jar, too.
I have read some documentation, posts, web pages, stack overflow questions, but I still cannot make it properly work.
In this question, reading the edited version of the accepted answer and the github project it looks very easy to make an executable jar out of a project having as parent spring-boot-starter-parent. Is it possible to make it work with a custom parent too?
I have already tried to follow these guidelines but it doesn't work with my project.
I tried adding the plugin
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
both with and without the execution node
and the plugin
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.0.0</version>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
<archive>
<manifestFile>src/main/webapp/META-INF/MANIFEST.MF</manifestFile>
</archive>
<!-- <archive>-->
<!-- <manifest>-->
<!-- <mainClass>my-boot-application</mainClass>-->
<!-- <springBootClasses>WEB-INF/classes/</springBootClasses>-->
<!-- <springBootLib>WEB-INF/lib/</springBootLib>-->
<!-- </manifest>-->
<!-- </archive>-->
</configuration>
</plugin>
both with and without the manifest customized information.
Eventually I have incurred in this stackoverflow post listing all that is necessary to make a spring boot application using jsp, embedded tomcat and custom parent project work.
So, my pom.xml is now much readable and compact and looks much like the examples in the link.

How to disable karaf-maven-plugin 4 tight dependency constraint checks

Currently I am moving from karaf 3.0.5 to the newest version 4.0.2, I do assembly my own karaf with the karaf-maven-plugin. This is how my pom looks like.
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>my.own.group</groupId>
<artifactId>assemble</artifactId>
<version>1.14.0-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<artifactId>karaf-customize</artifactId>
<modelVersion>4.0.0</modelVersion>
<packaging>karaf-assembly</packaging>
<dependencies>
<dependency>
<groupId>org.apache.karaf.features</groupId>
<artifactId>framework</artifactId>
<version>${karaf.version}</version>
<type>kar</type>
</dependency>
<dependency>
<groupId>org.apache.karaf.features</groupId>
<artifactId>standard</artifactId>
<classifier>features</classifier>
<version>${karaf.version}</version>
<type>xml</type>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.apache.cxf.karaf</groupId>
<artifactId>apache-cxf</artifactId>
<classifier>features</classifier>
<version>${cxf.version}</version>
<type>xml</type>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.apache.karaf.features</groupId>
<artifactId>enterprise</artifactId>
<classifier>features</classifier>
<version>${karaf.version}</version>
<type>xml</type>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>my.own.group</groupId>
<artifactId>kar-archive</artifactId>
<version>1.14.0-SNAPSHOT</version>
<type>pom</type>
<optional>true</optional>
</dependency>
<dependency>
<groupId>my.own.group</groupId>
<artifactId>karaf-branding</artifactId>
<version>1.14.0-SNAPSHOT</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
<dependency>
<groupId>com.alutam</groupId>
<artifactId>ziputils</artifactId>
<version>1.1</version>
</dependency>
<dependency>
<groupId>wsdl4j</groupId>
<artifactId>wsdl4j</artifactId>
<version>1.6.3</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.karaf.tooling</groupId>
<artifactId>karaf-maven-plugin</artifactId>
<version>${karaf.version}</version>
<extensions>true</extensions>
<configuration>
<javase>1.8</javase>
<bootFeatures>
<feature>jasypt-encryption</feature>
<feature>config</feature>
<feature>standard</feature>
<feature>region</feature>
<feature>management</feature>
<feature>bundle</feature>
<feature>package</feature>
<feature>kar</feature>
<feature>ssh</feature>
<feature>http</feature>
<feature>cxf</feature>
<feature>service-wrapper</feature>
<feature>jdbc</feature>
<feature>system</feature>
</bootFeatures>
</configuration>
</plugin>
</plugins>
</build>
</project>
With this configuration I do get the following error for several dependencies.
Caused by: org.osgi.framework.BundleException: Unsupported 'Bundle-ManifestVersion' value: 1
at org.apache.karaf.features.internal.resolver.ResourceBuilder.doBuild(ResourceBuilder.java:88)
at org.apache.karaf.features.internal.resolver.ResourceBuilder.build(ResourceBuilder.java:78)
I guess it happens within this parser. The reason is some old third party libraries have only Bundle-ManifestVersion: 1 set within their manifest file.
With karaf-maven-plugin 3.x this didn't matter at all. In contrast the karaf-maven-plugin 4.x fails with message above.
The only way I know to fix this is either rebuild from source or repack the hole jar again.
Is there any other way like a configuration for the karaf-maven-plugin to disable this constraint check? Because it would be awful lot of work to get all of this bundles up an running, again.
I faced the same error when updating to Karaf 4 and you have two choices:
Osgify conflictive dependency using bndtools:
Download bnd tools
Open a shell where you have downloaded bnd-2.4.0.jar.
Type:
java -jar bnd-2.4.0.jar wrap -o osgify-dependency.jar dependency.jar
where dependency.jar is your third party and osgify-dependency.jar will be the output.
Deploy to maven repo overriding the previous maven coordinates, or deploy your thirdparty with different coordinates.
mvn deploy:deploy-file -Dfile osgify-dependency.jar ..
Enable the wrap protocol
Add to you maven karaf plugin wrap and wrapper features.
So you can use wrap protocol to fix your corrupted MANIFEST.MF
Inside some karaf features:
<bundle>wrap:mvn:group.id/third.party.artefact.id/version</bundle>
Inside your pom.xml notice feature wrap / wrapper.
<plugin>
<groupId>org.apache.karaf.tooling</groupId>
<artifactId>karaf-maven-plugin</artifactId>
<extensions>true</extensions>
<executions>
</executions>
<configuration>
<!-- no startupFeatures -->
<bootFeatures>
<feature>feature</feature>
<feature>jaas</feature>
<feature>shell</feature>
<feature>ssh</feature>
<feature>management</feature>
<feature>bundle</feature>
<feature>config</feature>
<feature>deployer</feature>
<feature>diagnostic</feature>
<feature>instance</feature>
<feature>kar</feature>
<feature>log</feature>
<feature>package</feature>
<feature>service</feature>
<feature>system</feature>
<feature>wrap</feature>
<feature>aries-blueprint</feature>
</bootFeatures>
<installedFeatures>
..
<feature>wrapper</feature>
</installedFeatures>
</configuration>
</plugin>
Here you have the full code where i tested:
https://github.com/antoniomaria/gazpachoquest/blob/master/karaf-assembly/pom.xml

Maven Changing Java Compiler

When updating my maven project, the java compiler is changing from 1.7 to 1.5.
this is my pom.xml file
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.chart.simple</groupId>
<artifactId>core</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>core Maven Webapp</name>
<url>http://maven.apache.org</url>
<properties>
<java-version>1.7</java-version>
<org.springframework-version>4.0.3.RELEASE</org.springframework-version>
</properties>
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.3.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-dbcp2</artifactId>
<version>2.0</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.21</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${org.springframework-version}</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>4.3.5.Final</version>
</dependency>
</dependencies>
<build>
<finalName>core</finalName>
</build>
</project>
Help!!
The default compiler source and target level for Maven is 1.5.
"Also note that at present the default source setting is 1.5 and the default target setting is 1.5, independently of the JDK you run Maven with. If you want to change these defaults, you should set source and target as described in "Setting the -source and -target of the Java Compiler"."
Source:
http://maven.apache.org/plugins/maven-compiler-plugin/
One reason that your attempt at setting "java-version" property has no effect is that "java-version" is not one of the recognized Maven built-in properties. This page lists the built-in properties that are available:
http://docs.codehaus.org/display/MAVENUSER/MavenPropertiesGuide
Note that though there is a "java.version" property, it is an (effectively) read-only that reports the java version of the JVM that is running Maven. It doesn't control the Java compiler source and target levels.
Well, if you don't specify an explicit version, you get the default.
While it might look like setting java.version is doing something to select a particular JVM, it isn't. It's just a name bound to a value. Maven can't switch JVMs after it is invoked, so you are probably overwriting the original value (which was probably 1.5). Keep in mind that if you have Java 1.5 installed, if it's before the other JVMs it will get invoked first. Also, you can have "maven specific" settings in any "maven launching" scripts, and other such items.
Configure your compiler plugin like so. Set a source and target version. Also, keep in mind that Maven doesn't "include" a compiler, so it will do it's best to configure the installed compiler to fit your declared source and target settings.
Add the compiler plugin
<build>
<pluginManagement>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
I usually put the above on the parent POM that way any projects under it which are JAR/EAR/WAR projects will use 1.7 without triggering the plugin as part of the build.
If you have a solitary JAR module just get rid of pluginManagement to keep things simpler.

Maven dependency management for plugin dependencies

Recently, I came accross the following problem :
As I set up dependency management for my project, I had child-pom using plugin with dependencies, that I want to be synchronized with dependencies declared in my dependency management.
In a root pom, I declared in my dependency management:
<dependencyManagement>
<dependencies>
...
<dependency>
<groupId>com.google.gwt</groupId>
<artifactId>gwt-user</artifactId>
<version>2.4.0</version>
</dependency>
...
<dependencies>
<dependencyManagement>
And in the child pom, I have a plugin which needs gwt-user :
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>gwt-maven-plugin</artifactId>
<version>2.4.0</version>
<dependencies>
<dependency>
<groupId>com.google.gwt</groupId>
<artifactId>gwt-user</artifactId>
<version>2.4.0</version>
</dependency>
...
</dependencies>
...
</plugin>
However, if I remove the dependency version used in gwt-maven-plugin, the compilation fails.
Is there another way to achieve it ?
PS: There is a related post Choosing dependency version in maven and maven plugin which does not answer my question
According to the following links, it seems not to be possible:
http://maven.40175.n5.nabble.com/dependency-management-within-plugin-dependencies-td78367.html
https://issues.apache.org/jira/browse/MNG-2496
Here is a workaround I found, and I wanted to share with everyone, in case other people had the same problem:
In my root pom, I have defined a property, a dependency management and a plugin management:
<properties>
<gwtVersion>2.4.0</gwtVersion>
<gwtMavenPluginVersion>2.4.0</gwtMavenPluginVersion>
</properties>
<dependencyManagement>
<dependencies>
...
<dependency>
<groupId>com.google.gwt</groupId>
<artifactId>gwt-user</artifactId>
<version>${gwtVersion}</version>
</dependency>
...
</dependencies>
</dependencyManagement>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>gwt-maven-plugin</artifactId>
<version>${gwtMavenPluginVersion}</version>
<dependencies>
<dependency>
<groupId>com.google.gwt</groupId>
<artifactId>gwt-user</artifactId>
<version>${gwtVersion}</version>
</dependency>
...
</dependencies>
...
</plugins>
...
</pluginManagement>
</build>
And in my child pom, using the relationship provided by plugin management (see Maven2 - problem with pluginManagement and parent-child relationship), I just declare the plugin dependency:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>gwt-maven-plugin</artifactId>
</plugin>
Now if I change the version in the properties, it is automatically impacting all direct dependencies and plugin dependencies.
For a parent POM to control which plugin versions the child uses, you should declare the <plugin> in a <pluginManagement> section of the parent POM.
You defined com.google.gwt:gwt-user as a <dependency> in the <dependencyManagement> section.
I'm not sure if you are intending to use gwt-user as a plugin or as a dependency, but it should be listed as the same entity in both for inheritance to work.
The other possibility is to import all the dependencies of the parent POM:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>gwt-maven-plugin</artifactId>
<version>2.4.0</version>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>${project.artifactId}</artifactId>
<version>${project.version}</version>
</dependency>
...
</dependencies>
...
</plugin>
Not the most beautiful solution, but working :-)
In my case I was using the jetty maven plugin, with a dependency on hsqldb. I copied some sample lines from the sonatype book (I think that's where I got the lines from) for using the jetty plugin, which specified the groupId as hsqldb. I am using version 2.3.2 of hsqldb. In my parent pom in the dependencyManagement section and my persistence module the groupId is org.hsqldb. Having mismatched groupIds was what was causing me to get an error, because under that old groupId there isn't a version 2.3.2. Once I changed the groupId from hsqldb to org.hsqldb everything started working.

Categories

Resources