I have a Java web project using jMUPdf library as an external dependency. As I was not able to find jMUPdf in any public maven repository, I tried to install it to my local m2 repository using install-file
jMUPdf uses jmupdf.jar and a dependent jmupdf64.dll, so I did this:
mvn install:install-file -Dfile=jmupdf.jar -DgroupId=jmupdf -DartifactId=jmupdf -Dversion=0.4.1 -Dpackaging=jar
mvn install:install-file -Dfile=jmupdf64.dll -DgroupId=jmupdf -DartifactId=jmupdfdll64 -Dversion=0.4.1 -Dpackaging=dll
I can see both libraries in my local m2 repository.
This is an excerpt from my pom.xml
<dependency>
<groupId>jmupdf</groupId>
<artifactId>jmupdfdll64</artifactId>
<version>0.4.1</version>
<scope>runtime</scope>
<type>dll</type>
</dependency>
<dependency>
<groupId>jmupdf</groupId>
<artifactId>jmupdf</artifactId>
<version>0.4.1</version>
</dependency>
BUT: After compiling my project (which generates a war file) I only see the jmupdf.jar in \WEB-INF\lib and the DLL is missing. That's of course the reason for a runtime exception regarding the missing jmupdf64.dll
How can I make sure that the dll is part of the resulting war file?
EDIT: ... and that it will also be deployed correctly (e.g. into webapps/MYAPP/WEB-INF/lib on my Tomcat)?
This is my simple solution for my need of integrated security using ms-jdbc...
<dependencies>
<dependency>
<groupId>com.microsoft.sqlserver</groupId>
<artifactId>mssql-jdbc_auth</artifactId>
<version>8.4.1.x64</version>
<type>dll</type>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.microsoft.sqlserver</groupId>
<artifactId>mssql-jdbc</artifactId>
<version>8.4.1.jre14</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>3.1.1</version>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>prepare-package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<excludeScope>provided</excludeScope>
<includeTypes>dll</includeTypes>
<overWriteIfNewer>true</overWriteIfNewer>
<outputDirectory>${project.build.directory}/${project.build.finalName}/WEB-INF/lib</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
Related
I have Spring Boot app running with embedded Tomcat. I'm running it in docker container. When I try to follow this page about spring boot in container and build layered image I recieve error mentioned below when I try to start the container. I know that the best way would be to exclude old version of servlet-api from my dependecies but it's impossible as this dependency stops working while I'm doing that. Unfortunately I cannot also get rid of this dependency. Is there a way to force Spring Boot to use specific implementation from classpath? I've tried Jetty and Undertow and docker successfully started but then lib that is using older version didn't work properly.
Other question is why it's working when I'm copy just jar and start it?
Dockerfile that I'm trying to build:
FROM adoptopenjdk:11-jre-hotspot
ARG DEPENDENCY=target/dep
COPY ${DEPENDENCY}/BOOT-INF/lib /app/lib
COPY ${DEPENDENCY}/META-INF /app/META-INF
COPY ${DEPENDENCY}/BOOT-INF/classes /app
ENTRYPOINT ["java","-cp","app:app/lib/*","com.test.App"]
Dockerfile that works:
FROM adoptopenjdk:11-jre-hotspot
COPY /target/application.jar /app/application.jar
COPY /target/lib /app/lib
ENTRYPOINT ["java", "-jar", "app/application.jar"]
The one that works requires additional plugins in pom.xml to make it possible:
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<id>build-info</id>
<goals>
<goal>build-info</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<finalName>ttom-osm-converter</finalName>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>com.tomtom.mep.App</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>prepare-package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/lib</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
Dependecies from POM:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
<dependency> <!-- lib contains servlet-api-2.5 -->
<groupId>com.test.lib</groupId>
<artifactId>client</artifactId>
<version>${model.client.version}</version>
</dependency>
Error:
java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleException: Failed to start component [NonLoginAuthenticator[StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[/path]
***************************
APPLICATION FAILED TO START
***************************
Description:
An attempt was made to call a method that does not exist. The attempt was made from the following location:
org.apache.catalina.authenticator.AuthenticatorBase.startInternal(AuthenticatorBase.java:1220)
The following method did not exist:
'java.lang.String javax.servlet.ServletContext.getVirtualServerName()'
The method's class, javax.servlet.ServletContext, is available from the following locations:
jar:file:/app/lib/servlet-api-2.5.jar!/javax/servlet/ServletContext.class
jar:file:/app/lib/javax.servlet-api-4.0.1.jar!/javax/servlet/ServletContext.class
jar:file:/app/lib/tomcat-embed-core-9.0.29.jar!/javax/servlet/ServletContext.class
It was loaded from the following location:
file:/app/lib/servlet-api-2.5.jar
Action:
Correct the classpath of your application so that it contains a single, compatible version of javax.servlet.ServletContext
From the error about 'java.lang.String javax.servlet.ServletContext.getVirtualServerName()', we can see that is was added in Servlet 3.1: you should exclude servlet-api:2.5.
Use the following command:
mvn dependency:tree -Dincludes='*:servlet-api'
This will list you all all module/dependencies including servlet-api.
Then excludes the bad version from dependencies: the com.test.lib client should not even includes it in the first place, meaning the dependency should be provided in it as well.
<dependency> <!-- lib contains servlet-api-2.5 -->
<groupId>com.test.lib</groupId>
<artifactId>client</artifactId>
<version>${model.client.version}</version>
<exclusions> <exclusion> <groupId>...</groupId> <artifactId>servlet-api</artifactId> </exclusion> </exclusions>
</dependency>
Do note that the servlet-api groupId changed over the course of time: that's probably one reason why Maven does not select the "good" servlet-api.
And I would advise you to use maven-enforcer-plugin to lock these bad dependencies:
<rules>
<bannedDependencies>
<excludes>
<exclude>*:servlet-api:2.5</exclude>
</excludes>
</bannedDependencies>
</rules>
<fail>true</fail>
See http://maven.apache.org/enforcer/enforcer-rules/bannedDependencies.html for more information.
Now then you mention that your lib (com.test.lib) seems to not work without servlet-api 2.5, which means it use code that was probably removed between Servlet 2.5 and 3.1: your only course of action is to upgrade your lib as to not depends on said code:
The first servlet-api (2.5) is loaded
Tomcat and Spring Boot are compiled against later version
Tomcat/Spring Boot will may try to use a method added in later version
You will have another error and so on.
You can access to path:
~/.m2/repository/javax/servlet/servlet-api
And clear folder serverlet. For example:
rm -rf 2.5
Finally you re-run application and everything is ok.
I have a project called "commons" that contains common includes for both runtime and test.
In the main project I added a dependency for commons:
<dependency>
<groupId>com.alexb</groupId>
<artifactId>commons</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
However the test common files are not included. So I added :
<dependency>
<groupId>com.alexb</groupId>
<artifactId>commons</artifactId>
<version>1.0-SNAPSHOT</version>
<type>test-jar</type>
</dependency>
However when type is test-jar, the runtime is not included.
Unfortunatelly, it seems I cannot include both:
<type>jar,test-jar</type>
What can I do to include both?
As #khmarbaise mentioned in the comments you should separate your test-jar part project.
I presume you have in the commons pom.xml something like this which generates common test-jar.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.1.1</version>
<executions>
<execution>
<goals>
<goal>test-jar</goal>
</goals>
</execution>
</executions>
</plugin>
The problem with this approach is that you don't get the transitive test-scoped dependencies automatically.
Check this link for more details:
https://maven.apache.org/plugins/maven-jar-plugin/examples/create-test-jar.html
I have a working IzPack installer project set up with maven and added following to my install script install.xml to [installation][listeners]:
<listener classname="(company-name).listener.InstallerListener" stage="install"/>
Sadly, the line seems to be ignored and the debugger does not halt on set breakpoints in the InstallListener class. I have read the documentation for InstallListeners, but it is not useful as I have the build process integrated with maven; here are the relevant parts of the Project Object Model pom.xml:
<properties>
<izpack-standalone.version>4.3.1</izpack-standalone.version>
</properties>
<dependencies>
<!-- izpack -->
<dependency>
<groupId>org.codehaus.izpack</groupId>
<artifactId>izpack-standalone-compiler</artifactId>
<version>${izpack-standalone.version}</version>
<optional>true</optional>
</dependency>
</dependencies>
<plugins>
<!-- IzPack compiler -->
<plugin>
<groupId>org.codehaus.izpack</groupId>
<artifactId>izpack-maven-plugin</artifactId>
<version>${org.codehaus.izpack.izpack-maven-plugin.version}</version>
<dependencies>
<dependency>
<groupId>org.codehaus.izpack</groupId>
<artifactId>izpack-standalone-compiler</artifactId>
<version>${izpack-standalone.version}</version>
</dependency>
</dependencies>
<configuration>
<izpackBasedir>${staging.dir}</izpackBasedir>
<customPanelDirectory>${staging.dir}</customPanelDirectory>
</configuration>
<executions>
<execution>
<id>standard-installer</id>
<phase>package</phase>
<goals>
<goal>izpack</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
What am I missing here?
Note: The compiled installer does contain the specified InstallerListener class file, so it is available at runtime.
You must place the jar file containing your panel classes into the {customPanelDirectory}/bin/panels folder where it will be picked up automatically by the izpack-maven-plugin.
In the case above this folder would resolve to {staging.dir}/bin/panels since you configured <customPanelDirectory>${staging.dir}</customPanelDirectory>.
Adding it to install.xml file will not work, since this would be resolved at install time, but not at installer build time.
My Maven project foo.web has its source files in src/main and the test sources in src/test. Of course, the test classes make use of the "main" classes. Now I want to use the test classes in another project during runtime, so I followed these instructions on how to create a test-jar.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<executions>
<execution>
<goals>
<goal>test-jar</goal>
</goals>
</execution>
</executions>
</plugin>
This works perfectly well, a jar like web-SNAPSHOT-tests.jar is created and I can include it in my other project.
<dependency>
<groupId>foo</groupId>
<artifactId>web</artifactId>
<version>SNAPSHOT</version>
<type>test-jar</type>
</dependency>
But it seems like the dependency to web-SNAPSHOT is not correctly set, because at runtime I receive NoClassDefFoundErrors of classes which are available in foo.web. So I added another dependency:
<dependency>
<groupId>foo</groupId>
<artifactId>web</artifactId>
<version>SNAPSHOT</version>
<type>war</type>
<scope>runtime</scope>
</dependency>
Unfortunately, this changes nothing. Does anyone know what is wrong here?
WAR archives are structured differently from JARs. When running in an application server such as Tomcat or JBoss, the server will handle the WAR correctly. Since you are running outside of a server, the artifact will be used like to a normal JAR archive. Because WARs use different locations for the .class files, the NoClassDefFoundError is thrown at run time.
In a JAR, the class com.example.Foo will be stored at /com/example/Foo.class. Since WARs are designed to contain libraries, resources etc. the classes should not be stored relative to the root of the archive. Instead, they are contained in the folder /WEB-INF/classes, Foo would be stored as /WEB-INF/classes/com/example/Foo.class.
Fortunately, the Maven developers thought of this issue and added the attachClasses option to the WAR plugin. This option creates an additional JAR with the classes classifier that contains only the Java classes in JAR format (relative the the archive root).
To enable the building of this JAR, you can use this snippet in your WAR project's build section (in addition to the configuration for the maven-jar-plugin to build the test JAR):
<pluginManagement>
<plugins>
<!-- … -->
<plugin>
<!-- build the classes JAR (non-test classes) -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.4</version>
<configuration>
<attachClasses>true</attachClasses>
</configuration>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<!-- … -->
<plugin>
<!-- build the test JAR (test classes) -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<executions>
<execution>
<goals>
<goal>test-jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
Since the classes are attached, they will be installed and deployed by Maven together with the WAR artifact. Note that this only provides you with the contents of the regular WAR archive, to use the test classes, you need to depend on both the classes artifact and the test jar. To do this, you can use:
<dependencies>
<!-- … -->
<dependency>
<!-- test classes only -->
<groupId>foo</groupId>
<artifactId>web</artifactId>
<version>SNAPSHOT</version>
<type>test-jar</type>
</dependency>
<dependency>
<!-- non-test classes only -->
<groupId>foo</groupId>
<artifactId>web</artifactId>
<version>SNAPSHOT</version>
<type>jar</type>
<classifier>classes</classifier>
<scope>runtime</scope>
</dependency>
</dependencies>
Try:
<dependency>
<groupId>foo</groupId>
<artifactId>web</artifactId>
<version>SNAPSHOT</version>
<type>war</type>
<classifier>tests</classifier>
<scope>test</scope>
</dependency>
Maven allows you some configuration regarding snapshots dependancy
<repository>
<id>foo-repository</id>
<url>...</url>
<snapshots>
<enabled>true</enabled>
<updatePolicy>XXX</updatePolicy>
</snapshots>
Check the above config. If its false in pom.xml maven will not update snapshots. Also you will find the following thread useful for your query What exactly is a Maven Snapshot and why do we need it?
in my pom.xml I've configured maven-jaxb-plugin but I'm getting a "A required plugin was not found: Plugin could not be found - check that the goal name is correct: Unable to download the artifact from any repository" because of it. My config is like this:
<plugin>
<groupId>com.sun.tools.xjc.maven2</groupId>
<artifactId>maven-jaxb-plugin</artifactId>
<version>1.1</version>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
<configuration>
<generate-package>tld.mycompany.myproject.data.ws-schema</generate-package>
<schemaDirectory>src/main/resources/ws/xsd</schemaDirectory>
</configuration>
</plugin>
In dependencies, I have added the following.
<dependency>
<groupId>maven-plugins</groupId>
<artifactId>maven-jaxb-plugin</artifactId>
<version>1.1.0</version>
</dependency>
<dependency>
<groupId>org.jvnet.jaxb2.maven2</groupId>
<artifactId>maven-jaxb2-plugin</artifactId>
<version>0.7.5</version>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-xjc</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<version>2.2</version>
</dependency>
What am I missing? Why can't it find the correct artifacts?
Cheers
Nik
I suggest you use, when facing such a problem, one of the available maven search engines :
mvnbrowser
jarvana
mvnrepository
the two first having my preference. Here is what they say about your artifacts :
maven-jaxb-plugin is available at Apache
maven-jaxb2-plugin 0.7.5 is not known. The most up-to-date version, is 0.7.3 on mvnbrowser and 0.7.4 on jarvana. which may be the reason why your maven build is broken
jaxb-api 2.2 is available at both JavaNet and JBoss repositories
Well, wion't do all the job for you, as I guess you get the picture now.
You can find version 0.7.3 on the Java.net maven repository:
http://download.java.net/maven/2/