Spring Boot でメール送信する Web アプリケーションを作る ( その10 )( DataSource Bean の独自定義は不要?他 )
概要
Spring Boot でメール送信する Web アプリケーションを作る ( その9 )( メール送信画面の作成4 ) の続きです。
いろいろ修正したい部分があったので、メール送信画面の作成を一時中断して修正作業を行います。
今回の手順で確認できるのは以下の内容です。
- 以下の点を調査・修正します。
- Spring Boot でメール送信する Web アプリケーションを作る ( 番外編 )( DataSource Bean に application.properties の設定が反映される仕組みとは? )で DataSourceAutoConfiguration.java で DataSource Bean が自動生成されることに気づいたので、ApplicationConfig クラスで定義しなくてもよいか確認します。
- DataSourceAutoConfiguration.java を見て、インナークラスに @Configuration アノテーションを付加し、その中で Bean を生成出来ることに気づいたので、今の DomaBeanConfig クラスを DomaConfig クラスのインナークラスに出来ないか確認します。DomaBeanConfig クラスと DomaConfig クラスは出来れば1つにしたいと考えていました。
- MAIL001MailBuilder クラスを以下のように作り直します。
- package を ksbysample.webapp.email.web.mailsend → ksbysample.webapp.email.helper.mail へ移動します。
- クラス名を MAIL001MailBuilder → MAIL001MailHelper へ変更します。
- MAIL001MailHelper クラスに @Component アノテーションを付加します。
- Velocity のテンプレートファイルのパスをセットするフィールド templateLocation は MAIL001MailHelper クラス内で private final String で定数として定義します。
- VelocityUtils クラスをメソッドでセットするのではなく @Autowired で DI させます。
- build メソッドを削除し、create メソッドはメソッド名を createMessage へ変更します。
- 変数 mailsendForm は createMessage メソッドの引数で受け取ります。
- Doma-Gen で自動生成した Dao クラス、Entity クラスのファイルを Gradle の gen タスク内で git add させる方法があるのか調査します。
- 以下の点を調査・修正します。
ソフトウェア一覧
参考にしたサイト
Gradle Goodness: Use Git Commit Id in Build Script
http://mrhaki.blogspot.jp/2015/04/gradle-goodness-use-git-commit-id-in.html- build.gradle 内で git レポジトリにアクセスする方法 ( Grgit を使用する ) を参考にしました。
grgit 1.1.0 API
http://ajoberstar.org/grgit/docs/groovydoc/index.htmldomaframework/master/build.gradle
https://github.com/domaframework/master/blob/master/build.gradle
手順
DataSource Bean を定義する必要はないのではないか?
IntelliJ IDEA で 1.0.x-delete-datasource-bean ブランチを作成します。
src/main/java/ksbysample/webapp/email/config の下の ApplicationConfig.java を リンク先の内容 に変更します。
動作確認します。Gradle projects View から bootRun タスクを実行して Tomcat を起動します。正常に起動して "Started Application in ..." のログが出力されることが確認できます。
ブラウザを起動し http://localhost:8080/mailsend へアクセスします。以下の画像の値を入力後、「送信」ボタンをクリックします。
エラーは発生せず、メールも送信されました。email, email_item どちらのテーブルにもデータが保存されていました。DataSource Bean の定義を削除しても問題ないようです。
Run View で Ctrl+F2 を押して Tomcat を停止します。
commit、GitHub へ Push、1.0.x-delete-datasource-bean -> 1.0.x へ Pull Request、1.0.x でマージ、1.0.x-delete-datasource-bean ブランチを削除、をします。
DomaBeanConfig クラスを DomaConfig クラスのインナークラスとして定義できるか?
IntelliJ IDEA で 1.0.x-change-innerclass-domabeanconfig ブランチを作成します。
src/main/java/ksbysample/webapp/email/config の下の DomaConfig.java を リンク先の内容 に変更します。
src/main/java/ksbysample/webapp/email/config の下の DomaBeanConfig.java を削除します。
動作確認します。Gradle projects View から bootRun タスクを実行して Tomcat を起動します。正常に起動して "Started Application in ..." のログが出力されることが確認できます。
ブラウザを起動し http://localhost:8080/mailsend へアクセスします。「DataSource Bean を定義する必要はないのではないか?」の画像のテストデータの値を入力後、「送信」ボタンをクリックします。
エラーは発生せず、メールも送信されました。email, email_item どちらのテーブルにもデータが保存されていました。DomaBeanConfig クラスを DomaConfig クラスのインナークラスで定義しても問題ないようです。
Run View で Ctrl+F2 を押して Tomcat を停止します。
commit、GitHub へ Push、1.0.x-change-innerclass-domabeanconfig -> 1.0.x へ Pull Request、1.0.x でマージ、1.0.x-change-innerclass-domabeanconfig ブランチを削除、をします。
MAIL001MailBuilder クラスを作り直す
IntelliJ IDEA で 1.0.x-remake-mail001mailbuilder ブランチを作成します。
src/main/java/ksbysample/webapp/email/web/mailsend の下の MAIL001MailBuilder を選択後、Shift+F6 を押して「Rename」ダイアログを表示した後、MAIL001MailHelper へリネームします。
src/main/java/ksbysample/webapp/email/web/mailsend の下の MAIL001MailHelper を選択後、F6 を押して「Move」ダイアログを表示した後、ksbysample.webapp.email.helper.mail へ移動します。
上のダイアログで「Refactor」ボタンを押すと確認ダイアログが表示されて「Yes」ボタンを押すと存在しない package を作成してくれます。
src/main/java/ksbysample/webapp/email/helper/mail の下の MAIL001MailHelper.java を リンク先の内容 に変更します。
src/main/java/ksbysample/webapp/email/web/mailsend の下の MailsendService.java を リンク先の内容 に変更します。
動作確認します。Gradle projects View から bootRun タスクを実行して Tomcat を起動します。
ブラウザを起動し http://localhost:8080/mailsend へアクセスします。「DataSource Bean を定義する必要はないのではないか?」の画像のテストデータの値を入力後、「送信」ボタンをクリックします。
エラーは発生せず、メールも送信されました。email, email_item どちらのテーブルにもデータが保存されていました。
Run View で Ctrl+F2 を押して Tomcat を停止します。
commit、GitHub へ Push、1.0.x-remake-mail001mailbuilder -> 1.0.x へ Pull Request、1.0.x でマージ、1.0.x-remake-mail001mailbuilder ブランチを削除、をします。
Doma-Gen で自動生成したファイルを自動で git add する
IntelliJ IDEA で 1.0.x-gitadd-domagenfile ブランチを作成します。
build.gradle を リンク先の内容 に変更します。
Gradle projects View の左上にある「Refresh all Gradle projects」アイコンをクリックして、変更した build.gradle の内容を反映します。
動作確認します。最初に src/main/java/ksbysample/webapp/email の下の dao の下に TestDao インターフェースを、entity の下に TestEntity クラスを手動で作成します。この時「Add File to Git」ダイアログが出たら「No」ボタンをクリックして追加しないようにします。
この時点でメインメニューから「VCS」-「Commit Changes...」を選択して「Commit Changes」ダイアログを表示しても TestDao, TestEntity は表示されません。「Cancel」ボタンをクリックしてダイアログを閉じます。
次に gen タスクを実行します。
再度メインメニューから「VCS」-「Commit Changes...」を選択して「Commit Changes」ダイアログを表示すると、今度は git add されているので表示されます。「Cancel」ボタンをクリックしてダイアログを閉じます。
作成した TestDao インターフェース、TestEntity クラスを削除します。
commit、GitHub へ Push、1.0.x-gitadd-domagenfile -> 1.0.x へ Pull Request、1.0.x でマージ、1.0.x-gitadd-domagenfile ブランチを削除、をします。
- commit 時に Code Analysis ダイアログが表示されますが、表示される Warning 「Unnecessary qualified reference」と「'open' in 'org.ajoberstar.grgit.Grgit' cannot be applied to
(['dir':java.io.File])
」の対処方法が分からなかったため、「Commit」ボタンをクリックして先に進めます。
- commit 時に Code Analysis ダイアログが表示されますが、表示される Warning 「Unnecessary qualified reference」と「'open' in 'org.ajoberstar.grgit.Grgit' cannot be applied to
次回は。。。
- メール送信画面で作成したモジュールのテストを書きます。
- メールの unit test 用のライブラリもあるようなので、使用してみる予定です。
ソースコード
ApplicationConfig.java
package ksbysample.webapp.email.config; import org.springframework.context.annotation.Configuration; @Configuration public class ApplicationConfig { }
- DataSource Bean の定義を削除します。
- ApplicationConfig.java は Bean 定義用としてそのまま残しておきます。
DomaConfig.java
package ksbysample.webapp.email.config; import org.seasar.doma.jdbc.Config; import org.seasar.doma.jdbc.dialect.Dialect; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy; import org.springframework.stereotype.Component; import javax.sql.DataSource; @Component public class DomaConfig implements Config { private DataSource dataSource; @Autowired private Dialect dialect; @Autowired public void setDataSource(DataSource dataSource) { this.dataSource = new TransactionAwareDataSourceProxy(dataSource); } @Override public DataSource getDataSource() { return this.dataSource; } @Override public Dialect getDialect() { return this.dialect; } @Configuration protected static class DomaBeanConfig { @Value("${doma.dialect}") private String domaDialect; @Bean public Dialect dialect() throws ClassNotFoundException, IllegalAccessException, InstantiationException { return (Dialect)Class.forName(domaDialect).newInstance(); } } }
protected static class DomaBeanConfig { ... }
を追加します。DomaBeanConfig クラスには @Configuration を付加します。
MAIL001MailHelper.java
package ksbysample.webapp.email.helper.mail; import ksbysample.webapp.email.config.Constant; import ksbysample.webapp.email.util.VelocityUtils; import ksbysample.webapp.email.web.mailsend.MailsendForm; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.mail.SimpleMailMessage; import org.springframework.stereotype.Component; import java.util.HashMap; import java.util.Map; import java.util.stream.Collectors; @Component public class MAIL001MailHelper { private final String templateLocation = "mail/MAIL001/MAIL001-body.vm"; @Autowired private VelocityUtils velocityUtils; public SimpleMailMessage createMessage(MailsendForm mailsendForm) { SimpleMailMessage mailMessage = new SimpleMailMessage(); mailMessage.setFrom(mailsendForm.getFromAddr()); mailMessage.setTo(mailsendForm.getToAddr()); mailMessage.setSubject(mailsendForm.getSubject()); mailMessage.setText(generateTextUsingVelocity(mailsendForm)); return mailMessage; } private String generateTextUsingVelocity(MailsendForm mailsendForm) { Constant constant = Constant.getInstance(); Map<String, Object> model = new HashMap<>(); model.put("name", mailsendForm.getName()); model.put("sex", constant.SEX_MAP.get(mailsendForm.getSex())); model.put("type", constant.TYPE_MAP.get(mailsendForm.getType())); String itemList = mailsendForm.getItem().stream() .map(constant.ITEM_MAP::get) .collect(Collectors.joining(", ")); model.put("item", itemList); model.put("naiyo", mailsendForm.getNaiyo()); return velocityUtils.merge(this.templateLocation, model); } }
- クラスに @Component アノテーションを付加します。
private String templateLocation;
→private final String templateLocation = "mail/MAIL001/MAIL001-body.vm";
へ変更します。private VelocityUtils velocityUtils;
を追加します。- build, setForm, setVelocityUtils, setTemplateLocation メソッドを削除します。
- メソッド名を create → createMessage へ変更します。
- createMessage メソッドの実装を上記の内容に変更します。
- generateTextUsingVelocity メソッドを追加し、メール本文の生成処理をこのメソッドに移動します。
MailsendService.java
package ksbysample.webapp.email.web.mailsend; import ksbysample.webapp.email.dao.EmailDao; import ksbysample.webapp.email.dao.EmailItemDao; import ksbysample.webapp.email.entity.Email; import ksbysample.webapp.email.entity.EmailItem; import ksbysample.webapp.email.helper.mail.MAIL001MailHelper; import ksbysample.webapp.email.service.EmailService; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.mail.SimpleMailMessage; import org.springframework.stereotype.Service; @Service public class MailsendService { @Autowired private EmailDao emailDao; @Autowired private EmailItemDao emailItemDao; @Autowired private MAIL001MailHelper mail001MailHelper; @Autowired private EmailService emailService; public void saveAndSendEmail(MailsendForm mailsendForm) { // 入力されたデータを email, email_item テーブルに保存する saveEmail(mailsendForm); // メールを送信する sendEmail(mailsendForm); } public void saveEmail(MailsendForm mailsendForm) { // email テーブルに保存する Email email = new Email(); BeanUtils.copyProperties(mailsendForm, email); emailDao.insert(email); // email_item テーブルに保存する EmailItem emailItem = new EmailItem(); for (String item : mailsendForm.getItem()) { emailItem.setEmailItemId(null); emailItem.setEmailId(email.getEmailId()); emailItem.setItem(item); emailItemDao.insert(emailItem); } } public void sendEmail(MailsendForm mailsendForm) { SimpleMailMessage mailMessage = mail001MailHelper.createMessage(mailsendForm); emailService.sendSimpleMail(mailMessage); } }
private VelocityUtils velocityUtils;
を削除します。private MAIL001MailHelper mail001MailHelper;
を追加します。- sendEmail メソッドの実装を上記の内容に変更します。
build.gradle
buildscript { repositories { jcenter() // for org.springframework:springloaded maven { url "http://repo.spring.io/repo/" } } dependencies { classpath("org.springframework.boot:spring-boot-gradle-plugin:1.2.3.RELEASE") classpath("org.springframework:springloaded:1.2.3.RELEASE") // for Grgit classpath("org.ajoberstar:grgit:1.1.0") } } apply plugin: 'java' apply plugin: 'spring-boot' apply plugin: 'idea' // for Doma 2 // JavaクラスとSQLファイルの出力先ディレクトリを同じにする processResources.destinationDir = compileJava.destinationDir // コンパイルより前にSQLファイルを出力先ディレクトリにコピーするために依存関係を逆転する compileJava.dependsOn processResources ext { git = org.ajoberstar.grgit.Grgit.open(file('.')) } jar { baseName = 'ksbysample-webapp-email' version = '0.0.1-SNAPSHOT' } idea { module { inheritOutputDirs = false outputDir = file("$buildDir/classes/main/") } } configurations { domaGenRuntime } repositories { jcenter() // for org.seasar.doma:doma maven { url "https://oss.sonatype.org/content/repositories/snapshots/" } } dependencies { def jdbcDriver = "org.postgresql:postgresql:9.4-1201-jdbc41" // spring-boot-gradle-plugin によりバージョン番号が自動で設定されるもの // Appendix E. Dependency versions ( http://docs.spring.io/spring-boot/docs/current/reference/html/appendix-dependency-versions.html ) 参照 compile("org.springframework.boot:spring-boot-starter-web") compile("org.springframework.boot:spring-boot-starter-thymeleaf") compile("org.springframework.boot:spring-boot-starter-data-jpa") compile("org.springframework.boot:spring-boot-starter-velocity") compile("org.springframework.boot:spring-boot-starter-mail") compile("org.codehaus.janino:janino") testCompile("org.springframework.boot:spring-boot-starter-test") testCompile("org.yaml:snakeyaml") // spring-boot-gradle-plugin によりバージョン番号が自動で設定されないもの compile("${jdbcDriver}") compile("org.seasar.doma:doma:2.2.0") compile("org.bgee.log4jdbc-log4j2:log4jdbc-log4j2-jdbc4.1:1.16") compile("org.apache.commons:commons-lang3:3.4") compile("org.projectlombok:lombok:1.16.2") testCompile("org.dbunit:dbunit:2.5.0") // for Doma-Gen domaGenRuntime("org.seasar.doma:doma-gen:2.2.0") domaGenRuntime("${jdbcDriver}") } bootRun { jvmArgs = ['-Dspring.profiles.active=develop'] } test { jvmArgs = ['-Dspring.profiles.active=unittest'] } // for Doma-Gen task gen << { def rootPackageName = 'ksbysample.webapp.email' ant.taskdef(resource: 'domagentask.properties', classpath: configurations.domaGenRuntime.asPath) ant.gen(url: 'jdbc:postgresql://localhost/ksbyemail', user: 'ksbyemail_user', password: 'xxxxxxxx') { entityConfig(packageName: "${rootPackageName}.entity", useListener: false) daoConfig(packageName: "${rootPackageName}.dao") sqlConfig() // 自動生成したファイルを git add する def grgit = org.ajoberstar.grgit.Grgit.open(dir: project.projectDir) grgit.add(patterns: ['.']) } }
- buildscript の dependencies の中に
classpath("org.ajoberstar:grgit:1.1.0")
を追加します。 - task gen の最後に grgit で add する処理を追加します。
履歴
2015/05/13
初版発行。