Spring Boot Maven Project Obfuscation with Proguard - spring-boot

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

Related

AspectJ binary weaving with Jcabi Maven plugin not working for Kotlin code

I'm trying to run a little annotation over function that will log before and after the method execution.
What I've done: (all classes are under src/main/kotlin)
Annotation class
#Target(AnnotationTarget.FUNCTION)
#Retention(AnnotationRetention.RUNTIME)
annotation class LogMe
Aspect class
import org.aspectj.lang.JoinPoint
import org.aspectj.lang.ProceedingJoinPoint
import org.aspectj.lang.annotation.Around
import org.aspectj.lang.annotation.Aspect
#Aspect
abstract class Aspect {
#Around("#annotation(LogMe) && execution(* *(..))")
fun logMe(joinPoint: ProceedingJoinPoint): Any {
beforeExecution(joinPoint)
afterExecution(joinPoint)
return joinPoint.proceed()
}
private fun beforeExecution(joinPoint: JoinPoint) {
println("[${joinPoint.signature.name} has started its execution]")
}
private fun afterExecution(joinPoint: JoinPoint) {
println("[${joinPoint.signature.name} has ended its execution]")
}
}
Foo class with annotated method
class Foo {
#LogMe
fun yourMethodAround() {
println("Executing foo.yourMethodAround()")
}
}
main file
fun main(args: Array<String>) {
val foo = Foo()
foo.yourMethodAround()
}
my POM.xml (cut version)
...
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib-jdk8</artifactId>
<version>1.3.40</version>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-reflect</artifactId>
<version>1.3.40</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.9.4</version>
</dependency>
<!-- TEST -->
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-test</artifactId>
<version>1.3.40</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-test-junit</artifactId>
<version>1.3.40</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<sourceDirectory>src/main/kotlin</sourceDirectory>
<testSourceDirectory>src/test/kotlin</testSourceDirectory>
<plugins>
<plugin>
<artifactId>kotlin-maven-plugin</artifactId>
<configuration>
<jvmTarget>1.8</jvmTarget>
</configuration>
<groupId>org.jetbrains.kotlin</groupId>
<version>1.3.40</version>
<executions>
<execution>
<id>kapt</id>
<goals>
<goal>kapt</goal>
</goals>
</execution>
<execution>
<id>compile</id>
<phase>compile</phase>
<goals> <goal>compile</goal> </goals>
</execution>
<execution>
<id>test-compile</id>
<phase>test-compile</phase>
<goals> <goal>test-compile</goal> </goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>com.jcabi</groupId>
<artifactId>jcabi-maven-plugin</artifactId>
<version>0.14.1</version>
<executions>
<execution>
<goals>
<goal>ajc</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>MainKt</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.4.3</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
...
When I basically run this main, what I'm obtaining is the println that it's into my Foo class method:
Executing foo.yourMethodAround()
But I'm not getting the before and after execution prinln that I was expecting from the Aspect class.
Does any of you ever faced this issue before? This is struggling me, because I can't understand what's going on here.
Disclaimer:
I have never used the Jcabi plugin before, normally I always use AspectJ Maven plugin, also for binary weaving.
I have never used the Kotlin language before, normally I use Java or Groovy.
Now some things are not okay in your aspect:
It must not be abstract, otherwise no instance can be created.
For void methods it must be able to return null, so the Kotlin return type should be Any?
You should proceed() in between the before and after log messages, otherwise the log output will be wrong.
Assuming that your classes, especially the annotation class, do not reside in the default package but have an actual package name, you need to use the fully qualified class name in your pointcut, e.g. #annotation(de.scrum_master.app.LogMe)
Using an aspect class name Aspect, i.e. the same name as the #Aspect annotation, just in another package, is kind of ugly. You should rename it.
For me this works nicely:
package de.scrum_master.aspect
import org.aspectj.lang.JoinPoint
import org.aspectj.lang.ProceedingJoinPoint
import org.aspectj.lang.annotation.Around
import org.aspectj.lang.annotation.Aspect
#Aspect
class LogAspect {
#Around("#annotation(de.scrum_master.app.LogMe) && execution(* *(..))")
fun logMe(joinPoint: ProceedingJoinPoint): Any? {
beforeExecution(joinPoint)
val result = joinPoint.proceed()
afterExecution(joinPoint)
return result
}
private fun beforeExecution(joinPoint: JoinPoint) {
println("[${joinPoint.signature.name} has started its execution]")
}
private fun afterExecution(joinPoint: JoinPoint) {
println("[${joinPoint.signature.name} has ended its execution]")
}
}
Besides, maybe you also should configure the Jcabi plugin to language level Java 8. It works without it here, but maybe it is better depending on which language features you use:
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
My console after mvn clean verify looks like this:
$ java -jar target/so-aj-kotlin-56890630-1.0-SNAPSHOT.jar
[yourMethodAround has started its execution]
Executing foo.yourMethodAround()
[yourMethodAround has ended its execution]
My IDE IntelliJ IDEA does not quite pick up the binary weaving stuff because it does not know Jcabi, only AspectJ Maven. So I just configured the project to delegate compilation to Maven:
Then the log output is the same when running the application from IDEA directly.

