Getting ClassNotFoundException after upgrading karaf from 4.0.4 to 4.1.7 - osgi

We have created a karaf command using org.apache.karaf.shell.api.action.Action.
public class MyCommandIpl implements MyCommand {
#Override
public executeCOmmand() {someObj.execute;
}
}
It was working fine with karaf version 4.0.4. But when we upgraded the karaf version to 4.1.7, the hot deployment of this bundle is causing below exception,
java.lang.IllegalArgumentException: Bean class not found com.subhash.command.MyCommandIpl
at org.apache.aries.jpa.blueprint.impl.JpaComponentProcessor.handleComponent(JpaComponentProcessor.java:99)
at org.apache.aries.jpa.blueprint.impl.JpaComponentProcessor.process(JpaComponentProcessor.java:77)
at org.apache.aries.blueprint.container.BlueprintContainerImpl.processProcessors(BlueprintContainerImpl.java:549)
at org.apache.aries.blueprint.container.BlueprintContainerImpl.doRun(BlueprintContainerImpl.java:394)
at org.apache.aries.blueprint.container.BlueprintContainerImpl.run(BlueprintContainerImpl.java:275)
at org.apache.aries.blueprint.container.BlueprintExtender.createContainer(BlueprintExtender.java:300)
at org.apache.aries.blueprint.container.BlueprintExtender.createContainer(BlueprintExtender.java:269)
at org.apache.aries.blueprint.container.BlueprintExtender.createContainer(BlueprintExtender.java:265)
at org.apache.aries.blueprint.container.BlueprintExtender.modifiedBundle(BlueprintExtender.java:255)
at org.apache.aries.util.tracker.hook.BundleHookBundleTracker$Tracked.customizerModified(BundleHookBundleTracker.java:500)
at org.apache.aries.util.tracker.hook.BundleHookBundleTracker$Tracked.customizerModified(BundleHookBundleTracker.java:433)
at org.apache.aries.util.tracker.hook.BundleHookBundleTracker$AbstractTracked.track(BundleHookBundleTracker.java:725)
at org.apache.aries.util.tracker.hook.BundleHookBundleTracker$Tracked.bundleChanged(BundleHookBundleTracker.java:463)
at org.apache.aries.util.tracker.hook.BundleHookBundleTracker$BundleEventHook.event(BundleHookBundleTracker.java:422)
at org.apache.felix.framework.util.SecureAction.invokeBundleEventHook(SecureAction.java:1179)
at org.apache.felix.framework.EventDispatcher.createWhitelistFromHooks(EventDispatcher.java:730)
at org.apache.felix.framework.EventDispatcher.fireBundleEvent(EventDispatcher.java:485)
at org.apache.felix.framework.Felix.fireBundleEvent(Felix.java:4579)
at org.apache.felix.framework.Felix.startBundle(Felix.java:2174)
at org.apache.felix.framework.BundleImpl.start(BundleImpl.java:998)
at org.apache.felix.fileinstall.internal.DirectoryWatcher.startBundle(DirectoryWatcher.java:1260)
at org.apache.felix.fileinstall.internal.DirectoryWatcher.startBundles(DirectoryWatcher.java:1233)
at org.apache.felix.fileinstall.internal.DirectoryWatcher.doProcess(DirectoryWatcher.java:520)
at org.apache.felix.fileinstall.internal.DirectoryWatcher.process(DirectoryWatcher.java:365)
at org.apache.felix.fileinstall.internal.DirectoryWatcher.run(DirectoryWatcher.java:316)
Caused by: java.lang.ClassNotFoundException: com.subhash.command.MyCommandIpl not found by deadlock-test-tool [507]
at org.apache.felix.framework.BundleWiringImpl.findClassOrResourceByDelegation(BundleWiringImpl.java:1639)
at org.apache.felix.framework.BundleWiringImpl.access$200(BundleWiringImpl.java:80)
at org.apache.felix.framework.BundleWiringImpl$BundleClassLoader.loadClass(BundleWiringImpl.java:2053)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at org.apache.felix.framework.Felix.loadBundleClass(Felix.java:1927)
at org.apache.felix.framework.BundleImpl.loadClass(BundleImpl.java:978)
at org.apache.aries.jpa.blueprint.impl.JpaComponentProcessor.handleComponent(JpaComponentProcessor.java:97)
... 24 more
Where the pom has below data
build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>${maven.jar.plugin.version}</version>
<configuration>
<excludes>
<exclude>**/log4j.xml</exclude>
</excludes>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<instructions>
<Karaf-Commands>com.subhash.command*</Karaf-Commands>
<_removeheaders>Import-Service,Export-Service</_removeheaders>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
Kindly help!

