Custom maven plugin fails when mojo extends mojo from different module (no AbstractMojo) - maven

I have mutli project with 2 maven plugin modules: base and child (<packaging>maven-plugin</packaging>). Child depend on base.
Base plugin has single class:
public abstract class BaseMojo extends AbstractMojo {}
with POM:
<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>
<parent>
<groupId>plugin-set</groupId>
<artifactId>plugin-set</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>plugin-base</artifactId>
<packaging>maven-plugin</packaging>
<dependencies>
<dependency>
<groupId>org.apache.maven.plugin-tools</groupId>
<artifactId>maven-plugin-annotations</artifactId>
<version>3.4</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-core</artifactId>
<version>3.3.3</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-plugin-plugin</artifactId>
<version>3.4</version>
<configuration>
<goalPrefix>my</goalPrefix>
<skipErrorNoDescriptorsFound>true</skipErrorNoDescriptorsFound>
</configuration>
<executions>
<execution>
<id>mojo-descriptor</id>
<goals>
<goal>descriptor</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Child plugin has single class:
public abstract class ChildMojo extends BaseMojo {}
with POM:
<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>
<parent>
<groupId>plugin-set</groupId>
<artifactId>plugin-set</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>plugin-child</artifactId>
<packaging>maven-plugin</packaging>
<dependencies>
<dependency>
<groupId>org.apache.maven.plugin-tools</groupId>
<artifactId>maven-plugin-annotations</artifactId>
<version>3.4</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-core</artifactId>
<version>3.3.3</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>plugin-set</groupId>
<artifactId>plugin-base</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-plugin-plugin</artifactId>
<version>3.4</version>
<configuration>
<goalPrefix>my-child</goalPrefix>
<skipErrorNoDescriptorsFound>true</skipErrorNoDescriptorsFound>
</configuration>
<executions>
<execution>
<id>mojo-descriptor</id>
<goals>
<goal>descriptor</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Base compiles correctly, child pass compilation but fails maven-plugin-plugin:3.4:descriptor:
Failed to execute goal org.apache.maven.plugins:maven-plugin-plugin:3.4:descriptor (default-descriptor) on project plugin-child: The API of the mojo scanner is not compatible with this plugin version. Please check the plugin dependencies configured in the POM and ensure the versions match. org/apache/maven/plugin/AbstractMojo: org.apache.maven.plugin.AbstractMojo -> [Help 1]
How to build child module?
Both base and child has almost identical pom.xml, child has 1 more dependency: to base
Source: https://github.com/michaldo/mojo-extend-mojo

