title: Spring Boot and Proguard
body: <p>I have a simple Spring Boot 1.5.3 application that I am trying to obfuscate with Proguard 5.x using <code>proguard-maven-plugin</code>. I have the following <code>proguard.conf</code>.</p>
  
  <pre><code>-injars ../$FINAL_NAME$/WEB-INF/lib/$FINAL_NAME$.jar
  
  -outjars ./
  
  -optimizations !class/marking/final
  -dontoptimize
  
  -adaptresourcefilenames **.properties
  -adaptresourcefilecontents **.properties,META-INF/MANIFEST.MF
  
  -dontshrink
  -dontoptimize
  -dontobfuscate
  -dontusemixedcaseclassnames
  -dontpreverify
  -verbose
  
  -keep public class com.test.blah.OnboardingApp {
    public static void main(java.lang.String[]);
  }
  -keep public class * extends org.springframework.boot.web.support.SpringBootServletInitializer
  
  -keep class com.test.blah**.dto.** {
    void set*(***);
    *** get*();
  }
  
  -keepclassmembers class * {
    @org.springframework.beans.factory.annotation.Autowired *;
    @org.springframework.beans.factory.annotation.Qualifier *;
    @org.springframework.beans.factory.annotation.Value *;
    @org.springframework.beans.factory.annotation.Required *;
    @org.springframework.context.annotation.Bean *;
    @org.springframework.context.annotation.Primary *;
    @org.springframework.boot.context.properties.ConfigurationProperties *;
    @org.springframework.boot.context.properties.EnableConfigurationProperties *;
    @javax.inject.Inject *;
    @javax.annotation.PostConstruct *;
    @javax.annotation.PreDestroy *;
  }
  
  -keep @org.springframework.stereotype.Service class *
  -keep @org.springframework.stereotype.Controller class *
  -keep @org.springframework.stereotype.Component class *
  -keep @org.springframework.stereotype.Repository class *
  -keep @org.springframework.cache.annotation.EnableCaching class *
  -keep @org.springframework.context.annotation.Configuration class *
  -keep @org.springframework.boot.context.properties.ConfigurationProperties class *
  -keep @org.springframework.boot.autoconfigure.SpringBootApplication class *
  
  -allowaccessmodification
  -keepattributes Exceptions,InnerClasses,Signature,Deprecated,SourceFile,LineNumberTable,LocalVariable*Table,*Annotation*,Synthetic,EnclosingMethod
  -keepattributes *Annotation*
  -keepattributes Signature
  -keepattributes Exceptions
  -keepattributes InnerClasses
  
  -keepparameternames
  -keepdirectories com.test.blah
  -keepdirectories org.springframework.boot.autoconfigure
  
  -keepclassmembernames class * {
    java.lang.Class class$(java.lang.String);
    java.lang.Class class$(java.lang.String, boolean);
  }
  
  -keepclassmembers enum * {
    public static **[] values();
    public static ** valueOf(java.lang.String);
    public static ** fromValue(java.lang.String);
  }
  
  -keepnames class * implements java.io.Serializable
  -keepclassmembernames public class com.test.blah.config.liquibase.AsyncSpringLiquibase
  
  -keepclassmembers class * implements java.io.Serializable {
    static final long serialVersionUID;
    private static final java.io.ObjectStreamField[] serialPersistentFields;
    !static !transient &lt;fields&gt;;
    !private &lt;fields&gt;;
    !private &lt;methods&gt;;
    private void writeObject(java.io.ObjectOutputStream);
    private void readObject(java.io.ObjectInputStream);
    java.lang.Object writeReplace();
    java.lang.Object readResolve();
  }
  
  -keepclassmembers class * {
    @org.springframework.beans.factory.annotation.Autowired &lt;fields&gt;;
    @org.springframework.beans.factory.annotation.Autowired &lt;methods&gt;;
    @org.springframework.security.access.prepost.PreAuthorize &lt;methods&gt;;
  }
  </code></pre>
  
  <p>Im loading <code>proguard.conf</code> with,</p>
  
  <pre><code>&lt;plugin&gt;
      &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;
      &lt;artifactId&gt;maven-antrun-plugin&lt;/artifactId&gt;
      &lt;version&gt;${maven-antrun-plugin.version}&lt;/version&gt;
      &lt;executions&gt;
          &lt;execution&gt;
              &lt;phase&gt;process-classes&lt;/phase&gt;
              &lt;goals&gt;
                  &lt;goal&gt;run&lt;/goal&gt;
              &lt;/goals&gt;
              &lt;configuration&gt;
                  &lt;target&gt;
                      &lt;mkdir dir="${project.build.directory}/proguarded" /&gt;
                      &lt;copy file="proguard.conf" todir="target/proguarded" /&gt;
                      &lt;replace file="${project.build.directory}/proguarded/proguard.conf"
                               token="$FINAL_NAME$" value="${project.build.finalName}" /&gt;
                  &lt;/target&gt;
              &lt;/configuration&gt;
          &lt;/execution&gt;
      &lt;/executions&gt;
  &lt;/plugin&gt;
  
  &lt;plugin&gt;
      &lt;groupId&gt;com.github.wvengen&lt;/groupId&gt;
      &lt;artifactId&gt;proguard-maven-plugin&lt;/artifactId&gt;
      &lt;version&gt;${proguard-maven-plugin.version}&lt;/version&gt;
      &lt;executions&gt;
          &lt;execution&gt;
              &lt;phase&gt;prepare-package&lt;/phase&gt;
              &lt;goals&gt;
                  &lt;goal&gt;proguard&lt;/goal&gt;
              &lt;/goals&gt;
          &lt;/execution&gt;
      &lt;/executions&gt;
      &lt;configuration&gt;
          &lt;proguardInclude&gt;${project.build.directory}/proguarded/proguard.conf&lt;/proguardInclude&gt;
          &lt;libs&gt;
              &lt;lib&gt;${java.home}/lib/rt.jar&lt;/lib&gt;
              &lt;lib&gt;${java.home}/lib/jce.jar&lt;/lib&gt;
              &lt;lib&gt;${java.home}/lib/jsse.jar&lt;/lib&gt;
          &lt;/libs&gt;
      &lt;/configuration&gt;
  &lt;/plugin&gt;
  </code></pre>
  
  <p>I have no problems generating the <code>war</code> file artifact. However when I deploy to a tomcat instance I get the following error,</p>
  
  <pre><code>Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration$LiquibaseConfiguration': Invocation of init method failed; nested exception is java.lang.IllegalStateException: Cannot find changelog location: class path resource [db/changelog/db.changelog-master.yaml] (please add changelog or check your Liquibase configuration)
      at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:137)
      at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:409)
      at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1620)
      at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:555)
      at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
      at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
      at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
      at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
      at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
      at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:372)
      at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1173)
      at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1067)
      at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:513)
      at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
      at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
      at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
      at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
      at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
      at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:296)
      at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
      at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1081)
      at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:856)
      at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:542)
      at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:122)
      at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:737)
      at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:370)
      at org.springframework.boot.SpringApplication.run(SpringApplication.java:314)
      at org.springframework.boot.web.support.SpringBootServletInitializer.run(SpringBootServletInitializer.java:151)
      at org.springframework.boot.web.support.SpringBootServletInitializer.createRootApplicationContext(SpringBootServletInitializer.java:131)
      at org.springframework.boot.web.support.SpringBootServletInitializer.onStartup(SpringBootServletInitializer.java:86)
      at org.springframework.web.SpringServletContainerInitializer.onStartup(SpringServletContainerInitializer.java:169)
      at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5196)
      at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
      ... 10 more
  Caused by: java.lang.IllegalStateException: Cannot find changelog location: class path resource [db/changelog/db.changelog-master.yaml] (please add changelog or check your Liquibase configuration)
      at org.springframework.util.Assert.state(Assert.java:70)
      at org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration$LiquibaseConfiguration.checkChangelogExists(LiquibaseAutoConfiguration.java:92)
      at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
      at java.lang.reflect.Method.invoke(Method.java:498)
      at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleElement.invoke(InitDestroyAnnotationBeanPostProcessor.java:366)
      at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleMetadata.invokeInitMethods(InitDestroyAnnotationBeanPostProcessor.java:311)
      at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:134)
      ... 42 more
  </code></pre>
  
  <p>In my application I am loading the Liquibase bean with,</p>
  
  <pre><code>@Configuration("databaseConfiguration")
  @EnableJpaRepositories("com.test.blah.repository")
  @EnableJpaAuditing(auditorAwareRef = "springSecurityAuditorAware")
  @EnableTransactionManagement
  @EnableElasticsearchRepositories("com.test.blah.repository.search")
  public class DatabaseConfiguration {
  
      private final Logger log = LoggerFactory.getLogger(DatabaseConfiguration.class);
  
      @Inject
      private Environment env;
  
      @Bean
      public SpringLiquibase liquibase(DataSource dataSource, LiquibaseProperties liquibaseProperties) {
          // Use liquibase.integration.spring.SpringLiquibase if you don't want Liquibase to start asynchronously
          SpringLiquibase liquibase = new AsyncSpringLiquibase();
          liquibase.setDataSource(dataSource);
          liquibase.setChangeLog("classpath:config/liquibase/master.xml");
          liquibase.setContexts(liquibaseProperties.getContexts());
          liquibase.setDefaultSchema(liquibaseProperties.getDefaultSchema());
          liquibase.setDropFirst(liquibaseProperties.isDropFirst());
          if (env.acceptsProfiles(Constants.SPRING_PROFILE_NO_LIQUIBASE)) {
              liquibase.setShouldRun(false);
          } else {
              liquibase.setShouldRun(liquibaseProperties.isEnabled());
              log.debug("Configuring Liquibase");
          }
          return liquibase;
      }
  }
  </code></pre>
  
  <p>Can anyone please suggest why Im seeing the error ?</p>