Related

Adding a JNI library to a spring boot (maven) jar

I'm using Google Or-Tools library over a Java-Spring-Boot app, Windows 10 OS and Intellij IDE.
To make it work over intellij I did the following:
Install Microsoft Visual C++ Redistributable for Visual Studio 2019 (required according to the installation instructions).
Downloaded and extracted the OR-Tools library for Java (included 2 jars and a 1 dll file).
In Intellij, I added those jars as module dependencies (under a folder called lib).
Added the lib library path to VM options in Intellij run configurations.
Loaded the library statically in my code:
static {System.loadLibrary("jniortools");}
Now I can run the project successfully form Intellij.
Next I would like to pack everything to a spring boot jar that can run over any windows machine.
My folders structure is:
My pom file is pretty basic, a few dependencies with a standard spring-boot-maven-plugin:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
As I'm trying to pack the code using mvn install I'm getting package com.google.ortools.sat does not exist.
How can I make sure maven packs those 3rd party jars to the executable spring-boot jar?
UPDATE
I added to my pom file:
<dependency>
<groupId>com.google.ortools</groupId>
<artifactId>ortools</artifactId>
<version>LATEST</version>
<type>jar</type>
<scope>system</scope>
<systemPath>${project.basedir}/lib/com.google.ortools.jar</systemPath>
</dependency>
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>LATEST</version>
<type>jar</type>
<scope>system</scope>
<systemPath>${project.basedir}/lib/protobuf.jar</systemPath>
</dependency>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.7</version>
<executions>
<execution>
<phase>generate-test-sources</phase>
<configuration>
<tasks>
<mkdir dir="${project.basedir}/target/lib"/>
<echo message="Creating lib folder..."/>
<copy todir="${project.basedir}/target/lib">
<fileset dir="${project.basedir}/lib">
<include name="**/**"/>
</fileset>
</copy>
</tasks>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
In addition adding to library path:
static {
try {
String orToolsDllLibrary = System.getProperty("user.dir") + "\\lib";
addLibraryPath(orToolsDllLibrary);
System.loadLibrary("jniortools");
} catch (Exception e) {
e.printStackTrace();
}
}
public static void addLibraryPath(String pathToAdd) throws Exception {
final Field usrPathsField = ClassLoader.class.getDeclaredField("usr_paths");
usrPathsField.setAccessible(true);
//get array of paths
final String[] paths = (String[]) usrPathsField.get(null);
//check if the path to add is already present
for (String path : paths) {
if (path.equals(pathToAdd)) {
return;
}
}
//add the new path
final String[] newPaths = Arrays.copyOf(paths, paths.length + 1);
newPaths[newPaths.length - 1] = pathToAdd;
usrPathsField.set(null, newPaths);
}
And now when running command java -jar myApp-0.0.1-SNAPSHOT.jar getting an exception:
Caused by: java.lang.NoClassDefFoundError: com/google/ortools/sat/CpSolver
at java.base/java.lang.Class.getDeclaredMethods0(Native Method) ~[na:na]
at java.base/java.lang.Class.privateGetDeclaredMethods(Class.java:3167) ~[na:na]
at java.base/java.lang.Class.getDeclaredMethods(Class.java:2310) ~[na:na]
at org.springframework.util.ReflectionUtils.getDeclaredMethods(ReflectionUtils.java:463) ~[spring-core-5.2.6.RELEASE.jar!/:5.2.6.RELEASE]
... 29 common frames omitted
Caused by: java.lang.ClassNotFoundException: com.google.ortools.sat.CpSolver
at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:471) ~[na:na]
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:588) ~[na:na]
at org.springframework.boot.loader.LaunchedURLClassLoader.loadClass(LaunchedURLClassLoader.java:129) ~[solver-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521) ~[na:na]
... 33 common frames omitted
I am not sure how you added the library to your project? You don't seem to have done it through Maven, did you?
In the past I took the approach of adding it via using system scope in Maven (see here. This would give you something like this in your pom:
<dependency>
<groupId>com.google.ortools</groupId>
<artifactId>ortools</artifactId>
<version>1.0</version>
<scope>system</scope>
<systemPath>${basedir}/src/main/resources/lib/com.google.ortools.jar</systemPath>
</dependency>
However, this approach can also be a pain especially if you have to work multi-platform. Recently, I found this repo and that made my life much easier dealing with OR-tools. Hope this helps.
UPDATE:
I strongly recommend using the updated method below as it is much less of a headache:
<repositories>
...
<repository>
<id>bintray</id>
<url>https://dl.bintray.com/magneticflux/maven</url>
</repository>
....
</repositories>
<dependencies>
<dependency>
<groupId>com.skaggsm.ortools</groupId>
<artifactId>ortools-natives-all</artifactId>
<version>7.7.7810</version>
</dependency>
<!-- OR-tools needs protobuf -->
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>3.12.2</version>
</dependency>
</dependencies>
Then you can do a static load of the library:
static {
OrToolsHelper.loadLibrary()
}
Make sure to work with JDK >= 11 as elaborated here.
I tried:
First add the jniortools library to java.library.path pragmatically:
static {
String orToolsDllLibrary = System.getProperty("user.dir") + "\\lib";
addLibraryPath(orToolsDllLibrary);
System.loadLibrary("jniortools");
}
public static void addLibraryPath(String pathToAdd) throws Exception {
final Field usrPathsField = ClassLoader.class.getDeclaredField("usr_paths");
usrPathsField.setAccessible(true);
//get array of paths
final String[] paths = (String[]) usrPathsField.get(null);
//check if the path to add is already present
for (String path : paths) {
if (path.equals(pathToAdd)) {
return;
}
}
//add the new path
final String[] newPaths = Arrays.copyOf(paths, paths.length + 1);
newPaths[newPaths.length - 1] = pathToAdd;
usrPathsField.set(null, newPaths);
}
In pom file:
<dependencies>
....
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>3.12.2</version>
</dependency>
<dependency>
<groupId>com.google</groupId>
<artifactId>ortools</artifactId>
<version>0.0.2</version>
</dependency>
....
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
<executions>
<execution>
<id>install-external</id>
<phase>process-resources</phase>
<configuration>
<file>${basedir}/lib/com.google.ortools.jar</file>
<repositoryLayout>default</repositoryLayout>
<groupId>com.google</groupId>
<artifactId>ortools</artifactId>
<version>0.0.2</version>
<packaging>jar</packaging>
<generatePom>true</generatePom>
</configuration>
<goals>
<goal>install-file</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.7</version>
<executions>
<execution>
<phase>generate-sources</phase>
<configuration>
<tasks>
<mkdir dir="${project.basedir}/target/lib"/>
<echo message="Creating lib folder..."/>
<copy todir="${project.basedir}/target/lib">
<fileset dir="${project.basedir}/lib">
<include name="**/**"/>
</fileset>
</copy>
</tasks>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

Spring Boot Maven Project Obfuscation with Proguard

I am using Java 11, Spring Boot 2.2.4 and Proguard 6.2.2.
My pom.xml for proguard as follows
<build>
<finalName>${artifactId}</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>com.github.wvengen</groupId>
<artifactId>proguard-maven-plugin</artifactId>
<version>2.2.0</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>proguard</goal>
</goals>
</execution>
</executions>
<configuration>
<proguardVersion>6.2.2</proguardVersion>
<injar>${project.build.finalName}.jar</injar>
<outjar>${project.build.finalName}.jar</outjar>
<includeDependency>true</includeDependency>
<obfuscate>true</obfuscate>
<proguardInclude>${basedir}/proguard.conf</proguardInclude>
<injarNotExistsSkip>true</injarNotExistsSkip>
<libs>
<lib>${java.home}/jmods</lib>
<lib>${java.home}/lib</lib>
</libs>
<archive>
<manifest>
<mainClass>Application</mainClass>
<packageName>com.abc</packageName>
</manifest>
</archive>
</configuration>
<dependencies>
<dependency>
<groupId>net.sf.proguard</groupId>
<artifactId>proguard-base</artifactId>
<version>6.2.2</version>
<scope>runtime</scope>
</dependency>
</dependencies>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
<configuration>
<mainClass>com.abc.Application</mainClass>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
My Proguard configuration (proguard.conf) as follows
-ignorewarnings
-dontshrink
-dontoptimize
-keepdirectories
-adaptclassstrings
-useuniqueclassmembernames
-dontusemixedcaseclassnames
-flattenpackagehierarchy 'com.abc'
-keepattributes Exceptions,InnerClasses,Signature,Deprecated,SourceFile,LineNumberTable,LocalVariable*Table,*Annotation*,Synthetic,EnclosingMethod
-keep class com.abc.Application
-keep class * extends org.springframework.boot.ApplicationRunner
-keepclasseswithmembers public class * {
public static void main(java.lang.String[]);
}
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
-keepclasseswithmembers,includedescriptorclasses,allowshrinking class * {
native <methods>;
}
When I run the obfucated jar, I am getting below error
Exception in thread "main" java.lang.IllegalStateException: Failed to get nested archive for entry BOOT-INF/lib/spring-boot-starter-data-jpa-2.2.4.RELEASE.jar
Caused by: java.lang.IllegalStateException: Unable to open nested entry 'BOOT-INF/lib/spring-boot-starter-data-jpa-2.2.4.RELEASE.jar'. It has been compressed and nested jar files must be stored without compression. Please check the mechanism used to create your executable jar file

Spring Integration application does not define channels when executed as packaged jar

I started to use Spring Integration in a project at work. Everything was looking fine and running smoothly on my local dev environment (when executed from Eclipse).
However, when I tried to deploy to our dev/staging environment I got some issues related with the definition of the Spring Integration channels.
After a couple of hours completely clueless (blaming external dependencies, our development/staging environment setup etc etc), I came to realize that I would get exactly the same issue whenever I tried to execute my application as a packaged jar (on my local machine)
I did a small "sample" application without any other dependencies in order to reproduce this issue. Once again everything works fine from eclipse but whenever executed as a packaged jar the following exception was thrown:
Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'gatewayChannel' available
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:687)
at org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1207)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:284)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
at org.springframework.integration.support.channel.BeanFactoryChannelResolver.resolveDestination(BeanFactoryChannelResolver.java:89)
at org.springframework.integration.support.channel.BeanFactoryChannelResolver.resolveDestination(BeanFactoryChannelResolver.java:46)
at org.springframework.integration.gateway.MessagingGatewaySupport.getRequestChannel(MessagingGatewaySupport.java:344)
at org.springframework.integration.gateway.MessagingGatewaySupport.send(MessagingGatewaySupport.java:385)
at org.springframework.integration.gateway.GatewayProxyFactoryBean.invokeGatewayMethod(GatewayProxyFactoryBean.java:481)
at org.springframework.integration.gateway.GatewayProxyFactoryBean.doInvoke(GatewayProxyFactoryBean.java:433)
at org.springframework.integration.gateway.GatewayProxyFactoryBean.invoke(GatewayProxyFactoryBean.java:424)
at org.springframework.integration.gateway.GatewayCompletableFutureProxyFactoryBean.invoke(GatewayCompletableFutureProxyFactoryBean.java:65)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213)
at com.sun.proxy.$Proxy24.send(Unknown Source)
at com.test.App$RealApp.doThings(App.java:52)
at com.test.App.main(App.java:62)
Bellow you can find the code of my sample application and the pom that I used to build my packaged jar.
#ComponentScan
#EnableIntegration
#IntegrationComponentScan
#Configuration
public class App {
#MessagingGateway
public interface GatewayApp {
#Gateway(requestChannel = "gatewayChannel")
void send(String string);
}
#Bean
public IntegrationFlow inboud() {
return IntegrationFlows.from("gatewayChannel")
.handle(System.out::println)
.get();
}
#Component
public class RealApp {
#Autowired
private GatewayApp gateway;
public void doThings() {
gateway.send("yeee");
}
}
#SuppressWarnings("resource")
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.register(App.class);
context.refresh();
context.getBean(RealApp.class).doThings();
}
}
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>sprint-integration</groupId>
<artifactId>integration</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>integration</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spring.version>4.3.14.RELEASE</spring.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.20.1</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.3</version>
<configuration>
<createDependencyReducedPom>true</createDependencyReducedPom>
<createSourcesJar>false</createSourcesJar>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<finalName>yo-service</finalName>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<!-- Spring Integration -->
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-amqp</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-java-dsl</artifactId>
<version>1.2.3.RELEASE</version>
</dependency>
</dependencies>
</project>
Note: I think this issue might have exaclty the same cause as the one reported in Spring integration bootstrap - intellij in debug works, packaged jar does not
My best guess is the shade plugin is having some effect on the order in which BeanPostProcessors are run.
Does the app work if you explicitly define the channel...
#Bean
public MessageChannel gatewayChannel() {
return new DirectChannel();
}
...?
If so, that would be a smoking gun. In that case, the next step would be to get a DEBUG log for org.springframework in both environments and compare the bean definition/creation/post processing logs.
If you can post a complete (simple) example that exhibits the problem, we can take a look.
EDIT
The problem is the shade plugin does not merge the META-INF/spring.factories files, so we lose the entry from the JAVA DSL and hence don't process any IntegrationFlows...
From the Uber jar we just have the core file...
org.springframework.integration.config.IntegrationConfigurationInitializer=\
org.springframework.integration.config.GlobalChannelInterceptorInitializer,\
org.springframework.integration.config.IntegrationConverterInitializer,\
org.springframework.integration.config.IdempotentReceiverAutoProxyCreatorInitializer
and so are missing the additional initializer from the DSL jar...
org.springframework.integration.config.IntegrationConfigurationInitializer=\
org.springframework.integration.dsl.config.DslIntegrationConfigurationInitializer
Hence it works with 5.0.1 because the DSL is now part of core.
Spring Boot solves this problem by nesting the jars instead of extracting all the classes.
EDIT2
Here's another work-around, if you can't move to Spring Integration 5. Add this bean to your application...
#Bean
public static BeanFactoryPostProcessor dslInitializer() {
return new BeanFactoryPostProcessor() {
#Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory bf) throws BeansException {
new DslIntegrationConfigurationInitializer().initialize(bf);
}
};
}
(Notice static).
Adding to Gary Russell's answer: The problem is indeed that the META-INF/spring.factories files are not automatically merged by the shade plugin.
You can use the AppendingTransformer of the shade plugin to merge these files.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<shadedArtifactAttached>true</shadedArtifactAttached>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>com.my.MainClass</mainClass>
</transformer>
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
<resource>META-INF/spring.handlers</resource>
</transformer>
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
<resource>META-INF/spring.schemas</resource>
</transformer>
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
<resource>META-INF/spring.tooling</resource>
</transformer>
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
<resource>META-INF/spring.factories</resource>
</transformer>
<transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer" />
</transformers>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>
</filters>
</configuration>
</execution>
</executions>
</plugin>

