0
votes

I'm using ProGuard for spring-boot app obfuscation. It's working fine, resulting jar is builded and is running well, without any issues.

To achieve that I used a few tweaks:

  • custom beanNameGenerator

        public static void main(String[] args) {
            new SpringApplicationBuilder(MainApp.class)
              .beanNameGenerator((beanDefinition, beanDefinitionRegistry) -> beanDefinition.getBeanClassName())
              .run(args);
         }
    
  • preservation of Autowired, Qualifier, Bean, Value annotation members,
  • preservation of main method
  • keepattributes switch with Exceptions, InnerClasses, Signature, Deprecated, SourceFile, LineNumberTable, Annotation, EnclosingMethod
  • dontshrink, dontoptimize, useuniqueclassmembernames, adaptclassstrings, dontusemixedcaseclassnames options

However, integration tests (@SpringBootTest) broke with error (they are running fine when builded without proguard):

java.lang.IllegalStateException: Unable to find a @SpringBootConfiguration, you need to use @ContextConfiguration or @SpringBootTest(classes=...) with your test.

After include of main entry class (@SpringBootTest(classes=MainApp.class)) :

2019-09-11 19:00:13,178 [main] ERROR org.springframework.test.context.TestContextManager - Caught exception while allowing TestExecutionListener [org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener@6b04acb2] to prepare te
st instance [com.xxx.xxx.it.ExternalIT@258274cb]
java.lang.IllegalStateException: Failed to load ApplicationContext
        at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:125) ~[spring-test-5.1.7.RELEASE.jar:5.1.7.RELEASE]
...
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.xxx.xxx.a.a.b' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}

And so on.

Is there any way to make it work, other than creating new profile for performing tests without obfuscating?

2

2 Answers

1
votes

preservation of Autowired, Qualifier, Bean, Value annotation members,

You did the right thing here,you need to preserve all attribute

-keepattributes Exceptions,InnerClasses,Signature,Deprecated,SourceFile,LineNumberTable,LocalVariable*Table,*Annotation*,Synthetic,EnclosingMethod

however It's not the cause of your problem,Spring does the autowiring byType and in my experience post obfuscation such issue comes of not finding bean of type.

You need to tweak your code, use your annotation with name like

@Component("yourComponentName")

instead of

@Component

same with bean and Service and other annotation

and wherever you use then use @Qualifier("nameofbeanorService")

and since you preserved annotation attribute your application will work smooth.

Thanks

0
votes

Extracting BeanNameGenerator to separate Bean and registering it in @ComponentScan in @SpringBootApplication, instead of inlining it in SpringApplicationBuilder in main method made things working.