The direct solution to your compilation issue is to remove <scope>provided</scope> from the maven-core dependency in plugin-child.
However, although it will compile after that, there are a lot of changes to be made to your project for it to work.
You should have a clear view of what a Mojo is and how it is implemented.
First of all, a Mojo should comply to a simple contract, which is implementing the Mojo interface.
Although the requirements on Mojos are minimal by design, there are still a very few requirements that Mojo developers must keep in mind. Basically, these Mojo requirements are embodied by the org.apache.maven.plugin.Mojo interface, which the Mojo must implement (or else extend its abstract base class counterpart org.apache.maven.plugin.AbstractMojo).
You can have a hierarchy of abstract classes but the top-most abstract one should inherit from AbstractMojo (or implement Mojo). Having a common abstract parent class is not uncommon. It is done by a lot of standard Maven plugins, like the maven-install-plugin.
What is important to note that the abstract classes are simply there to factor common code from multiple Mojo in a plugin. They do not represent a goal. As such, the plugin-base module, which contains your abstract superclass:
should not be packaged as a maven-plugin.
should not declare an execution of the maven-plugin-plugin plugin.
The concrete Mojo is inside plugin-child so it is this module that should be packaged as a maven-plugin. Since this will be the concrete implementation, it must not be abstract and it can be annotated with #Mojo to ease its declaration:
#Mojo(name = "child")
public class ChildMojo extends BaseMojo {
#Override
public void execute() throws MojoExecutionException, MojoFailureException {
}
}
This declares the goal "child" for this Mojo.
Sample code
plugin-base
<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>
<parent>
<groupId>plugin-set</groupId>
<artifactId>plugin-set</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>plugin-base</artifactId>
<dependencies>
<dependency>
<groupId>org.apache.maven.plugin-tools</groupId>
<artifactId>maven-plugin-annotations</artifactId>
<version>3.4</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-core</artifactId>
<version>3.3.3</version>
</dependency>
</dependencies>
</project>
with the only class being
import org.apache.maven.plugin.AbstractMojo;
public abstract class BaseMojo extends AbstractMojo { }
plugin-child
<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>
<parent>
<groupId>plugin-set</groupId>
<artifactId>plugin-set</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>plugin-child</artifactId>
<packaging>maven-plugin</packaging>
<dependencies>
<dependency>
<groupId>org.apache.maven.plugin-tools</groupId>
<artifactId>maven-plugin-annotations</artifactId>
<version>3.4</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-core</artifactId>
<version>3.3.3</version>
</dependency>
<dependency>
<groupId>plugin-set</groupId>
<artifactId>plugin-base</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-plugin-plugin</artifactId>
<version>3.4</version>
<configuration>
<goalPrefix>my-child</goalPrefix>
</configuration>
<executions>
<execution>
<id>mojo-descriptor</id>
<goals>
<goal>descriptor</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
with the following Java code:
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.Mojo;
#Mojo(name = "child")
public class ChildMojo extends BaseMojo {
#Override
public void execute() throws MojoExecutionException, MojoFailureException {
}
}
Finally, you can test that this works by depending on this plugin:
<plugin>
<groupId>plugin-set</groupId>
<artifactId>plugin-child</artifactId>
<version>0.0.1-SNAPSHOT</version>
<executions>
<execution>
<id>foo</id>
<goals>
<goal>child</goal>
</goals>
<phase>install</phase>
</execution>
</executions>
</plugin>
If you build the test project depending on plugin-child then you will correctly see Maven invoking it, on the install phase here.

Related

Spring Boot App with Maven and Wildly (26.1.1) - PAGE NOT FOUND Error

I have created a Spring Boot application. I use WildFly as the application server - this is what I want to use to run the application.
These are the Java and Maven related files I have:
#RestController
public class MyController {
#Autowired
private Student student;
#GetMapping(value="/index")
public String sayHello() {
return "Hello";
}
}
Of course I have the main method with the Spring Boot related annotations:
#SpringBootApplication
public class SpringBootTestApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootTestApplication.class, args);
}
}
I have the Maven file like this:
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.2</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<groupId>com.globalsoftwaresupport</groupId>
<artifactId>spring-boot-test</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spring-boot-test</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>17</java.version>
<deploy.jboss.host>127.0.0.1</deploy.jboss.host>
<deploy.jboss.port>9990</deploy.jboss.port>
<deploy.jboss.username>balazs</deploy.jboss.username>
<deploy.jboss.password>balazs1990</deploy.jboss.password>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
<plugin>
<groupId>org.wildfly.plugins</groupId>
<artifactId>wildfly-maven-plugin</artifactId>
<version>2.0.2.Final</version>
<executions>
<execution>
<phase>install</phase>
<goals>
<goal>deploy</goal>
</goals>
</execution>
</executions>
<configuration>
<filename>${project.build.finalName}.war</filename>
<hostname>${deploy.jboss.host}</hostname>
<port>${deploy.jboss.port}</port>
<username>${deploy.jboss.username}</username>
<password>${deploy.jboss.password}</password>
</configuration>
</plugin>
</plugins>
</build>
<packaging>war</packaging>
When I build the project with mvn clean install then Maven compiles and deployed the app to the Wildfly server.
So far so good I have the application on the server. First of all:
1.) is it not a problem that I have the SNAPSHOT present in the context root?
2.) another problem is that I can not run the application - I start WildFly server in Eclipse and I check the context root.
Can you help me why is this happening? Thank you for your help in advance!

No schemas have been found - Spring Boot WS

