title: Creating a custom Jasypt PropertySource in Springboot
body: <p>I'm using Spring Boot to create a simple web application which accesses a database. I'm taking advantage of the autoconfiguration functionality for the DataSource by setting up <code>spring.datasource.*</code> properties in <code>application.properties</code>. That all works brilliantly and was very quick - great work guys @ Spring! </p>
  
  <p>My companys policy is that there should be no clear text passwords. Therefore I need to have the <code>sping.datasource.password</code> encrypted. After a bit of digging around I decided to create a <code>org.springframework.boot.env.PropertySourceLoader</code> implementation which creates a jasypt <code>org.jasypt.spring31.properties.EncryptablePropertiesPropertySource</code> as follows:</p>
  
  <pre><code>public class EncryptedPropertySourceLoader implements PropertySourceLoader
  {
      private final StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor();
  
      public EncryptedPropertySourceLoader()
      {
          //TODO: this could be taken from an environment variable
          this.encryptor.setPassword("password"); 
      }
  
      @Override
      public String[] getFileExtensions()
      {
          return new String[]{"properties"};
      }
  
      @Override
      public PropertySource&lt;?&gt; load(final String name, final Resource resource, final String profile) throws IOException
      {
          if (profile == null)
          {
              final Properties props = PropertiesLoaderUtils.loadProperties(resource);
  
              if (!props.isEmpty())
              {
                  return new EncryptablePropertiesPropertySource(name, props, this.encryptor);
              }
          }
  
          return null;
      }
  }
  </code></pre>
  
  <p>I then packaged this in it's own jar with a <code>META-INF/spring.factories</code> file as follows:</p>
  
  <pre><code>org.springframework.boot.env.PropertySourceLoader=com.mycompany.spring.boot.env.EncryptedPropertySourceLoader
  </code></pre>
  
  <p>This works perfectly when run from maven using <code>mvn spring-boot:run</code>. The problem occurs when I run it as a standalone war using <code>java -jar my-app.war</code>. The application still loads but fails when I try to connect to the database as the password value is still encrypted. Adding logging reveals that the <code>EncryptedPropertySourceLoader</code> is never loaded. </p>
  
  <p>To me this sounds like a classpath issue. When run under maven the jar loading order is strict but once under the embebed tomcat there is nothing to say that my custom jar should be loaded before Spring Boot.</p>
  
  <p>I've tried adding the following to my pom.xml to ensure the classpth is preserved but it doesn't seem to have had any effect.</p>
  
  <pre><code>&lt;build&gt;
      &lt;pluginManagement&gt;
          &lt;plugins&gt;
              &lt;plugin&gt;
                  &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;
                  &lt;artifactId&gt;maven-war-plugin&lt;/artifactId&gt;
                  &lt;configuration&gt;
                      &lt;failOnMissingWebXml&gt;false&lt;/failOnMissingWebXml&gt;
                      &lt;archive&gt;
                          &lt;manifest&gt;
                              &lt;mainClass&gt;${start-class}&lt;/mainClass&gt;
                              &lt;addClasspath&gt;true&lt;/addClasspath&gt;
                          &lt;/manifest&gt;
                      &lt;/archive&gt;
                  &lt;/configuration&gt;
              &lt;/plugin&gt;
          &lt;/plugins&gt;
      &lt;/pluginManagement&gt;
      &lt;plugins&gt;
          &lt;plugin&gt;
              &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
              &lt;artifactId&gt;spring-boot-maven-plugin&lt;/artifactId&gt;
          &lt;/plugin&gt;
      &lt;/plugins&gt;
  &lt;/build&gt;
  </code></pre>
  
  <p>Does anyone have any ideas? Thanks in advance.</p>
  
  <p><b>UPDATE:</b></p>
  
  <p>A step forward: I've managed to fix this by having the <code>EncryptedPropertySourceLoader</code> class implement <code>org.springframework.core.PriorityOrdered</code> interface and returning <code>HIGHEST_PRECEDENCE</code> from <code>getOrder()</code>. This has now fixed the issue of the PropertySourceLoader not being used. However it's now throwing the following error when it tries to decrypt the properties:</p>
  
  <pre><code>org.jasypt.exceptions.EncryptionInitializationException: java.security.NoSuchAlgorithmException: PBEWithMD5AndDES SecretKeyFactory not available
      at org.jasypt.encryption.pbe.StandardPBEByteEncryptor.initialize(StandardPBEByteEncryptor.java:716)
      at org.jasypt.encryption.pbe.StandardPBEStringEncryptor.initialize(StandardPBEStringEncryptor.java:553)
      at org.jasypt.encryption.pbe.StandardPBEStringEncryptor.decrypt(StandardPBEStringEncryptor.java:705)
      at org.jasypt.properties.PropertyValueEncryptionUtils.decrypt(PropertyValueEncryptionUtils.java:72)
      at org.jasypt.properties.EncryptableProperties.decode(EncryptableProperties.java:230)
      at org.jasypt.properties.EncryptableProperties.get(EncryptableProperties.java:209)
      at org.springframework.core.env.MapPropertySource.getProperty(MapPropertySource.java:36)
      at org.springframework.boot.env.EnumerableCompositePropertySource.getProperty(EnumerableCompositePropertySource.java:49)
      at org.springframework.boot.context.config.ConfigFileApplicationListener$ConfigurationPropertySources.getProperty(ConfigFileApplicationListener.java:490)
  </code></pre>
  
  <p>Again this doesn't happen when running from <code>mvn spring-boot:run</code> but does happen when running from the executable war file. Both scenarios use the same JVM (jdk1.6.0_35). Results on Google/Stackoverflow suggest this is an issue with the java security policy but as it does work when run from maven I think I can discount that. Possibly a packaging issue...</p>