How to fix corrupted xls file by maven?

I have a method of generating report made with jett:
try {
InputStream inPath = ProdutoManagedBean.class.getResourceAsStream("/template.xls");
ExcelTransformer transformer = new ExcelTransformer();
transformer.transform(inPath, beans);
} catch (IOException e) {
e.printStackTrace();
} catch (InvalidFormatException e) {
e.printStackTrace();
}
I'm having an InvalidFormatException in transformer.transfom (...):
22:44:37,803 ERROR [stderr] (default task-28) org.apache.poi.openxml4j.exceptions.InvalidFormatException: Your InputStream was neither an OLE2 stream, nor an OOXML stream
I investigated that maven causes this data corruption, but I put the filter artifacts in the pom.xml and it still continues to come corrupted:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${compiler-plugin.version}</version>
<configuration>
<encoding>UTF-8</encoding>
<nonFilteredFileExtensions>
<nonFilteredFileExtension>xls</nonFilteredFileExtension>
</nonFilteredFileExtensions>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.5</version>
<inherited>true</inherited>
<configuration>
<encoding>UTF-8</encoding>
<nonFilteredFileExtensions>
<nonFilteredFileExtension>xls</nonFilteredFileExtension>
</nonFilteredFileExtensions>
</configuration>
</plugin>
<plugin>
I was able to solve; I put this artifact in the pom.xml of the project that has the web infrastructure components:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.1.0</version>
<inherited>true</inherited>
<configuration>
<encoding>UTF-8</encoding>
<nonFilteredFileExtensions>
<nonFilteredFileExtension>xls</nonFilteredFileExtension>
</nonFilteredFileExtensions>
</plugin>
</plugins>
</build>
It was probably a problem caused by a specificity of the technical architecture of the project.

