I included Client files to get port and some utils which commonly used at client in the jar which I generate to consume some web services, the problem I am facing is even for a small change in client files I need to generate and compile all the WSDL classes which has no modification.
Is there any way only to compile externally added classes and reuse already genarated class and create jar file.
Below is the pom.xml I am using
< 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.logicsector</groupId>
<artifactId>My-client</artifactId>
<version>1.0</version>
<name>SOAP </name>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxws</artifactId>
<version>2.1.2</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http</artifactId>
<version>2.1.2</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
</dependencies>
<build>
<finalName>My-client</finalName>
<plugins>
<!-- Generate Java classes from WSDL during build -->
<plugin>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-codegen-plugin</artifactId>
<version>2.1.2</version>
<executions>
<execution>
<id>generate-sources</id>
<phase>generate-sources</phase>
<configuration>
<sourceRoot>${project.build.directory}/generated/cxf</sourceRoot>
<wsdlOptions>
<wsdlOption>
<dataBinding>jaxb</dataBinding>
<wsdl><!-- My WSDL URL http://domain:port/path--></wsdl>
<extraargs>
<extraarg>-keep</extraarg>
<extraarg>-client</extraarg>
<extraarg>-exsh</extraarg>
<extraarg>true</extraarg>
</extraargs>
<BindingFiles>
<BindingFile>${basedir}/binding.xjb</BindingFile>
</BindingFiles>
</wsdlOption>
</wsdlOptions>
</configuration>
<goals>
<goal>wsdl2java</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Add generated sources - avoids having to copy generated sources to build location -->
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<executions>
<execution>
<id>add-source</id>
<phase>generate-sources</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>${basedir}/target/generated/src/main/java</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
<!-- Build the JAR with dependencies -->
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<phase>install</phase>
<configuration>
<tasks>
<copy todir="../lib">
<fileset file="target/my-client.jar" />
</copy>
</tasks>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Thanks in advance
Related
I have an app that consists of two main modules: backend and frontend.
Backend is written in SpringBoot, with SpringMVC.
Frontend is Angular.
I would like to build the app and for all the frontend paths to have a prefix "/app-frontend" so that I can easily ignore them from the SpringBoot security configurations. How can I achieve this? What I have until now is the following:
fronent pom.xml:
<?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>com.demo.app</groupId>
<artifactId>demo-app</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>demo-app-frontend</artifactId>
<packaging>jar</packaging>
<build>
<resources>
<resource>
<!-- we copy the content of the frontend directory in the final artifact -->
<directory>./dist/demo-app-frontend</directory>
<targetPath>static</targetPath>
</resource>
</resources>
<plugins>
<!-- clean the dist directory used by Angular -->
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<filesets>
<fileset>
<directory>dist</directory>
</fileset>
</filesets>
</configuration>
</plugin>
<plugin>
<groupId>com.github.eirslett</groupId>
<artifactId>frontend-maven-plugin</artifactId>
<version>1.11.2</version>
<configuration>
<workingDirectory>./</workingDirectory>
<nodeVersion>v14.18.0</nodeVersion>
<npmVersion>6.14.15</npmVersion>
</configuration>
<executions>
<execution>
<id>install node and npm</id>
<goals>
<goal>install-node-and-npm</goal>
</goals>
</execution>
<execution>
<id>npm install</id>
<goals>
<goal>npm</goal>
</goals>
</execution>
<execution>
<id>npm run build</id>
<goals>
<goal>npm</goal>
</goals>
<configuration>
<arguments>run pipeline-build</arguments>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
backend pom.xml:
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>demo-app-frontend</artifactId>
<version>${project.version}</version>
<type>jar</type>
</dependency>
</dependencies>
...
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<id>merge</id>
<phase>initialize</phase>
<goals>
<goal>unpack</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>com.demo.app</groupId>
<artifactId>demo-app-frontend</artifactId>
<type>jar</type>
<overWrite>true</overWrite>
<outputDirectory>${project.build.directory}/classes</outputDirectory>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
The build passes and I can start UI by running the jar and accessing localhost:8080 but I do not know what changes I need to do for the UI to be accessible at localhost:8080/frontend-app
Within a larger Maven project, I have a Java file (AudioFileBuilder.java) that generates audio files from the Google Cloud Text-to-Speech service. It can execute from its own main() class; however, this file references an enumeration within the project (that other project source files depend on).
I am creating a fat JAR (JAR-with-dependencies), .exe file (Windows), and .app file (macOS) for the main project. I would like to exclude the AudioFileBuilder.java file AND the associated Google Cloud Text-to-Speech dependency in the JAR, exe, and app files. However, I still need the AudioFileBuilder.java file to run every time the project is built.
Here is a link to my project's current POM file (the project is open-source):
https://github.com/hadi16/GamesForTheBlind/blob/Alex-Branch/pom.xml
This is my current POM 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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>edu.up</groupId>
<artifactId>Games_For_Blind</artifactId>
<version>1.0.0.0</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<packaging>jar</packaging>
<dependencies>
<!-- Compile Dependencies -->
<dependency>
<groupId>com.google.cloud</groupId>
<artifactId>google-cloud-texttospeech</artifactId>
<version>0.117.0-beta</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.1</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
<version>2.3.2</version>
<scope>compile</scope>
</dependency>
<!-- Test Dependencies -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.2</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>12</source>
<target>12</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.1.1</version>
<configuration>
<outputDirectory>${project.build.directory}/dist</outputDirectory>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>gamesforblind.Main</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>assemble-all</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>copy-resources</id>
<phase>process-classes</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${project.build.outputDirectory}</outputDirectory>
<resources>
<resource>
<directory>${basedir}/target/xsd-out</directory>
<filtering>false</filtering>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
<!-- To generate the phrase audio files. -->
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.6.0</version>
<executions>
<execution>
<phase>prepare-package</phase>
<goals>
<goal>exec</goal>
</goals>
</execution>
</executions>
<configuration>
<executable>java</executable>
<arguments>
<argument>-classpath</argument>
<classpath/>
<argument>gamesforblind.synthesizer.AudioFileBuilder</argument>
</arguments>
<environmentVariables>
<GOOGLE_APPLICATION_CREDENTIALS>google_api_key.json</GOOGLE_APPLICATION_CREDENTIALS>
</environmentVariables>
</configuration>
</plugin>
<!-- Create executable Windows file. -->
<plugin>
<groupId>com.akathist.maven.plugins.launch4j</groupId>
<artifactId>launch4j-maven-plugin</artifactId>
<version>1.7.25</version>
<executions>
<execution>
<id>l4j-clui</id>
<phase>package</phase>
<goals>
<goal>launch4j</goal>
</goals>
<configuration>
<headerType>gui</headerType>
<jar>${project.build.directory}/dist/${project.artifactId}-${project.version}-jar-with-dependencies.jar</jar>
<outfile>${project.build.directory}/dist/${project.artifactId}-${project.version}.exe</outfile>
<classPath>
<mainClass>gamesforblind.Main</mainClass>
</classPath>
<jre>
<minVersion>12</minVersion>
<jdkPreference>preferJre</jdkPreference>
</jre>
<versionInfo>
<copyright>2019</copyright>
<fileVersion>${project.version}</fileVersion>
<txtFileVersion>${project.version}</txtFileVersion>
<fileDescription>${project.name}</fileDescription>
<productVersion>${project.version}</productVersion>
<txtProductVersion>${project.version}</txtProductVersion>
<productName>${project.name}</productName>
<internalName>${project.name}</internalName>
<originalFilename>${project.artifactId}-${project.version}.exe</originalFilename>
<companyName>University of Portland</companyName>
</versionInfo>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>de.perdian.maven.plugins</groupId>
<artifactId>macosappbundler-maven-plugin</artifactId>
<version>1.3.0</version>
<configuration>
<plist>
<CFBundleDisplayName>Games For The Blind</CFBundleDisplayName>
<JVMMainClassName>gamesforblind.Main</JVMMainClassName>
<JVMVersion>12</JVMVersion>
<CFBundleDisplayName>Games For The Blind</CFBundleDisplayName>
<CFBundleName>Games For The Blind</CFBundleName>
</plist>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>bundle</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
UPDATE:
I divided the project into two separate modules: "audio-builder" & "application" - as suggested by Welsh.
However, I have a Java enumeration ("Phrases.java") that both the audio-builder & application uses. The audio-builder needs this file to know which audio phrases are currently in the program, while the rest of the application needs this to load in said audio files & call the playback of these files.
So, this made me add the "audio-builder" module as a dependency for the "application" module. Since the Google Cloud dependency is needed at compile-time, this means that it is bundled in the generated JAR, app, and exe files.
These changes can be found here: https://github.com/hadi16/GamesForTheBlind/tree/Maven-Fixes
Root POM file:
<?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>edu.up</groupId>
<artifactId>games-for-the-blind</artifactId>
<version>1.0.0.0</version>
<modules>
<module>games-for-the-blind/audio-builder</module>
<module>games-for-the-blind/application</module>
</modules>
<packaging>pom</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>
Audio-builder POM file:
<?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>edu.up</groupId>
<artifactId>audio-builder</artifactId>
<version>1.0.0.0</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>com.google.cloud</groupId>
<artifactId>google-cloud-texttospeech</artifactId>
<version>0.117.0-beta</version>
<scope>compile</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>12</source>
<target>12</target>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.6.0</version>
<executions>
<execution>
<phase>prepare-package</phase>
<goals>
<goal>exec</goal>
</goals>
</execution>
</executions>
<configuration>
<executable>java</executable>
<arguments>
<argument>-classpath</argument>
<classpath/>
<argument>builder.AudioFileBuilder</argument>
</arguments>
<environmentVariables>
<GOOGLE_APPLICATION_CREDENTIALS>google_api_key.json</GOOGLE_APPLICATION_CREDENTIALS>
</environmentVariables>
</configuration>
</plugin>
</plugins>
</build>
</project>
Application POM file (note the dependency to audio-builder):
<?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>edu.up</groupId>
<artifactId>application</artifactId>
<version>1.0.0.0</version>
<packaging>jar</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- Compile Dependencies -->
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.1</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
<version>2.3.2</version>
<scope>compile</scope>
</dependency>
<!-- Test Dependencies -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>edu.up</groupId>
<artifactId>audio-builder</artifactId>
<version>1.0.0.0</version>
<scope>compile</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.2</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>12</source>
<target>12</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.1.1</version>
<configuration>
<outputDirectory>${project.build.directory}/dist</outputDirectory>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>gamesforblind.Main</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>assemble-all</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>copy-resources</id>
<phase>process-classes</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${project.build.outputDirectory}</outputDirectory>
<resources>
<resource>
<directory>${basedir}/target/xsd-out</directory>
<filtering>false</filtering>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
<!-- Create executable Windows file. -->
<plugin>
<groupId>com.akathist.maven.plugins.launch4j</groupId>
<artifactId>launch4j-maven-plugin</artifactId>
<version>1.7.25</version>
<executions>
<execution>
<id>l4j-clui</id>
<phase>package</phase>
<goals>
<goal>launch4j</goal>
</goals>
<configuration>
<headerType>gui</headerType>
<jar>
${project.build.directory}/dist/${project.artifactId}-${project.version}-jar-with-dependencies.jar
</jar>
<outfile>${project.build.directory}/dist/${project.artifactId}-${project.version}.exe
</outfile>
<classPath>
<mainClass>gamesforblind.Main</mainClass>
</classPath>
<jre>
<minVersion>12</minVersion>
<jdkPreference>preferJre</jdkPreference>
</jre>
<versionInfo>
<copyright>2019</copyright>
<fileVersion>${project.version}</fileVersion>
<txtFileVersion>${project.version}</txtFileVersion>
<fileDescription>${project.name}</fileDescription>
<productVersion>${project.version}</productVersion>
<txtProductVersion>${project.version}</txtProductVersion>
<productName>${project.name}</productName>
<internalName>${project.name}</internalName>
<originalFilename>${project.artifactId}-${project.version}.exe</originalFilename>
<companyName>University of Portland</companyName>
</versionInfo>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>de.perdian.maven.plugins</groupId>
<artifactId>macosappbundler-maven-plugin</artifactId>
<version>1.3.0</version>
<configuration>
<plist>
<CFBundleDisplayName>Games For The Blind</CFBundleDisplayName>
<JVMMainClassName>gamesforblind.Main</JVMMainClassName>
<JVMVersion>12</JVMVersion>
<CFBundleDisplayName>Games For The Blind</CFBundleDisplayName>
<CFBundleName>Games For The Blind</CFBundleName>
</plist>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>bundle</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Thank you!
I would recommend that you split your projects into two sub projects, so you would have for example:
games-for-the-blind/
pom.xml
audio-builder/
pom.xml
application/
pom.xml
Then what you can do is have the audio-builder package output the required files into the application/resources directory and have it listed first in the main pom.xml file.
This would allow you to distribute the application resultant files that would not contain any of the details of the audio-builder project.
I am writing my groovy code in maven using GMaven plugin. when I do mvn clean install it is showing build success but when I checked my target folder it is not generating any jar for me. I am refering this atlassian link in that
<plugins>
<plugin>
<executions>
<execution>
<goals>
<goal>generateStubs</goal>
<goal>compile</goal>
<goal>generateTestStubs</goal>
<goal>testCompile</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
but for this I am getting pom error on execution. please help me out here
Below is my pom 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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.myproject</groupId>
<artifactId>mydata</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>mydata</name>
<url>http://maven.apache.orgurl>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<gmaven.version>1.5</gmaven.version>
<groovy.version>2.1.8</groovy.version>
</properties>
<dependencies>
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy-all</artifactId>
<version>2.4.11</version>
</dependency>
</dependencies>
<build>
<!-- <pluginManagement> -->
<plugins>
<plugin>
<groupId>org.codehaus.gmaven</groupId>
<artifactId>gmaven-plugin</artifactId>
<version>${gmaven.version}</version>
<configuration>
<providerSelection>2.0</providerSelection>
</configuration>
<dependencies>
<dependency>
<groupId>org.codehaus.gmaven.runtime</groupId>
<artifactId>gmaven-runtime-2.0</artifactId>
<version>${gmaven.version}</version>
</dependency>
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy-all</artifactId>
<version>${groovy.version}</version>
</dependency>
</dependencies>
<!-- <executions>
<execution>
<goals>
<goal>generateStubs</goal>
<goal>compile</goal>
<goal>generateTestStubs</goal>
<goal>testCompile</goal>
</goals>
</execution>
</executions> -->
</plugin>
</plugins>
<!-- </pluginManagement> -->
</build>
</project>
UPDATE 1:
I am able to see the jar but it does not have my groovy code
Can you please try the following:
<plugin>
<groupId>org.codehaus.gmavenplus</groupId>
<artifactId>gmavenplus-plugin</artifactId>
<version>1.5</version>
<executions>
<execution>
<goals>
<goal>addSources</goal>
<goal>compile</goal>
</goals>
</execution>
</executions>
<configuration>
<sources>
<source>
<directory>${project.basedir}/src</directory>
<includes>
<include>**/*.groovy</include>
</includes>
</source>
</sources>
</configuration>
</plugin>
Actually that's what I'm using and jar is correctly generated
PS: Make sure that source.directory points to where your .groovy files exist
What is the recommended Maven setup for using Dagger 2 in a mixed Java/Kotlin project?
I found a sample project which uses Gradle: https://github.com/damianpetla/kotlin-dagger-example
Something similar with Maven would be very helpful.
UPDATE: What have I tried?
I used the Kotlin configuration from kotlinlang.org/docs/reference/using-maven.html
and the Dagger configuration from google.github.io/dagger.
I also used the build-helper-maven-plugin plugin to integrate the annotation processing in IDEA.
My main problem was that I run into compilation cycles. My configuration mixed the compilation of Kotlin and calling the annotation processor, which generates Dagger2 classes. I unsystematically tried to separate both phases but lacked the deeper Maven understanding to get it working.
javac can scan both source files (java) and classes in search for annotations:
http://docs.oracle.com/javase/7/docs/technotes/tools/windows/javac.html#processing
This means that you can make this work if you don't have any Dagger-generated classes referenced in Kotlin code (which means Dagger module implementations)
invoke kotlin compiler (no Dagger generated types in Kotlin code)
invoke annotation processor (processes annotations in both java files and kotlin-compiled files)
invoke java compiler - has access to both Dagger generated types and Kotlin types
You can write your services in both java and kotlin, but the module must be created by a java class
Here is the corresponding pom.xml
<?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.test</groupId>
<artifactId>testkotlindagger</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<kotlin.version>1.0.6</kotlin.version>
<dagger2.version>2.7</dagger2.version>
</properties>
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib</artifactId>
<version>${kotlin.version}</version>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-test</artifactId>
<version>${kotlin.version}</version>
<scope>test</scope>
</dependency>
<!-- Dagger 2 -->
<dependency>
<groupId>com.google.dagger</groupId>
<artifactId>dagger</artifactId>
<version>${dagger2.version}</version>
</dependency>
<dependency>
<groupId>com.google.dagger</groupId>
<artifactId>dagger-compiler</artifactId>
<version>${dagger2.version}</version>
<optional>true</optional>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>kotlin-maven-plugin</artifactId>
<groupId>org.jetbrains.kotlin</groupId>
<version>${kotlin.version}</version>
<executions>
<execution>
<id>compile</id>
<phase>compile</phase>
<goals> <goal>compile</goal> </goals>
<configuration>
<sourceDirs>
<source>src/main/java</source>
<source>src/main/kotlin</source>
</sourceDirs>
</configuration>
</execution>
<execution>
<id>test-compile</id>
<phase>test-compile</phase>
<goals> <goal>test-compile</goal> </goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.bsc.maven</groupId>
<artifactId>maven-processor-plugin</artifactId>
<version>2.2.4</version>
<executions>
<execution>
<id>process</id>
<goals>
<goal>process</goal>
</goals>
<phase>compile</phase>
<configuration>
<outputDirectory>target/generated-sources/annotations</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<executions>
<!-- Replacing default-compile as it is treated specially by maven -->
<execution>
<id>default-compile</id>
<phase>none</phase>
</execution>
<!-- Replacing default-testCompile as it is treated specially by maven -->
<execution>
<id>default-testCompile</id>
<phase>none</phase>
</execution>
<execution>
<id>java-compile</id>
<phase>compile</phase>
<goals> <goal>compile</goal> </goals>
</execution>
<execution>
<id>java-test-compile</id>
<phase>test-compile</phase>
<goals> <goal>testCompile</goal> </goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
On the other hand, if you include Dagger-generated types in your kotlin code, you must have these available before kotlin code is compiled, which means you need Kotlin-aware annotation processor (KAPT)
In this scenario the problem boils down to the question:
Is kapt supported in maven?
Sadly, the answer is no, but there is a bug filed to support it:
https://youtrack.jetbrains.com/issue/KT-14478
Since kapt is now supported in maven, you can write your services in both Java and Kotlin, and the module can be created by either a Java class or a Kotlin class. You can configure pom.xml build file like this:
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib</artifactId>
<version>1.7.20</version>
</dependency>
<dependency>
<groupId>com.google.dagger</groupId>
<artifactId>dagger</artifactId>
<version>2.22</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<version>${kotlin.version}</version>
<executions>
<execution>
<id>kapt</id>
<goals>
<goal>kapt</goal>
</goals>
<configuration>
<sourceDirs>
<sourceDir>src/main/kotlin</sourceDir>
<sourceDir>src/main/java</sourceDir>
</sourceDirs>
<annotationProcessorPaths>
<!-- Specify your annotation processors here. -->
<annotationProcessorPath>
<groupId>com.google.dagger</groupId>
<artifactId>dagger-compiler</artifactId>
<version>2.22</version>
</annotationProcessorPath>
</annotationProcessorPaths>
</configuration>
</execution>
<execution>
<id>compile</id>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
<configuration>
<sourceDirs>
<sourceDir>src/main/kotlin</sourceDir>
<sourceDir>src/main/java</sourceDir>
</sourceDirs>
</configuration>
</execution>
<execution>
<id>test-compile</id>
<phase>test-compile</phase>
<goals>
<goal>test-compile</goal>
</goals>
<configuration>
<sourceDirs>
<sourceDir>src/test/kotlin</sourceDir>
<sourceDir>src/test/java</sourceDir>
</sourceDirs>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>11</source>
<target>11</target>
</configuration>
<executions>
<execution>
<id>default-compile</id>
<phase>none</phase>
</execution>
<execution>
<id>default-testCompile</id>
<phase>none</phase>
</execution>
<execution>
<id>java-compile</id>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
<execution>
<id>java-test-compile</id>
<phase>test-compile</phase>
<goals>
<goal>testCompile</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
These are the links usefull to read when you want to create maven project with java, kotlin and dagger:
https://www.baeldung.com/kotlin/maven-java-project
https://kotlinlang.org/docs/kapt.html#using-in-maven
https://github.com/google/dagger#installation
Please note that kapt is still not supported for IntelliJ IDEA's own build system. Because of this, you will not be able to compile and run the application in the Intellij IDE by clicking on the Play button next to the Main method. To run the application, first build the project using the maven toolbox. After that, you can run the application in the Intellij IDE by clicking on the Play button next to the Main method. Alternatively you can create a run configuration to run the jar file. After that, you can run this configuration, or run it in debug mode by clicking on the run or debug button next to the run configuration combobox.
This question already has answers here:
Maven archetype for simple Servlet application
(6 answers)
Closed 9 years ago.
For testing purposes, I need to create a very simple Java web application, which will contain only one servlet.
I want to be able to run this web app easily (e. g. by entering mvn jetty:run).
For a Vaadin application I used these calls:
1) mvn archetype:generate
-DarchetypeGroupId=com.vaadin
-DarchetypeArtifactId=vaadin-archetype-clean
-DarchetypeVersion=LATEST
-DgroupId=your.company
-DartifactId=project-name
-Dversion=1.0
-Dpackaging=war
2) mvn eclipse:eclipse
Now I need analogous calls for creating a simple web app with just one servlet.
How can I do it (which Maven command/archetype can I use) ?
Solution
In order to create a skeleton of a web app, do following steps:
1) Run
mvn archetype:generate -DgroupId=ru.mycompany -DartifactId=mywebapp -DarchetypeArtifactId=maven-archetype-webapp -DinteractiveMode=false
2) Put
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>maven-jetty-plugin</artifactId>
<version>7.0.0.pre5</version>
<configuration>
<scanIntervalSeconds>10</scanIntervalSeconds>
<stopKey>foo</stopKey>
<stopPort>9999</stopPort>
</configuration>
<executions>
<execution>
<id>start-jetty</id>
<phase>pre-integration-test</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<scanIntervalSeconds>0</scanIntervalSeconds>
<daemon>true</daemon>
</configuration>
</execution>
<execution>
<id>stop-jetty</id>
<phase>post-integration-test</phase>
<goals>
<goal>stop</goal>
</goals>
</execution>
</executions>
</plugin>
into the pom.xml file such that it looks like this:
<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>ru.mycompany</groupId>
<artifactId>mywebapp</artifactId>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
<name>mywebapp Maven Webapp</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<finalName>mywebapp</finalName>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>maven-jetty-plugin</artifactId>
<version>7.0.0.pre5</version>
<configuration>
<scanIntervalSeconds>10</scanIntervalSeconds>
<stopKey>foo</stopKey>
<stopPort>9999</stopPort>
</configuration>
<executions>
<execution>
<id>start-jetty</id>
<phase>pre-integration-test</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<scanIntervalSeconds>0</scanIntervalSeconds>
<daemon>true</daemon>
</configuration>
</execution>
<execution>
<id>stop-jetty</id>
<phase>post-integration-test</phase>
<goals>
<goal>stop</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
3) Run mvn jetty:run -Djetty.port=PORT and verify that you see a Hello World! lettering in the browser (localhost:PORT/mywebapp), where PORT is the port number you want Jetty to run on.
You will need to create archtype using -DarchetypeArtifactId=maven-archetype-webapp
Also for jetty:run to work you need to update pom.xml with jetty plugin
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>maven-jetty-plugin</artifactId>
<version>7.0.0.pre5</version>
<configuration>
<scanIntervalSeconds>10</scanIntervalSeconds>
<stopKey>foo</stopKey>
<stopPort>9999</stopPort>
</configuration>
<executions>
<execution>
<id>start-jetty</id>
<phase>pre-integration-test</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<scanIntervalSeconds>0</scanIntervalSeconds>
<daemon>true</daemon>
</configuration>
</execution>
<execution>
<id>stop-jetty</id>
<phase>post-integration-test</phase>
<goals>
<goal>stop</goal>
</goals>
</execution>
</executions>
</plugin>
You need to define the servlet in the web.xml.
And the maven configuration (pom.xml) like this:
<build>
<plugins>
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>8.1.8.v20121106</version>
<configuration>
<scanIntervalSeconds>0</scanIntervalSeconds>
<contextPath>/</contextPath>
<connectors>
<connector implementation="org.eclipse.jetty.server.nio.SelectChannelConnector">
<port>8081</port>
<maxIdleTime>60000</maxIdleTime>
</connector>
</connectors>
</configuration>
</plugin>
</plugins>
</build>
Now you can start the web with the command:
mvn compile jetty:run