QueryDslPredicateExecutor Q-class is not generating

My Pom file is
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-apt</artifactId>
<version>4.0.6</version>
</dependency>
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-jpa</artifactId>
<version>4.0.6</version>
</dependency>
<plugin>
<groupId>com.mysema.maven</groupId>
<artifactId>apt-maven-plugin</artifactId>
<version>1.1.3</version>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>process</goal>
</goals>
<configuration>
<outputDirectory>target/generated-sources</outputDirectory>
<processor>com.querydsl.apt.jpa.JPAAnnotationProcessor</processor>
</configuration>
</execution>
</executions>
</plugin>
After adding those dependency and plugin in pom.xml, I ran mvn clean install, QAutoManifest is not generating. I am new to jpa, Please help me.
public interface AutoManifestRepository extends CrudRepository<AutoManifest,String>,QueryDslPredicateExecutor<AutoManifest>{
}
And my Predicate class is
public class AutoManifestPredicate {
private AutoManifestPredicate() {
System.out.println("Predicate Object gets created");
}
static Predicate searchAutoManifest(SearchAutoManifest manifest) {
return null;
}
}

Spring project obfuscation using proguard using Maven

is there any good example for obfuscating Spring application using proguard & Maven ? I tried adding this snippet in pom.xml. My project is compiling and running, but did not get obfuscated.
I was able to decompile my war file and view the code. Is there any setting required to obfuscate generated file ??
<!-- ProGuard obfuscation plugin -->
<plugin>
<groupId>com.github.wvengen</groupId>
<artifactId>proguard-maven-plugin</artifactId>
<version>2.0.6</version>
<executions>
<execution>
<configuration>
<obfuscate>true</obfuscate>
<proguardVersion>5.2.1</proguardVersion>
<options>
<option>-target 1.7</option>
<option>-dontnote</option>
<option>-dontpreverify</option>
<option>-dontskipnonpubliclibraryclasses</option>
<option>-dontskipnonpubliclibraryclassmembers</option>
<option>-allowaccessmodification</option>
<option>-repackageclasses ''</option>
<option>-keep public class ${mainClass} { public static void
main(java.lang.String[]); }</option>
<option>-keepattributes
InnerClasses,Signature,LineNumberTable,*Annotation*,EnclosingMethod</option>
<option>-keepclassmembers enum * { public static **[] values();
public static ** valueOf(java.lang.String); }</option>
<option>-dontwarn org.spout.**</option>
<option>-dontwarn com.google.**</option>
</options>
<proguardInclude>${basedir}/proguard.conf</proguardInclude>
<includeDependency>false</includeDependency>
<libs>
<lib>${java.home}/lib/jce.jar</lib>
<lib>${java.home}/lib/jfxrt.jar</lib>
<lib>${java.home}/lib/rt.jar</lib>
</libs>
</configuration>
<phase>package</phase>
<goals>
<goal>proguard</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>net.sf.proguard</groupId>
<artifactId>proguard-base</artifactId>
<version>5.2.1</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>net.sf.proguard</groupId>
<artifactId>proguard</artifactId>
<version>4.4</version>
</dependency>
</dependencies>
</plugin>

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 JBehave : encoding stories UTF8