How to pass java code a parameter from maven for testing

I need to pass on following values …
exeEvironment (Test environment) ,
testGroup (Group in testNG)
from Command-Line -> POM -> TestNG -> Test cases.
Based on these two posts ....
pass a java parameter from maven
How to pass parameters to guicified TestNG test from Surefire Maven plugin?
I did the following configuration ..
In surefire plugin, I tried following two options, none seem to work.
=====
(1)
<execution>
<id>default-test</id>
<goals>
<goal>test</goal>
</goals>
<configuration>
<properties>
<exeEnvironment>${exeEnvironment}</exeEnvironment>
<testGroup>${testGroup}</testGroup>
</properties>
<suiteXmlFiles>
<suiteXmlFile>testng.xml</suiteXmlFile>
</suiteXmlFiles>
</configuration>
</execution>
(2)
<execution>
<id>default-test</id>
<goals>
<goal>test</goal>
</goals>
<configuration>
<systemPropertyVariables> <exeEnvironment>${exeEnvironment}</exeEnvironment>
<testGroup>${testGroup}</testGroup> </systemPropertyVariables>
<suiteXmlFiles>
<suiteXmlFile>testng.xml</suiteXmlFile>
</suiteXmlFiles>
</configuration>
</execution>
In testNG.xml , can I use the the variable testGroup like …
<test name="Web Build Acceptance">
<groups>
<run>
<include name="${testGroup} />
</run>
</groups>
<classes>
<class name="com.abc.pqr" />
</classes>
</test>
This doesn't seem to work as well, do I need to define a parameter.
In the test cases , I tried to get he variables in following two ways ….
(1)
testEnv = testContext.getSuite().getParameter("exeEnvironment");
testGroup = testContext.getSuite().getParameter("testGroup");
(2)
testEnv = System.getProperty("exeEnvironment");
testGroup = System.getProperty("testGroup");
This is the exact thing I was looking for my automation test and I got it working.
Command Line argument
mvn clean test -Denv.USER=UAT -Dgroups=Sniff
My 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>TestNg</groupId>
<artifactId>TestNg</artifactId>
<version>1.0</version>
<dependencies>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>6.8</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.12.4</version>
<configuration>
<systemPropertyVariables>
<environment>${env.USER}</environment>
</systemPropertyVariables>
</configuration>
</plugin>
</plugins>
</build>
</project>
TestNG test
import org.testng.annotations.Parameters;
import org.testng.annotations.Test;
public class TestAuthentication {
#Test (groups = { "Sniff", "Regression" })
public void validAuthenticationTest(){
System.out.println(" Sniff + Regression" + System.getProperty("environment"));
}
#Test (groups = { "Regression" },parameters = {"environment"})
public void failedAuthenticationTest(String environment){
System.out.println("Regression-"+environment);
}
#Parameters("environment")
#Test (groups = { "Sniff"})
public void newUserAuthenticationTest(String environment){
System.out.println("Sniff-"+environment);
}
}
The above works well. Additionally, if you need to use testng.xml, you can specify the suiteXmlFile like ...
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.12.4</version>
<configuration>
<systemPropertyVariables>
<environment>${env.USER}</environment>
</systemPropertyVariables>
<suiteXmlFiles>
<suiteXmlFile>testng.xml</suiteXmlFile>
</suiteXmlFiles>
</configuration>
</plugin>
Also, I prefer using #Parameters instead of parameters in #Test() as the later is deprecated.
You need not define anything for groups in testng xml or the pom, the support comes inbuilt. You can simply specify the groups on the cmd line
http://maven.apache.org/plugins/maven-surefire-plugin/test-mojo.html#groups
Hope it helps..
Edit 2:
Ok..so here's another option...Implement IMethodInterceptor
Define your custom property.
Use -Dcustomproperty=groupthatneedstoberun in your command line call.
In the intercept call, scan through all methods ..something to the effect..
System.getProperty("customproperty");
for(IMethodInstance ins : methods) {
if(ins.getMethod().getGroups()) contains group)
Add to returnedVal;
}
return returnedVal;
Add this to the listeners list in your xml.
Perfect.
The simplest way to pass the variable from POM.xml to ABC.java
POM.xml
<properties>
<hostName>myhostname.com</hostName>
</properties>
And in the ABC.java we can call it from the system properties like this
System.getProperty("hostName")
Passing parameter like browser and other can be done as below :
<properties>
<BrowserName></BrowserName>
<TestRunID></TestRunID>
</properties>
<!-- Below plug-in is used to execute tests -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.18.1</version>
<configuration>
<suiteXmlFiles>
<suiteXmlFile>src/test/resources/${testXml}</suiteXmlFile>
</suiteXmlFiles>
<systemPropertyVariables>
<browserName>${BrowserName}</browserName>
<testRunID>${TestRunID}</testRunID>
</systemPropertyVariables>
</configuration>
<executions>
<execution>
<id>surefire-it</id>
<phase>integration-test</phase>
<goals>
<goal>test</goal>
</goals>
<configuration>
<skip>false</skip>
<testFailureIgnore>true</testFailureIgnore>
</configuration>
</execution>
</executions>
</plugin>
and to handle this in java code use this :
public static final String Browser_Jenkin=System.getProperty("BrowserName");
public static final String TestRunID=System.getProperty("TestRunID");
public static String browser_Setter()
{
String value=null;
try {
if(!Browser_Jenkin.isEmpty())
{
value = Browser_Jenkin;
}
} catch (Exception e) {
value =propObj.getProperty("BROWSER");
}
return value;
}
public static String testRunID_Setter()
{
String value=null;
try {
if(!TestRunID.isEmpty())
{
value = TestRunID;
}
} catch (Exception e) {
value =propObj.getProperty("TEST_RUN_ID");
}
return value;
}
building on the accepted answer
if maven surefire and the <systemPropertyVariables> are declared in a maven profile, they are not available and will return null unless the profile is also invoked.
Command Line argument
mvn clean test -PmyTestProfile -Denv.USER=UAT -Dgroups=Sniff
pom.xml
<profiles>
<profile>
<id>myTestProfile</id>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>${surefire.version}</version>
<configuration>
<systemPropertyVariables>
<environment>${env.USER}</environment>
</systemPropertyVariables>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
You don't need to use environment variables or edit pom.xml to use them.
The goals and options for Invoke Maven 3 under Build section takes the parameter. Try this (assuming you parameterized the build):
Invoke Maven 3
Goals and options = test -Denv=$PARAM_ENV -Dgroup=$PARAM_GROUP

Resources