I have a Spring Boot application developed in STS which connects to SAP through SAP Java connector. That connector comes in a jar whose rules forbid renaming or repackaging the archive.
Since the application must run on several platforms, I've locally repackaged the SAP JCO jars in a custom set of dependencies so shaped:
connectors-project
| pom.xml
|
+---sap-jco-api
| pom.xml
| sapjco3.jar
|
+---sap-jco-linux-x86_64
| | pom.xml
| |
| \---src
| \---main
| \---resources
| libsapjco3.so
| Readme.txt
| sapjco3.jar
| sapjcomanifest.mf
|
\---sap-jco-nt-amd64
| pom.xml
|
\---src
\---main
\---resources
Readme.txt
sapjco3.dll
sapjco3.jar
sapjco3.pdb
sapjcomanifest.mf
The sap-jco-api module is used for compilation, the others for execution. Proper packaging is handled on a per-project basis, configuring the maven-dependency-plugin plugin each time.
For the Spring Boot application in question, here's the relevant portion of the 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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>...</groupId>
<artifactId>...</artifactId>
<packaging>...</packaging>
<version>...</version>
<name>...</name>
<description>...</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.0.RELEASE</version>
</parent>
<properties />
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifestEntries>
<Class-Path>sap-jco/sapjco3.jar</Class-Path>
</manifestEntries>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>...</mainClass>
<excludeGroupIds>com.sap</excludeGroupIds>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>unpack-dependencies-package</id>
<phase>package</phase>
<goals>
<goal>unpack-dependencies</goal>
</goals>
<configuration>
<excludeTransitive>true</excludeTransitive>
<includeGroupIds>com.sap</includeGroupIds>
<excludeArtifactIds>sap-jco-api</excludeArtifactIds>
<excludes>META-INF/**</excludes>
<outputDirectory>${project.build.directory}/sap-jco</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<!-- Spring Boot -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>...</artifactId>
</dependency>
<!-- SAP JCO connector -->
<dependency>
<groupId>com.sap</groupId>
<artifactId>sap-jco-api</artifactId>
<version>3.0.18</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.sap</groupId>
<artifactId>sap-jco-nt-amd64</artifactId>
<version>3.0.18</version>
<scope>provided</scope>
</dependency>
<!-- other -->
<dependency>...</dependency>
</dependencies>
</project>
At package time, all SAP dependencies are excluded from the jar produced by spring-boot-maven-plugin and the platform-specific files are copied to a subdirectory made visible to the final jar by the MANIFEST Class-Path entry.
This is the Maven-created target folder for that POM:
application-project
|
\---target
| application.jar
|
\---sap-jco
Readme.txt
sapjco3.dll
sapjco3.jar
sapjco3.pdb
sapjcomanifest.mf
The resulting jar works as expected when run with java -jar target\application.jar.
The problem arises in STS (or Eclipse), when I run the application with right click -> Run As -> Spring Boot App, the project seems to be packaged in a default way - thus with the SAP jar packaged - and execution breaks with:
JCo initialization failed with java.lang.ExceptionInInitializerError: Illegal JCo archive [...]. It is not allowed to rename or repackage the original archive "sapjco3.jar".
I guess I have to somehow replicate the Maven configuration within the IDE, but I can't find a way to do that. In "Run configurations" there doesn't seem to be a way to do this, nor does that menu command seem to run the Spring Boot Maven Plugin spring-boot:run goal, that I could configure inside the POM.
This is impeding me from debugging the application from inside the IDE and I'm also forced to manually package and run it from the command line, slowing down development.
What can I do?
Related
I want to run JUnit tests for the performance testing using JMeter Maven Plugin.
During the JUnit tests run, I use one external properties file located inside <project>/src/resources/env.properties
This file has some configuration which I need to run the tests successfully.
I have given this file in src/test/jmeter location as well but the plugin is not picking up this file.
During performance tests run using JMeter Maven Plugin, This file is not found because of the relative path given inside JUnit tests as
String fileName = "src/resources/env.properties";
I get the below error during the JMeter test run
[INFO] fileName = env.properties
[INFO] java.io.FileNotFoundException: src/resources/env.properties (No such file or directory)
Can you please help, where to give the location of this file? do I need to give in pom.xml?
These tests working perfectly fine using the JMeter application where I put this file under <JMeterApp>/bin/src/resources and run the test.
Please find below pom.xml 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>com</groupId>
<artifactId>myProject</artifactId>
<version>1.0-SNAPSHOT</version>
<name>MyProject</name>
<url>http://maven.apache.org</url>
<build>
<plugins>
<plugin>
<groupId>com.lazerycode.jmeter</groupId>
<artifactId>jmeter-maven-plugin</artifactId>
<version>3.4.0</version>
<executions>
<!-- Generate JMeter configuration -->
<execution>
<id>configuration</id>
<goals>
<goal>configure</goal>
</goals>
</execution>
<!-- Run JMeter tests -->
<execution>
<id>jmeter-tests</id>
<goals>
<goal>jmeter</goal>
</goals>
</execution>
<!-- Fail build on errors in test -->
<execution>
<id>jmeter-check-results</id>
<goals>
<goal>results</goal>
</goals>
</execution>
</executions>
<configuration>
<generateReports>true</generateReports>
<jmeterExtensions>
<artifact>kg.apc:jmeter-plugins:pom:1.4.0</artifact>
<artifact>kg.apc:jmeter-plugins-json:2.7</artifact>
</jmeterExtensions>
<junitLibraries>
<artifact>com:myProject:1.0-SNAPSHOT</artifact>
</junitLibraries>
<propertiesFilesDirectory>src/test/jmeter/src/resources</propertiesFilesDirectory>
<downloadExtensionDependencies>false</downloadExtensionDependencies>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
When you run your tests via JMeter Maven Plugin the current working directory looks like:
your_project\target\some-guid-like-structure\jmeter\bin
so in order to access the file which lives under your_project\src\resources you need to refer it like:
String fileName = "../../../../src/resources/env.properties";
More information: How to Use the JMeter Maven Plugin
Using maven-exec-plugin and a java goal I execute a jar program that validates some files in my project. When the validation fails, it calls System.exit to return a non zero return code.
The problem is that it executes in the same JVM as Maven, so when it calls exit, the processing stops since it does not fork.
I configured it to execute with maven-exec-plugin and a java goal (like in here ). The execute jar is in my Nexus repository, so I want to download it as a dependency in my pom.xml.
A very nice feature of configuring the maven-exec-plugin dependency is that it downloads the jar and all its dependencies, so it isn't necessary to use maven assembly plugin to include all jars in the executable.
How do I configure my pom.xml to execute a jar dependency and correctly stop when it fails?
I solved my problem. Basically, instead of using the java goal, I must use the exec goal, and run the java executable. The code below sets the classpath and the class with the main method.
This solution using the pom.xml and a Nexus repository has a lot of advantages over just handling a jar file for my users:
No need to install anything in the machine that will run it, be it a developer machine or a continuous integration one.
The validation tool developer can release new versions and it will be automatically updated.
The developer can turn it off with a simple parameter.
Also solves the original problem: the validation tool will execute in a separate process, so the maven process won't abort when it calls System.exit.
Here is a commented 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.company</groupId>
<artifactId>yourId</artifactId>
<version>1.0</version>
<properties>
<!--
Skip the validation executing maven setting the parameter below
mvn integration-test -Dvalidation.skip
-->
<validation.skip>false</validation.skip>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.6.0</version>
<executions>
<execution>
<id>MyValidator</id>
<phase>integration-test</phase> <!-- you can associate to any maven phase -->
<goals>
<goal>exec</goal> <!-- forces execution in another process -->
</goals>
</execution>
</executions>
<configuration>
<executable>java</executable> <!-- java must be in your PATH -->
<includeProjectDependencies>false</includeProjectDependencies>
<includePluginDependencies>false</includePluginDependencies>
<skip>${validation.skip}</skip>
<arguments>
<argument>-classpath</argument>
<classpath/> <!-- will include your class path -->
<mainClass>com.company.yourpackage.AppMain</mainClass> <!-- the class that has your main file -->
<argument>argument.xml</argument> <!-- any argument for your executable -->
</arguments>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<!-- Specify your executable jar here -->
<groupId>com.company.validator</groupId>
<artifactId>validatorId</artifactId>
<version>RELEASE</version> <!-- you can specify a fixed version here -->
<type>jar</type>
</dependency>
</dependencies>
</project>
You can run more than one executable passing its id: mvn exec:exec#MyValidator
I have stumbled upon the same issue - System.exit halts the maven with exec:java.
I have experimented to use the exec:exec goal, and made it work with the following configuration:
(using exec-maven-plugin 3.1.0)
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<executions>
<execution>
<id>generate-observability-docs</id>
<phase>prepare-package</phase>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<executable>java</executable>
<arguments>
<argument>-jar</argument>
<argument>${settings.localRepository}/io/micrometer/micrometer-docs-generator/${micrometer-docs-generator.version}/micrometer-docs-generator-${micrometer-docs-generator.version}.jar</argument>
<argument>${micrometer-docs-generator.inputPath}</argument>
<argument>${micrometer-docs-generator.inclusionPattern}</argument>
<argument>${micrometer-docs-generator.outputPath}</argument>
</arguments>
</configuration>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-docs-generator</artifactId>
<version>${micrometer-docs-generator.version}</version>
<type>jar</type>
</dependency>
</dependencies>
</plugin>
I would like to integrate blazemeter random CSV data plugin set into my jmeter maven project. I am new to both maven and jmeter 3.2, but I have got a project built.
However there is no information on how I can setup the random CSV data plugin and how it should be setup in the configuration of the POM file.
So far, I have added the dependencies for the plugin, but there is no documentation on configuration within the pom file.
Dependency:
<dependency>
<groupId>kg.apc</groupId>
<artifactId>jmeter-plugins-cmn-jmeter</artifactId>
<version>0.5</version>
</dependency>
<dependency>
<groupId>org.apache.jmeter</groupId>
<artifactId>ApacheJMeter_components</artifactId>
<version>4.0</version>
</dependency>
<dependency>
<groupId>kg.apc</groupId>
<artifactId>jmeter-plugins-emulators</artifactId>
<version>0.4</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.blazemeter</groupId>
<artifactId>jmeter-plugins-random-csv-data-set</artifactId>
<version>0.6</version>
</dependency>
Is there a way I can configure the plugin in the verify stage or do I configure the plugin by adding in the properties.user and set the values within the in the pom file.
This is not how you should use dependencies in your JMeter Maven project, you should add any required JMeter Plugins into configuration/jmeterExtensions section like:
<configuration>
<jmeterExtensions>
<artifact>com.blazemeter:jmeter-plugins-random-csv-data-set:0.6</artifact>
<artifact>kg.apc:jmeter-plugins-emulators:0.4</artifact>
<artifact>kg.apc:jmeter-plugins-cmn-jmeter:0.5</artifact>
</jmeterExtensions>
<downloadExtensionDependencies>false</downloadExtensionDependencies>
</configuration>
Full pom.xml just in case:
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
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.example</groupId>
<artifactId>mvn-jmeter</artifactId>
<version>1.0-SNAPSHOT</version>
<name>maven-jmeter-demo</name>
<url>http://maven.apache.org</url>
<build>
<plugins>
<plugin>
<groupId>com.lazerycode.jmeter</groupId>
<artifactId>jmeter-maven-plugin</artifactId>
<version>2.7.0</version>
<executions>
<execution>
<id>jmeter-tests</id>
<phase>verify</phase>
<goals>
<goal>jmeter</goal>
</goals>
</execution>
</executions>
<configuration>
<jmeterExtensions>
<artifact>com.blazemeter:jmeter-plugins-random-csv-data-set:0.6</artifact>
<artifact>kg.apc:jmeter-plugins-emulators:0.4</artifact>
<artifact>kg.apc:jmeter-plugins-cmn-jmeter:0.5</artifact>
</jmeterExtensions>
<downloadExtensionDependencies>false</downloadExtensionDependencies>
</configuration>
</plugin>
</plugins>
</build>
</project>
More information:
Adding jar's to the /lib/ext directory
Five Ways To Launch a JMeter Test without Using the JMeter GUI
I have a multi module web application.
The structure is:
Parent
|
| - - Child 1
| - - Child 2
| - - Web
And the web project depends on the two child modules
When using my IDE to build my project I was used to the IDE building the classes in the WEB-INF/classes folder. This was nice as the web server noticed the new classes and either restarted or hot deployed these files. With maven it seems that I have to package the whole thing from scratch every time.
I would like to find a way in maven such that i can avoid running mvn:clean mvn:install mvn:war:inplace. Instead I would like a mvn:comile, and then the stuff just there.
I hope you understand what I mean. Testing the web app is extremely slow when you always have to build all the project jars and run som war command before things are updated.
The web apps 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>
...
</parent>
<artifactId>web</artifactId>
<packaging>war</packaging>
<dependencies>
<dependency>
<groupId>bla.bla.bla</groupId>
<artifactId>bla_child1</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>bla.bla.bla</groupId>
<artifactId>bla_child2</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.4</version>
</plugin>
<plugin>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>9.0.4.v20130625</version>
<configuration>
<scanIntervalSeconds>30</scanIntervalSeconds>
<webApp>
<contextPath>/blabla</contextPath>
</webApp>
</configuration>
</plugin>
</plugins>
</build>
</project>
A possible solution to your problem could be to build a skinny war with the maven-war-plugin (or at least exclude child1 and child2 if you have other dependencies as well) and add the target/classes folders of the child-projects to your classpath. This could be done with the Build Helper Maven Plugin's add-resource goal.
Disclaimer: I didn't try this myself but in theory it could work :)
This is my own temporary answer to this problem.
It would be nice if it could be done with maven, but I haven't been able to find a solution. Therefore I have bound an ant target to the compile phase of the web module.
This is probably not a solution that can be used anywhere, but it works in my case.
web/pom.xml:
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.7</version>
<executions>
<execution>
<id>copy-modules</id>
<phase>compile</phase>
<configuration>
<target>
<delete dir="${project.basedir}\src\main\webapp\WEB-INF\classes"/>
<copy todir="${project.basedir}\src\main\webapp\WEB-INF\classes">
<fileset dir="${main.basedir}\modules\child-1\target\classes">
<include name="**/*.class"/>
<include name="**/*.xml"/>
</fileset>
<fileset dir="${main.basedir}\modules\child-2\target\classes">
<include name="**/*.class"/>
<include name="**/*.xml"/>
</fileset>
</copy>
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
Now the jetty sees everytime I do a compile, which is much faster than install, war and the stuff that was needed before.
I'm trying to use the maven-checkstyle plugin for a multi-module project here is my projec structure
|pom-root
| -- my-checkstyles
| |-- pom.xml
| |-- checkstyles
| |-- checkstyles.xml
| -- my-war
| |-- pom.xml
| -- my-ejb
| |-- pom.xml
| -- my-ear
| |-- pom.xml
| -- pom.xml
and here is the pom.xml for my pom-root project :
<project
xsi:schemaLocation=
"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
xmlns=
"http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
>
<modelVersion>4.0.0</modelVersion>
<groupId>test</groupId>
<artifactId>pom-root</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>my-checkstyles</module>
<module>my-ear</module>
<module>my-ejb</module>
<module>my-war</module>
</modules>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>2.5</version>
<configuration>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins </groupId>
<artifactId> maven-site-plugin </artifactId>
<version>3.0-beta-3</version>
<dependencies>
<dependency>
<groupId>com.puppycrawl.tools</groupId>
<artifactId>checkstyle</artifactId>
<version>5.4</version>
</dependency>
<dependency>
<groupId>fr.info.saone</groupId>
<artifactId>info-saone-checkstyle</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
<configuration>
<outputEncoding>UTF-8</outputEncoding>
<reportPlugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<version>2.7</version>
<configuration>
<cacheFile>target/cachefile</cacheFile>
<configLocation>checkstyles/checkstyle_vnf.xml</configLocation>
<linkXRef>true</linkXRef>
</configuration>
</plugin>
</reportPlugins>
</configuration>
</plugin>
</plugins>
</build>
</project>
When I execute mvn site it fails unless I have the checkstyle project installed in the repository, which is pretty annoying because if a make a slight change in the file I need to install it again in the repo.
I know Maven is supposed to work this way, but is there a way to configure the root pom to resolve the dependency to the checkstyle project at compile time and not get it from the repo?
I tried using maven options "--also-make" and "-pl" but I couldn't get it working.
Also I know I can tell checkfile to look for the checkstyle file using the file:/// protocol (thats how I'm doing it now) but I would rather find an alternative way.
Thanks in advance