I have the next throuble:
When I follow the Spring boot WS example with maven, when I follow the steps, after add the xsd file, the guide indicate how to add the plugin to pom.xml file and this automatically turn the xsd file into java class objects. But I've received this:
No schemas have been found (org.codehaus.mojo:jaxb2-maven-plugin:1.6:xjc:xjc:generate-sources)
org.apache.maven.plugin.MojoExecutionException: No schemas have been found
at org.codehaus.mojo.jaxb2.AbstractXjcMojo.execute(AbstractXjcMojo.java:376)
at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:134)
at org.eclipse.m2e.core.internal.embedder.MavenImpl.execute(MavenImpl.java:331)
at org.eclipse.m2e.core.internal.embedder.MavenImpl$11.call(MavenImpl.java:1362)
...
Here is my pom.xml:
<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.tester</groupId>
<artifactId>test-ws</artifactId>
<version>0.0.1</version>
<packaging>war</packaging>
<name>test-ws</name>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.10.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web-services</artifactId>
</dependency>
<dependency>
<groupId>wsdl4j</groupId>
<artifactId>wsdl4j</artifactId>
</dependency>
</dependencies>
<properties>
<java.version>1.7</java.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>jaxb2-maven-plugin</artifactId>
<version>1.6</version>
<executions>
<execution>
<id>xjc</id>
<goals>
<goal>xjc</goal>
</goals>
</execution>
</executions>
<configuration>
<schemaDirectory>${project.basedir}/src/main/resources/</schemaDirectory>
<outputDirectory>${project.basedir}/src/main/java</outputDirectory>
<clearOutputDir>false</clearOutputDir>
</configuration>
</plugin>
</plugins>
</build>
This is a screenshot how is look like the error:
Any help is appreciated!
Ok, if someone has the same error, I got the solution like this:
First, I configured the maven user settings in eclipse by adding a separate repository folder for the related project (Override the default path located in X:\Users\User.m2\repository).
I removed two custom profiles that I had in the previous file.
I updated the project and magically, the error disappeared.
Thanks to all for the help.

Maven plugin default phase

