Spring Framework 3.1あたりから追加された profile機能について軽く説明します。
profile機能とは、実行環境によって異なるJDBC接続プロパティなどを切り替えるための仕組みです。profile機能を使用すると 1つのapplication contextのxmlの中に、開発用、出荷時用の2つのプロファイルとして設定を記述し、実行時にどちらのプロファイルを有効化するかを指定することができます。
以下にxmlの例を書きます。この例は、開発時のUnitTestではin-memory-dbを使用し、出荷時のAPサーバにデプロイしたときはJNDIでDataSourceを取得するような場合の設定方法です。
プロファイル定義
下記のxmlの beans profile="development" と beans profile="production" を見てください。
<beans profile="development"> <jdbc:embedded-database id="dataSource" /> </beans> <beans profile="production" > <bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean"> <property name="jndiName" value="java:comp/env/jdbc/DatabaseName"/> </bean> </beans>
それぞれの<beans>要素は、developmentプロファイルには in-memory-db (参考 Reference Documentation 13.8 Embedded database support)、productionプロファイルにはJNDIで取得するdataSourceを定義しています。
実行時に有効化するプロファイルの指定
springらしく(笑)、さまざまなやり方があります。(参考Spring 3.1 Environment Profiles | Technophile Blog)
ここではいくつかの例を挙げます。
アプリケーション実行時の指定
web.xmlによる指定
Servletの場合はweb.xmlで指定できます
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>spring.profiles.active</param-name>
<param-value>production</param-value>
</init-param>
</servlet>
System Propertyまたは環境変数による指定
java実行時に spring.profiles.activeにプロファイル名を指定できます
-Dspring.profiles.active=production
または
export spring_profiles_active=production
JUnitでの指定
JUnitで springの機能をテストするときに、@ActiveProfilesというアノテーションで、有効化するプロファイルを指定します。このコードではdevelopmentが有効化されるので、このテストのdataSourceは、in-memory-dbになります。
@ContextConfiguration(locations={"/application-context.xml"})
@RunWith(SpringJUnit4ClassRunner.class)
@ActiveProfiles("development")
public class ProfileTest {
@Autowired
private DataSource dataSource;
}
(参考までに): 複数のプロファイル
複数のプロファイルを設定したり、複数のプロファイルを有効化して実行することができます。
複数プロファイルの設定
<beans profile="integration,production" > <!-- integration,productionのいずれか1つが有効化されている場合に、ここのbean定義が使用されます --> <bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean"> <property name="jndiName" value="java:comp/env/jdbc/DatabaseName"/> </bean> </beans>
実行時の複数プロファイル有効化指定
-Dspring.profiles.active=production,apiV2,specialFeatureA
使ってみて思ったこと
経験上これまでspring frameworkを使ったプロジェクトは、xml設定ファイルのデバッグに多大な時間が費やされることが多かったです。しかもAPサーバにデプロイしないと動作しない設定が含まれていると非常にデバッグの効率が悪く、数日ハマることもありました。
profile機能を使うことで、UnitTestと製品用で一元的に設定したものを使用し、環境の差分のみをプロファイルで切り替えることができます。特にDB・トランザクションまわりの設定はシステム全体に関わるものなので、とある機能に必要な設定を追加した途端に、別の機能が動かなくなったりすることがspring frameworkではよく起きます。そういったことをUnitTestの段階で見つけることができるのは非常によいことです。たとえばJenkinsなどのCIサーバでUnitTestを走らせてフィードバックを常に得られていれば、設定関係の問題がデプロイしてから発生することは少なくなり、また発生しても問題箇所が限定的になるためデバッグ効率もこれより向上することが期待できるのではないでしょうか。
まとめ
profile機能は複数の異なる設定をプロファイルとして定義し、実行環境で有効化したい設定をプロファイルを指定することで切り替えることができます。
UnitTestと製品で同じ設定ファイルを使用していれば、設定ファイルに関係する問題の多くを早い段階で見つけることができるのです。