We managed to create and run tests with internationalized stories using JBehave within eclipse.
Everything went fine.
But when we tried to run them using the maven plug-in, we cannot get rud of the encoding problem (for example, instead of reading "scénario" from the story, it gets "Scénario" : clearly an UTF8 encoding problem).
Does someone have found a way to get JBehave to read the stories in UTF8 using the maven plug-in ?
What we already tried :
adding -Dfile.encoding=UTF-8 option
changing keyword file using UTF8
changing the whole project encoding in ISO => which works but isn't suitable for production part that need to display messages in UTF8
our 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">
...
<properties>
<jbehave.version>3.6.5</jbehave.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<resource.encoding>UTF-8</resource.encoding>
</properties>
<build>
<testOutputDirectory>target/classes</testOutputDirectory>
<testResources>
<testResource>
<directory>src/test/resources</directory>
</testResource>
<testResource>
<directory>src/test/story</directory>
</testResource>
</testResources>
<plugins>
...
<plugin>
<artifactId>maven-eclipse-plugin</artifactId>
<version>2.8</version>
<configuration>
<downloadSources>true</downloadSources>
<downloadJavadocs>true</downloadJavadocs>
<additionalBuildcommands>
<buildcommand>com.google.gdt.eclipse.core.webAppProjectValidator</buildcommand>
</additionalBuildcommands>
<additionalProjectnatures>
<projectnature>com.google.gwt.eclipse.core.gwtNature</projectnature>
</additionalProjectnatures>
<classpathContainers>
<classpathContainer>org.eclipse.jdt.launching.JRE_CONTAINER</classpathContainer>
</classpathContainers>
<additionalConfig>
<file>
<name>.settings/org.eclipse.core.resources.prefs</name>
<content>
<![CDATA[eclipse.preferences.version=1
encoding/<project>=UTF-8]]>
</content>
</file>
</additionalConfig>
</configuration>
</plugin>
<plugin>
<groupId>org.jbehave</groupId>
<artifactId>jbehave-maven-plugin</artifactId>
<version>${jbehave.version}</version>
<executions>
<execution>
<id>run-stories-as-embeddables</id>
<phase>test</phase>
<configuration>
<scope>test</scope>
<includes>
<include>**/*Story.java</include>
</includes>
<ignoreFailureInStories>true</ignoreFailureInStories>
<ignoreFailureInView>false</ignoreFailureInView>
</configuration>
<goals>
<goal>run-stories-as-embeddables</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>unpack-jbehave-site-resources</id>
<phase>generate-resources</phase>
<goals>
<goal>unpack</goal>
</goals>
<configuration>
<overwriteReleases>false</overwriteReleases>
<overwriteSnapshots>true</overwriteSnapshots>
<artifactItems>
<artifactItem>
<groupId>org.jbehave.site</groupId>
<artifactId>jbehave-site-resources</artifactId>
<version>3.1.1</version>
<type>zip</type>
<outputDirectory>
${project.build.directory}/jbehave/view
</outputDirectory>
</artifactItem>
</artifactItems>
</configuration>
</execution>
<execution>
<id>unpack-jbehave-reports-resources</id>
<phase>generate-resources</phase>
<goals>
<goal>unpack</goal>
</goals>
<configuration>
<overwriteReleases>false</overwriteReleases>
<overwriteSnapshots>true</overwriteSnapshots>
<artifactItems>
<artifactItem>
<groupId>org.jbehave</groupId>
<artifactId>jbehave-core</artifactId>
<version>${jbehave.version}</version>
<outputDirectory>
${project.build.directory}/jbehave/view
</outputDirectory>
<includes>
**\/*.css,**\/*.ftl,**\/*.js
</includes>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
...
<!-- JBehave Dependencies -->
<dependency>
<groupId>org.jbehave</groupId>
<artifactId>jbehave-core</artifactId>
<version>${jbehave.version}</version>
</dependency>
<!-- Test Frameworks Dependencies -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.8.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>1.8.4</version>
<scope>test</scope>
</dependency>
</dependencies>
I have had some success subclassing the org.jbehave.core.io.LoadFromClasspath class, which I use in my configuration as the story loader, i.e.
MostUsefulConfiguration().useStoryLoader(new LoadFromClasspathUtf8());
here's my subclass with the proper method override:
import java.io.IOException;
import java.io.InputStream;
import org.apache.commons.io.IOUtils;
import org.jbehave.core.io.InvalidStoryResource;
import org.jbehave.core.io.LoadFromClasspath;
public class LoadFromClasspathUtf8 extends LoadFromClasspath {
public LoadFromClasspathUtf8(Class<?> loadFromClass) {
super(loadFromClass);
}
public LoadFromClasspathUtf8(ClassLoader classLoader) {
super(classLoader);
}
#Override
public String loadResourceAsText(String resourcePath) {
InputStream stream = resourceAsStream(resourcePath);
try {
return IOUtils.toString(stream, "UTF-8");
} catch (IOException e) {
throw new InvalidStoryResource(resourcePath, stream, e);
}
}
}
I say "I had some success" because when I look at the logs of my jbehave execution, accented french characters like è,à,é etc. are replaced by ?, but then, jbehave still matches this correctly to the steps using the regular RegexStoryParser. I didn't take time to investigate why this is, but I'm satisfied that my stories work correctly now.
I also added the file.encoding system property to my plugin configuration to make it clear that I intend to use UTF-8 encoding.
Same problem here as well. Even after adding the "-Dfile.encoding=UTF-8" parameter to MAVEN_OPTS the problem persisted. Turn out that I had this line inside my ~/.mavenrc file:
export MAVEN_OPTS="-Xmx1024m"
What was happening is the MAVEN_OPTS variable got reset before executing the JVM.
After change the ~/.mavenrc file to:
export MAVEN_OPTS="$MAVEN_OPTS -Xmx1024m"
The problem was solved. The file encoding is set correct when running:
export MAVEN_OPTS="$MAVEN_OPTS -Dfile.encoding=UTF-8"
mvn clean integration-test
Since you have your stories in the "test" context rather than "main" (in another module) - I think that there is probably something going on when stories are copied to target/test-classes.
I had exactly the same problem. By default, JBehave doesn't honor platform encoding. In order to fix this, you can use this custom StoryLoader which honors file.encoding system property:
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import org.apache.commons.io.IOUtils;
import org.jbehave.core.io.InvalidStoryResource;
import org.jbehave.core.io.LoadFromClasspath;
/**
* #author cedric.vidal
*
*/
public class FixedStoryLoader extends LoadFromClasspath {
public String loadResourceAsText(String resourcePath) {
InputStream stream = resourceAsStream(resourcePath);
try {
return IOUtils.toString(stream, platformCharset().name());
} catch (IOException e) {
throw new InvalidStoryResource(resourcePath, stream, e);
}
}
public static Charset platformCharset() {
String csn = System.getProperty("file.encoding");
Charset cs = Charset.forName(csn);
if (cs == null) {
cs = Charset.forName("UTF-8");
}
return cs;
}
}
Register it in JBehave configuration with:
new MostUsefulConfiguration().useStoryLoader(new FixedStoryLoader());
Configure your POM to use UTF-8 in all respectfull plugins (will be used by m2eclipse too):
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
And tell the JBehave Maven Plugin to use it also (look for the systemProperties block):
<plugin>
<groupId>org.jbehave</groupId>
<artifactId>jbehave-maven-plugin</artifactId>
<version>${jbehave.core.version}</version>
<executions>
<execution>
<id>unpack-view-resources</id>
<phase>process-resources</phase>
<goals>
<goal>unpack-view-resources</goal>
</goals>
</execution>
<execution>
<id>embeddable-stories</id>
<phase>integration-test</phase>
<configuration>
<includes>
<include>${embeddables}</include>
</includes>
<excludes/>
<systemProperties>
<property>
<name>file.encoding</name>
<value>${project.build.sourceEncoding}</value>
</property>
</systemProperties>
<ignoreFailureInStories>true</ignoreFailureInStories>
<ignoreFailureInView>false</ignoreFailureInView>
<threads>1</threads>
<metaFilters>
<metaFilter/>
</metaFilters>
</configuration>
<goals>
<goal>run-stories-as-embeddables</goal>
</goals>
</execution>
</executions>
</plugin>

Resources