I am trying to write a Hello World Maven plugin.
I assigned defaultPhase=LifecyclePhase.CLEAN to it but when I execute mvn clean it is not working.
When I execute mvn gorov:clean it is working.
Any suggestions?
DS
The code is:
Location in project: maven-plugin\src\main\java\com\gorovdude\plugins\maven\mojos\WriteConsoleMojo.java
package com.gorovdude.plugins.maven.mojos;
import java.io.File;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
#Mojo(name = "clean", defaultPhase = LifecyclePhase.CLEAN, threadSafe = true, aggregator = true)
public class WriteConsoleMojo extends AbstractMojo {
public void execute() throws MojoExecutionException, MojoFailureException {
try {
String path = "C:\\Apache-maven-3.2.5\\testing.txt";
System.out.println("testing");
File f = new File(path);
f.createNewFile();
} catch (Exception e) {
throw new MojoExecutionException(e.getMessage(), e);
}
}
}
The pom.xml of the plugin:
Location in maven-plugin\pom.xml
<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.gorovdude</groupId>
<artifactId>gorov-maven-plugin</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>maven-plugin</packaging>
<description>gorov Maven Plugin</description>
<properties>
<mavenVersion>3.0</mavenVersion>
<mavenPluginVersion>3.1</mavenPluginVersion>
</properties>
<prerequisites>
<maven>${mavenVersion}</maven>
</prerequisites>
<dependencies>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-core</artifactId>
<version>${mavenVersion}</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-plugin-api</artifactId>
<version>${mavenVersion}</version>
</dependency>
<dependency>
<groupId>org.apache.maven.plugin-tools</groupId>
<artifactId>maven-plugin-annotations</artifactId>
<version>${mavenPluginVersion}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-artifact</artifactId>
<version>2.0.9</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-plugin-plugin</artifactId>
<version>${mavenPluginVersion}</version>
<executions>
<execution>
<id>generate-descriptor</id>
<goals>
<goal>descriptor</goal>
</goals>
</execution>
</executions>
<configuration>
<goalPrefix>gorov</goalPrefix>
<skipErrorNoDescriptorsFound>true</skipErrorNoDescriptorsFound>
</configuration>
</plugin>
</plugins>
</build>
</project>
The pom.xml that I run mvn commands on:
Location in Project: maven-plugin\src\test\pom.xml
<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.gorovdude</groupId>
<artifactId>test-gorov-maven-plugin</artifactId>
<version>0.0.1-SNAPSHOT</version>
<description>Testing the plugin</description>
<build>
<plugins>
<plugin>
<groupId>com.gorovdude</groupId>
<artifactId>gorov-maven-plugin</artifactId>
<version>0.0.1-SNAPSHOT</version>
</plugin>
</plugins>
</build>
</project>
Your source code of the plugin can be called as following
<build>
<plugins>
<plugin>
<groupId>com.gorovdude</groupId>
<artifactId>gorov-maven-plugin</artifactId>
<version>0.0.1-SNAPSHOT</version>
<executions>
<execution>
<goals>
<goal>clean</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
You have to specify the goal in the executions. if you type "maven clean", you just call the maven clean plugin, not yours. A plugin may contain multiple goals, unless you define in the executions of you project, which the goals you want to run, they won't run.
Look here: https://maven.apache.org/guides/plugin/guide-java-plugin-development.html
See the help text if you enter just mvn:
No goals have been specified for this build. You must specify a valid
lifecycle phase or a goal in the format <plugin-prefix>:<goal> [...].
Available lifecycle phases are: [...] , clean, [...].
If you enter mvn clean you're not invoking the clean goal of your plugin but the clean phase of the clean lifecycle (which has the clean goal of the [maven-]clean[-plugin] plugin bound to it by default).
If you enter mvn gorov:clean you're using the plugin prefix gorov declared in <goalPrefix>gorov</goalPrefix> in your plugin's POM (though this declaration wouldn't be necessary since the same prefix would be derived from the artifact ID of your plugin gorov-maven-plugin by default).
See also Maven: Lifecycle vs. Phase vs. Plugin vs. Goal.

NoSuchFieldError: RESOURCE_PREFIX with a maven project using tess4j

tess4j is an OCR packed with native library, I made a maven project to test it,
I did add the installation path of maven to eclipse.
I added M2_HOME, MAVEN_HOME and JAVA_HOME env variable,
here is my parent pom
<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>fr.mssb.ongoing</groupId>
<artifactId>ongoing-parent</artifactId>
<packaging>pom</packaging>
<version>1.0</version>
<name>ongoing</name>
<modules>
<module>capcha-solver</module>
</modules>
<build>
<pluginManagement>
<plugins>
<!-- All project will be interpreted (source) and compiled (target) in java 7 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
<!-- this will make eclipse:eclipse goal work and make the project Eclipse compatible -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-eclipse-plugin</artifactId>
<version>2.5.1</version>
<configuration>
<downloadSources>true</downloadSources>
<downloadJavadocs>true</downloadJavadocs>
<classpathContainers>
<classpathContainer>org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7</classpathContainer>
</classpathContainers>
<additionalBuildcommands>
<buildcommand>net.sf.eclipsecs.core.CheckstyleBuilder</buildcommand>
</additionalBuildcommands>
<additionalProjectnatures>
<projectnature>net.sf.eclipsecs.core.CheckstyleNature</projectnature>
</additionalProjectnatures>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
<!-- All child pom will inherit those dependancies -->
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
and here is my child pom
<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>
<parent>
<groupId>fr.mssb.ongoing</groupId>
<artifactId>ongoing-parent</artifactId>
<version>1.0</version>
</parent>
<groupId>fr.mssb.ongoing</groupId>
<artifactId>capcha-solver</artifactId>
<version>1.0</version>
<packaging>jar</packaging> <!-- I think this is useless -->
<name>A capcha solver based on terassec ocr</name>
<build>
<plugins>
<!-- autorun unit tests during maven compilation -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<argLine>-Xmx1024m -XX:MaxPermSize=256m -XX:-UseSplitVerifier</argLine>
<skipTests>-DskipTests</skipTests>
</configuration>
</plugin>
<!-- this should make the tesseract ocr native dll work without doing anything -->
<plugin>
<groupId>com.googlecode.mavennatives</groupId>
<artifactId>maven-nativedependencies-plugin</artifactId>
<version>0.0.7</version>
<executions>
<execution>
<id>unpacknatives</id>
<goals>
<goal>copy</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<!--
Log4j 2 is broken up in an API and an implementation (core), where the API
provides the interface that applications should code to. Strictly speaking
Log4j core is only needed at runtime and not at compile time.
However, below we list Log4j core as a compile time dependency to improve
the startup time for custom plugins.
-->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.1</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.1</version>
</dependency>
<!--
Integration of tesseract OCR
-->
<dependency>
<groupId>net.sourceforge.tess4j</groupId>
<artifactId>tess4j</artifactId>
<version>1.4.1</version>
</dependency>
</dependencies>
</project>
and of course, the code (taken from tess4j example)
package test;
import java.io.File;
import net.sourceforge.tess4j.Tesseract;
import net.sourceforge.tess4j.TesseractException;
/**
* Classe d'exemple.
*/
public class TesseractExample {
public static void main(String[] args) {
File imageFile = new File("C:\\DEV\\repo\\ongoing\\capcha-solver\\src\\test\\resources\\random.jpg");
Tesseract instance = Tesseract.getInstance(); // JNA Interface Mapping
// Tesseract1 instance = new Tesseract1(); // JNA Direct Mapping
try {
String result = instance.doOCR(imageFile);
System.out.println(result);
} catch (TesseractException e) {
System.err.println(e.getMessage());
}
}
}
When I lauch it I'm getting this exception
Exception in thread "main" java.lang.NoSuchFieldError: RESOURCE_PREFIX
at net.sourceforge.tess4j.util.LoadLibs.<clinit>(LoadLibs.java:60)
at net.sourceforge.tess4j.TessAPI.<clinit>(TessAPI.java:40)
at net.sourceforge.tess4j.Tesseract.init(Tesseract.java:303)
at net.sourceforge.tess4j.Tesseract.doOCR(Tesseract.java:239)
at net.sourceforge.tess4j.Tesseract.doOCR(Tesseract.java:188)
at net.sourceforge.tess4j.Tesseract.doOCR(Tesseract.java:172)
at test.TesseractExample.main(TesseractExample.java:19)
I don't know if this is tess4j related or a JNA/JNI problem, as you can see I have a plugin that "should" (never worked with DLLs before) make them work.
Also in the parent pom my plugin are betwen plugin managment tags, I think I should have put them betwen build tags, no?
Any idea?
Thanks.
There was 2 problems
1/ some dlls and files from tess4j had to be copied to the project root directory
2/ tess4j had a transitive dependancy toward com.sun.jna:jna:jar:3.0.9 conflicting with net.java.dev.jna:jna:jar:4.1.0 (also from tess4j) ecluding the 3.0.9 version makes everything work, the RESSOURCE_PREFIX error was coming from that
pom.xml for 32 bit version (you need a 32 bit JVM installed) which takes care of those 2 things, change win32-x86 to win32-x86-64 if you want to use this in 64 bits
<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>fr.mssb.ocr</groupId>
<artifactId>tesseractOcr</artifactId>
<version>1.0</version>
<packaging>jar</packaging>
<name>tesseract ocr project</name>
<build>
<plugins>
<!--
this extract the 32 bits dll and the tesseractdata folder to
the project root from tess4j.jar
-->
<plugin>
<groupId>org.apache.portals.jetspeed-2</groupId>
<artifactId>jetspeed-unpack-maven-plugin</artifactId>
<version>2.2.2</version>
<dependencies>
<dependency>
<groupId>net.sourceforge.tess4j</groupId>
<artifactId>tess4j</artifactId>
<version>1.4.1</version>
</dependency>
</dependencies>
<executions>
<execution>
<id>unpack-step</id>
<phase>compile</phase>
<goals>
<goal>unpack</goal>
</goals>
<configuration>
<unpack>
<artifact>net.sourceforge.tess4j:tess4j:jar</artifact>
<overwrite>true</overwrite>
<resources combine.children="append">
<resource>
<path>win32-x86</path>
<destination>../</destination>
<overwrite>true</overwrite>
<flat>true</flat>
<include>*</include>
</resource>
<resource>
<path>tessdata</path>
<destination>../tessdata</destination>
<overwrite>true</overwrite>
<flat>true</flat>
<include>*</include>
</resource>
<resource>
<path>tessdata/configs</path>
<destination>../tessdata/configs</destination>
<overwrite>true</overwrite>
<flat>true</flat>
<include>*</include>
</resource>
</resources>
</unpack>
<verbose>true</verbose>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>net.sourceforge.tess4j</groupId>
<artifactId>tess4j</artifactId>
<version>1.4.1</version>
<exclusions>
<exclusion>
<groupId>com.sun.jna</groupId>
<artifactId>jna</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
</project>
The child pom could be easily built without any problems and manually copying libs, this is not TESS4J related.
Anyway the jna 3.0.9 could be removed if not needed anymore: https://github.com/nguyenq/tess4j/issues/8
Still, all you have to do to run tess4j is the maven dependency:
<dependency>
<groupId>net.sourceforge.tess4j</groupId>
<artifactId>tess4j</artifactId>
<version>1.4.1</version>
</dependency>
and the correct use of the TESS4J-API, for example:
File imageFile = new File("C:\\random.png");
Tesseract instance = Tesseract.getInstance();
//In case you don't have your own tessdata, let it also be extracted for you
File tessDataFolder = LoadLibs.extractTessResources("tessdata");
//Set the tessdata path
instance.setDatapath(tessDataFolder.getAbsolutePath());
try {
String result = instance.doOCR(imageFile);
System.out.println(result);
} catch (TesseractException e) {
System.err.println(e.getMessage());
}
That's it!
The problem is caused by the conflict between net.java.dev.jna:jna and com.sun.jna:jna. Both jars contain a class com.sun.jna.Platform. Both jars are declared as tess4j dependencies. To solve this you can omit the second dependency in your pom:
<dependency>
<groupId>net.sourceforge.tess4j</groupId>
<artifactId>tess4j</artifactId>
<version>1.4.1</version>
<exclusions>
<exclusion>
<groupId>com.sun.jna</groupId>
<artifactId>jna</artifactId>
</exclusion>
</exclusions>
</dependency>
because the JNA version mismatch. you are using more than one version in class path library. just use one version of JNA.

Maven, JUnit and Dagger - Dagger module could not be loaded

Note: I am building/testing via command line only.
I am running into an issue using Dagger, and have been able to reproduce the same issue in a very small test project. When trying to use Dagger in a unit test, I get the following error while running 'mvn clean test':
sanity(com.mycompany.app.AppTest): Module adapter for class com.mycompany.app.AppTest$TestModule could not be loaded. Please ensure that code generation was run for this module.
In the application, Dagger is compiling/building just fine, and injection is working great. The only issue is with the unit tests, and I feel that the unit tests arent picking up the results from the dagger-compiler, but am not sure how to test/fix this.
pom.xml:
<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.mycompany.app</groupId>
<artifactId>my-app</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>my-app</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.7</source>
<target>1.7</target>
<compilerArgument>-proc:none</compilerArgument>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
<dependencies>
<dependency>
<groupId>com.squareup.dagger</groupId>
<artifactId>dagger</artifactId>
<version>1.2.2</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.squareup.dagger</groupId>
<artifactId>dagger-compiler</artifactId>
<version>1.2.2</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.8.2</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
AppTest.java
package com.audible.hushpuppy.dagger;
import org.junit.Before;
import org.junit.Test;
import dagger.Module;
import dagger.ObjectGraph;
import static org.junit.Assert.assertNull;
public class AppTest {
#Module(injects = AppTest.class)
public class TestModule{
}
#Before
public void setUp() throws Exception {
ObjectGraph.create(new TestModule());
}
#Test
public void sanity() throws Exception {
assertNull(null);
}
}
Aha - apparently annotation processing was completely turned off in an earlier commit, and I completely missed this line in the pom:
<compilerArgument>-proc:none</compilerArgument>

Resources