ProGuard + Spring Boot + Maven Plugin - maven

Guys, I'm trying to obfuscate a .jar application using the proguard-maven-plugin.
When I try to perform the obfuscate process, I get error messages stating that there are unexpected classes.
I'm using the Spring Boot 1.4.1.RELEASE and Proguard Maven Plugin 2.0.13.
This is my proguard.conf
-injars /workspace/base/target/test-1.0.0.jar
-libraryjars /Library/Java/JavaVirtualMachines/jdk1.8.0_101.jdk/Contents/Home/jre/lib/rt.jar
-dontshrink
-dontoptimize
-dontobfuscate
-dontusemixedcaseclassnames
-keepattributes Exceptions,InnerClasses,Signature,Deprecated,SourceFile,LineNumberTable,LocalVariable*Table,*Annotation*,Synthetic,EnclosingMethod
-adaptresourcefilenames **.properties
-adaptresourcefilecontents **.properties,META-INF/MANIFEST.MF
-dontpreverify
-verbose
-keepclasseswithmembers public class * {
public static void main(java.lang.String[]);
}
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
-keep class * extends java.beans.BeanInfo
-keep class * {
void set*(***);
void set*(int,***);
boolean is*();
boolean is*(int);
*** get*();
*** get*(int);
}
-assumenosideeffects public class java.lang.System {
public static long currentTimeMillis();
static java.lang.Class getCallerClass();
public static int identityHashCode(java.lang.Object);
public static java.lang.SecurityManager getSecurityManager();
public static java.util.Properties getProperties();
public static java.lang.String getProperty(java.lang.String);
public static java.lang.String getenv(java.lang.String);
public static java.lang.String mapLibraryName(java.lang.String);
public static java.lang.String getProperty(java.lang.String,java.lang.String);
}
The pom.xml file. I am only informing the configuration by the plugin.
<plugin>
<groupId>com.github.wvengen</groupId>
<artifactId>proguard-maven-plugin</artifactId>
<version>2.0.13</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>proguard</goal>
</goals>
</execution>
</executions>
<configuration>
<obfuscate>false</obfuscate>
<outFilter>**/BOOT-INF/classes/ **.class</outFilter>
<proguardInclude>${basedir}/proguard.conf</proguardInclude>
<outputDirectory>${project.build.directory}</outputDirectory>
<injar>${project.build.finalName}.jar</injar>
<outjar>${project.build.finalName}-min.jar</outjar>
</configuration>
</plugin>
However, during the execution process I get the following return for all classes in my application.
Warning: class [BOOT-INF/classes/br/com/base/BaseApplication.class] unexpectedly contains class [br.com.base.BaseApplication]
Warning: class [BOOT-INF/classes/br/com/base/controller/CaixaController.class] unexpectedly contains class [br.com.base.controller.CaixaController]
[...]
And the final output of ProGuard. PS: All classes are in the BOOT-INF/classes directory
Warning: there were 97 classes in incorrectly named files.
You should make sure all file names correspond to their class names.
The directory hierarchies must correspond to the package hierarchies.
(http://proguard.sourceforge.net/manual/troubleshooting.html#unexpectedclass)
If you don't mind the mentioned classes not being written out,
you could try your luck using the '-ignorewarnings' option.
Please correct the above warnings first.
Can anyone imagine any alternatives I can try?
Thanks.

In order to fix this, I made sure to change the order of the plugins in the pom. The proguard plugin should go first, followed by the spring boot plugin.
Additionally, make sure you have the <goal>repackage</goal> specified in the spring boot configuration. With the correct order and the repackage goal specified, the proguard obfuscation/optimization/whatever you have configured will take place and produce a jar. Then the spring boot plugin will repackage that jar as an executable and everything should work.
My plugin configuration from pom.xml:
<project ...>
....
<plugin>
<groupId>com.github.wvengen</groupId>
<artifactId>proguard-maven-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>proguard</goal>
</goals>
</execution>
</executions>
<configuration>
<proguardInclude>${basedir}/proguard.conf</proguardInclude>
<libs>
<lib>${java.home}/lib/rt.jar</lib>
<lib>${java.home}/lib/jce.jar</lib>
</libs>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
<configuration>
<start-class>org.springframework.boot.loader.JarLauncher</start-class>
</configuration>
</execution>
</executions>
</plugin>
...

Related

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

Cucumber Parallel Testing giving weird results

I'm trying to run my cucumber project (two runner classes) in parallel browsers and I am getting weird results. When I do a mvn verify, first it will run each runner class sequentially. The first will pass and the second will fail due to the following error -
org.openqa.selenium.NoSuchSessionException: Session ID is null. Using WebDriver after calling quit()?
Then right after, it will run both runner classes in parallel (like I want it to), and all will pass just fine. And maven will report the Build Success.
I am not initializing the webdriver in the #Before annotation. Instead I am using cucumber-picocontainer dependency injection right into my step definition classes. I have tried swapping driver.close() and driver.quit() in my #After annotation, but that didn't change the results. Please find some code snippets below and then my POM. Many thanks in advance.
public class GivenSteps {
WebDriver driver;
CustomWaits waits;
public GivenSteps(DependencyInjection dependencyInjection) {
this.driver = dependencyInjection.getDriver();
this.waits = dependencyInjection.getWaits();
}
Hooks -
public class Hooks {
WebDriver driver;
public Hooks(DependencyInjection dependencyInjection) {
this.driver = dependencyInjection.getDriver();
}
#Before("#setup")
public void setUp() {
driver.manage().deleteAllCookies();
driver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS);
driver.manage().timeouts().pageLoadTimeout(20, TimeUnit.SECONDS);
}
#After("#destroy")
public void tearDown() throws Throwable {
//driver.close();
driver.quit();
}
Dependency Injection -
public class DependencyInjection {
private static String browserType = Settings.BROWSER.getValue();
private static WebDriver driver = null;
private static CustomWaits waits = null;
public WebDriver getDriver() {
if (driver == null) {
driver = utilities.DriverFactory.createDriver(browserType);
}
return driver;
}
POM.xml -
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.20.1</version>
<configuration>
<testFailureIgnore>true</testFailureIgnore>
<includes>
<exclude>
**/*Runner.java
</exclude>
</includes>
</configuration>
</plugin>
<plugin>
<groupId>com.github.temyers</groupId>
<artifactId>cucumber-jvm-parallel-plugin</artifactId>
<version>5.0.0</version>
<executions>
<execution>
<id>generateRunners</id>
<phase>generate-test-sources</phase>
<goals>
<goal>generateRunners</goal>
</goals>
<configuration>
<glue>
<package>test.java.stepDefinitions</package>
</glue>
<outputDirectory>target/generated-test-sources/cucumber</outputDirectory>
<featuresDirectory>src/test/resource/</featuresDirectory>
<cucumberOutputDir>target/Reports/</cucumberOutputDir>
<namingPattern>Runner{c}</namingPattern>
<!-- One of [SCENARIO, FEATURE]. SCENARIO generates one runner per
scenario. FEATURE generates a runner per feature. -->
<parallelScheme>FEATURE</parallelScheme>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>2.19.1</version>
<executions>
<execution>
<id>acceptance-test</id>
<phase>integration-test</phase>
<goals>
<goal>integration-test</goal>
</goals>
<configuration>
<forkCount>10</forkCount>
<reuseForks>true</reuseForks>
<includes>
<include>**/*Runner.class</include>
</includes>
</configuration>
</execution>
</executions>
</plugin>
I had to comment out the section in my POM.xml -> maven-surefire-plugin because now I am only using maven-failsafe-plugin
Originally I had both active in my POM, so both were running sequentially.

Jaxb2 maven plugin getting error when generating xsd from complex classes

I have a case that i have 35 classes that some of them related with each other inside of them. Such as;
Addendum.java
#XmlType(name="addendum",namespace= GenericNameSpaceConstants.POLICY_NAMESPACE_URI)
#XmlAccessorType(XmlAccessType.FIELD)
public class Addendum implements Serializable {
#XmlElement(name="changeNumber",nillable=false,required=true)
private Long changeNumber;
#XmlElement(name="changeTypeDesc",nillable=false,required=true)
private String changeTypeDesc;
#XmlElement(name="changeTypeId",nillable=false,required=true)
private Integer changeTypeId;
}
Policy.java
#XmlRootElement(name="policy",namespace=GenericNameSpaceConstants.POLICY_NAMESPACE_URI)
#XmlType(name="policy",namespace= GenericNameSpaceConstants.POLICY_NAMESPACE_URI)
#XmlAccessorType(XmlAccessType.FIELD)
public class Policy {
#XmlElement(name="addendum",required=true,nillable=false)
private Addendum addendum;
}
My jaxb schemage config in pom file like that
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>jaxb2-maven-plugin</artifactId>
<version>2.2</version>
<configuration>
<createJavaDocAnnotations>false</createJavaDocAnnotations>
<sources>
<source>
${project.basedir}\src\main\java\com\aegon\common\service\bean\
</source>
</sources>
<verbose>true</verbose>
<outputDirectory>${basedir}/src/main/resources/schemas</outputDirectory>
<transformSchemas>
<transformSchema>
<toPrefix>pol</toPrefix>
<toFile>policy_model_v2.xsd</toFile>
</transformSchema>
</transformSchemas>
<generateEpisode>true</generateEpisode>
</configuration>
<executions>
<execution>
<phase>generate-resources</phase>
<goals>
<goal>schemagen</goal>
</goals>
</execution>
</executions>
</plugin>
When i run the project for phase generate-resources or generate-sources. I am getting this error Addendum is a non-static inner class, and JAXB can't handle those.
How can i resolve this problem?? How can i generate all classes xsd in a simple xsd Or how can i create xsds' one by one and import to complex one
I have found the problem. every class need a default constructor

How to define #Parameter annotation in Maven POM

I wrote a Mojo Plugin and set two #Parameter (import org.apache.maven.plugins.annotations.Parameter;)
I want to configure the Parameters in the POM of the project where I want to use this plugin.
No matter where everytime I get an error message.
The part of the POM:
<plugin>
<groupId>com.tup.test</groupId>
<artifactId>versionsextra</artifactId>
<version>1.0-SNAPSHOT</version>
<executions>
<execution>
<id>path</id>
<phase>test</phase>
<configuration>
<path>${basedir}/src/main/resources/configsys/dev/etc/deploy_env</path>
</configuration>
</execution>
</executions>
So one of the Parameter is called path:
#Parameter()
private String path;
ok, I got it.
I have to declare it like this:
#Mojo(name="devversion")
public class ParameterMojo extends AbstractMojo {
#Parameter()
private String path;
#Parameter()
private String pathsave;
...
And in POM:
<plugin>
<groupId>com.tup.test</groupId>
<artifactId>versionsextra</artifactId>
<version>1.0-SNAPSHOT</version>
<executions>
<execution>
<id>testen</id>
<phase>initialize</phase>
<goals>
<goal>devversion</goal>
</goals>
<configuration>
<path>${basedir}/src/main/resources/configsys/dev/etc/deploy_env</path>
<pathsave>${basedir}/src/main/resources/configsys/dev/etc/test.txt</pathsave>
</configuration>
</execution>
</executions>
</plugin>

Maven mojo not picking up configuration from pom

I've written a Maven plugin and incorporated it as a goal in the package phase of another project with configuration given in that project's pom.xml. However, none of the fields set using the #parameter notation end up being populated so they just throw NullPointerExceptions when they get used.
My mojo:
/**
* #goal wrap
* #phase package
*/
public class MyMojo extends AbstractMojo {
/**
* #parameter expression="${project.build.directory}"
*/
private String outputDirectory;
/**
* #parameter
*/
private String dbDataName;
private File dbFile;
public MyMojo(){
dbFile = new File(outputDirectory, dbDataName) // throws nullpointerexception
}
public void execute() throws MojoExecutionException{
// Do stuff
}
}
Some of the mojo pom:
<groupId>com.mycompany.wrapper</groupId>
<artifactId>something-maven-plugin</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>maven-plugin</packaging>
...
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-plugin-plugin</artifactId>
<version>3.2</version>
<configuration>
<skipErrorNoDescriptorsFound>true</skipErrorNoDescriptorsFound>
</configuration>
<executions>
<execution>
<id>mojo-descriptor</id>
<goals>
<goal>descriptor</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
The relevant bit of my project pom:
<plugin>
<groupId>com.mycompany.wrapper</groupId>
<artifactId>something-maven-plugin</artifactId>
<version>1.0-SNAPSHOT</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>wrap</goal>
</goals>
<configuration>
<dbDataName>dcbTestData.sql</dbDataName>
</configuration>
</execution>
</executions>
</plugin>
Can anyone see what I'm doing wrong here? Most likely it's some silly mistake that I'm just not seeing.
I've solved the problem. I had done a few things wrong but after changing and tinkering, I managed to work it out.
Incidentally, this process was made rather harder by the fact that the Maven docs and user guides are a bit inconsistent about whether they prefer the annotations or the javadocs styles, and in some places they recommend deprecated methods, such as the expression="${stuff}" form.
Anyway to get it working:
I corrected the mistakes pointed out by khmarbaise in his first comment where I had slightly mangled the maven-plugin-plugin definition in my pom.
I updated to the Java annotations based way of denoting Mojos and parameters (it might have worked if I had done step 3 without doing this step, but it still seemed a good idea to update)
The main problem was that I was trying to access the parameter variables in the constructor to assign values to other variables but the mojo doesn't pick up the configuration details until the execute() method is run. So I just moved any variable assignments that used the parameters to the start of the execute() method and then they worked.
So here's what my mojo looks like now:
#Mojo(name = "wrap", defaultPhase = LifecyclePhase.PACKAGE)
public class MyMojo extends AbstractMojo {
#Parameter(property="project.build.directory")
private File outputDirectory;
#Parameter(property="dbDataName")
private String dbDataName;
private File dbFile;
public void execute()
throws MojoExecutionException {
dbFile = new File(outputDirectory, dbDataName);
// Do other stuff
}
}
You should change your code like the following:
/**
* #parameter default-value="${project.build.directory}"
*/
private String outputDirectory;

Resources