Spring Boot + npm + Geb で入力フォームを作ってテストする ( その2 )( Project の作成 )
概要
記事一覧はこちらです。
Spring Boot + npm + Geb で入力フォームを作ってテストする ( その1 )( 概要 ) の続きです。
- 今回の手順で確認できるのは以下の内容です。
- Project の作成
参照したサイト・書籍
- spring-projects/spring-session - Add @EnableSpringHttpSession
https://github.com/spring-projects/spring-session/issues/231
目次
- GitHub 上で ksbysample-boot-miscellaneous レポジトリを新規作成してクローンする
- IntelliJ IDEA の起動し、Project を新規作成する
- build.gradle を変更する
- Gradle の設定を変更する
- Project language level を SDK default に変更する
- JUnit によるテスト実行時の spring.profiles.active を設定する
- src/main/resources の下に static, templates ディレクトリを作成する
- ksbysample-webapp-lending からファイルをコピーする(その1)
- 続く。。。
手順
GitHub 上で ksbysample-boot-miscellaneous レポジトリを新規作成してクローンする
GitHub 上で ksbysample-boot-miscellaneous レポジトリを新規作成します。
SourceTree で作成した ksbysample-boot-miscellaneous レポジトリを C:\project-springboot\ksbysample-boot-miscellaneous へクローンします。
C:\project-springboot\ksbysample-boot-miscellaneous の下に .gitignore を新規作成し、リンク先の内容 に変更します。この .gitignore は Spring Integration のサンプルを作成している ksbysample-boot-integration レポジトリ のものをコピーしたものです。
develop ブランチ、feature/1-issue ブランチを作成します。
IntelliJ IDEA の起動し、Project を新規作成する
IntelliJ IDEA を起動します。他の Project を開いている場合には、メイン画面のメニューから「File」->「Close Project」を選択して Project をクローズします。
「Welcome to IntelliJ IDEA」画面が表示されます。画面中央の「Create New Project」をクリックします。
「New Project」画面が表示されます。画面左側のリストから「Gradle」を選択し、画面右側は以下の画像の状態にして「Next」ボタンをクリックします。
GroupId、ArtifactId、Version を入力する画面が表示されます。以下の点を変更した後、「Next」ボタンをクリックします。
- 「GroupdId」に “project” を入力します。
- 「ArtifactId」に “boot-npm-geb-sample” を入力します。
Gradle の設定をする画面が表示されます。何も変更せず「Next」ボタンをクリックします。
Project name、Project location を入力する画面が表示されます。以下の点を変更した後、「Finish」ボタンをクリックします。
- 「Project location」に “C:\project-springboot\ksbysample-boot-miscellaneous\boot-npm-geb-sample” を入力します。
「Directory Does Not Exist」ダイアログが表示されますので「OK」ボタンをクリックします。
IntelliJ IDEA のメイン画面が表示されて Project Tool Window に以下のディレクトリ構造が表示されます。
※src/main/java や src/test/java に以下の画像のように色が付いていることを確認します。
build.gradle を変更する
build.gradle を リンク先の内容 に変更します。
コマンドプロンプトを起動して gradlew wrapper コマンドを実行し、gradle を 3.5 へバージョンアップします。
Gradle Tool Window の左上にある「Refresh all Gradle projects」ボタンをクリックして更新します。
Gradle の設定を変更する
メイン画面のメニューから「File」->「Settings…」を選択して「Settings」ダイアログを表示します。
画面左上の検索フィールドに “Gradle” と入力して画面左側のツリーから「Build, Execution, Deployment」-「Build Tools」-「Gradle」を選択した後、以下の点を変更します。
- 「Create directories for empty content roots automatically」をチェックします。
- 画面右側の「Gradle JVM」で「Use Project JDK」を選択します。
「OK」ボタンをクリックして「Settings」ダイアログを閉じます。
再度 Gradle Tool Window の左上にある「Refresh all Gradle projects」ボタンをクリックして更新します。src/man/groovy, src/test/groovy ディレクトリが自動作成されます。
Project language level を SDK default に変更する
メイン画面のメニューから「File」->「Project Structure…」を選択して「Project Structure」ダイアログを表示します。
画面左側のツリーから「Project Settings」-「Project」を選択し、画面右側で「Project language level」の設定を「SDK default」に変更します。
「OK」ボタンをクリックして「Project Structure」ダイアログを閉じます。
JUnit によるテスト実行時の spring.profiles.active を設定する
メイン画面のメニューから「Run」->「Edit Configurations…」を選択します。
「Run/Debug Configuraitons」ダイアログが表示されます。左側のツリーで「Defaults」-「JUnit」を選択した後、右側の画面の「VM options」の末尾に
-Dspring.profiles.active=unittest
を追加します。「OK」ボタンをクリックして「Run/Debug Configuraitons」ダイアログを閉じます。
src/main/resources の下に static, templates ディレクトリを作成する
- Project Tool Window で src/main/resources の下に static, templates ディレクトリを作成します。
ksbysample-webapp-lending からファイルをコピーする
以下の画像の階層のパッケージを作成します。
ksbysample-webapp-lending から以下のファイルをコピーします。
※リンクのあるファイルはリンク先の内容に変更します。
■src/main/java
- /ksbysample/webapp/lending/Application.java
→ /ksbysample/webapp/bootnpmgeb/Application.java - /ksbysample/webapp/lending/aspect/logging/ControllerAndEventNameLogger.java
→ /ksbysample/webapp/bootnpmgeb/aspect/logging/ControllerAndEventNameLogger.java - /ksbysample/webapp/lending/aspect/logging/LoggingControllerName.java
→ /ksbysample/webapp/bootnpmgeb/aspect/logging/LoggingControllerName.java - /ksbysample/webapp/lending/aspect/logging/LoggingEventName.java
→ /ksbysample/webapp/bootnpmgeb/aspect/logging/LoggingEventName.java - /ksbysample/webapp/lending/aspect/logging/MethodLogger.java
→ /ksbysample/webapp/bootnpmgeb/aspect/logging/MethodLogger.java - /ksbysample/webapp/lending/aspect/logging/RequestAndResponseLogger.java
→ /ksbysample/webapp/bootnpmgeb/aspect/logging/RequestAndResponseLogger.java - /ksbysample/webapp/lending/config/ApplicationConfig.java
→ /ksbysample/webapp/bootnpmgeb/config/ApplicationConfig.java - /ksbysample/webapp/lending/config/DomaConfig.java
→ /ksbysample/webapp/bootnpmgeb/config/DomaConfig.java - /ksbysample/webapp/lending/config/WebMvcConfig.java
→ /ksbysample/webapp/bootnpmgeb/config/WebMvcConfig.java - /ksbysample/webapp/lending/config/WebSecurityConfig.java
→ /ksbysample/webapp/bootnpmgeb/config/WebSecurityConfig.java - /ksbysample/webapp/lending/helper/freemarker/FreeMarkerHelper.java
→ /ksbysample/webapp/bootnpmgeb/helper/freemarker/FreeMarkerHelper.java - /ksbysample/webapp/lending/helper/freemarker/EmailHelper.java
→ /ksbysample/webapp/bootnpmgeb/helper/freemarker/EmailHelper.java - /ksbysample/webapp/lending/util/doma/ComponentAndAutowiredDomaConfig.java
→ /ksbysample/webapp/bootnpmgeb/util/doma/ComponentAndAutowiredDomaConfig.java - /ksbysample/webapp/lending/util/doma/SelectOptionsUtils.java
→ /ksbysample/webapp/bootnpmgeb/util/doma/SelectOptionsUtils.java
- /ksbysample/webapp/lending/Application.java
続く。。。
長くなったので2回に分けます。
ソースコード
.gitignore
# built application files *.apk *.ap_ # files for the dex VM *.dex # Java class files *.class # generated files **/bin/ **/gen/ # Local configuration file (sdk path, etc) local.properties # Eclipse project files .classpath .project # Proguard folder generated by Eclipse **/proguard/ # Intellij project files *.iml *.ipr *.iws **/.idea/ **/out/ #Gradle .gradletasknamecache **/.gradle/ **/build/ **/bin/
build.gradle
group 'ksbysample' version '1.5.4-RELEASE' buildscript { ext { springBootVersion = '1.5.4.RELEASE' } repositories { mavenCentral() maven { url "https://plugins.gradle.org/m2/" } } dependencies { classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}") // for Error Prone ( http://errorprone.info/ ) classpath("net.ltgt.gradle:gradle-errorprone-plugin:0.0.10") } } apply plugin: 'java' apply plugin: 'eclipse' apply plugin: 'idea' apply plugin: 'org.springframework.boot' apply plugin: 'groovy' apply plugin: 'net.ltgt.errorprone' apply plugin: 'checkstyle' apply plugin: 'findbugs' apply plugin: 'pmd' sourceCompatibility = 1.8 targetCompatibility = 1.8 task wrapper(type: Wrapper) { gradleVersion = '3.5' } [compileJava, compileTestGroovy, compileTestJava]*.options*.compilerArgs = ['-Xlint:all,-options,-processing,-path'] compileJava.options.compilerArgs += ['-Xep:RemoveUnusedImports:WARN'] // for Doma 2 // JavaクラスとSQLファイルの出力先ディレクトリを同じにする processResources.destinationDir = compileJava.destinationDir // コンパイルより前にSQLファイルを出力先ディレクトリにコピーするために依存関係を逆転する compileJava.dependsOn processResources idea { module { inheritOutputDirs = false outputDir = file("$buildDir/classes/main/") } } configurations { // for Doma 2 domaGenRuntime } checkstyle { configFile = file("${rootProject.projectDir}/config/checkstyle/google_checks.xml") toolVersion = '8.0' sourceSets = [project.sourceSets.main] } findbugs { toolVersion = '3.0.1' sourceSets = [project.sourceSets.main] ignoreFailures = true effort = "max" excludeFilter = file("${rootProject.projectDir}/config/findbugs/findbugs-exclude.xml") } tasks.withType(FindBugs) { // Gradle 3.3以降 + FindBugs Gradle Plugin を組み合わせると、"The following errors occurred during analysis:" // の後に "Cannot open codebase filesystem:..." というメッセージが大量に出力されるので、以下の doFirst { ... } // のコードを入れることで出力されないようにする doFirst { def fc = classes if (fc == null) { return } fc.exclude '**/*.properties' fc.exclude '**/*.xml' fc.exclude '**/META-INF/**' fc.exclude '**/static/**' fc.exclude '**/templates/**' classes = files(fc.files) } reports { xml.enabled = false html.enabled = true } } pmd { toolVersion = "5.8.1" sourceSets = [project.sourceSets.main] ignoreFailures = true consoleOutput = true ruleSetFiles = rootProject.files("/config/pmd/pmd-project-rulesets.xml") ruleSets = [] } repositories { mavenCentral() } dependencyManagement { imports { // BOM は https://repo.spring.io/release/io/spring/platform/platform-bom/Brussels-SR3/ // の下を見ること mavenBom("io.spring.platform:platform-bom:Brussels-SR3") { bomProperty 'guava.version', '22.0' bomProperty 'thymeleaf.version', '3.0.6.RELEASE' bomProperty 'thymeleaf-extras-springsecurity4.version', '3.0.2.RELEASE' bomProperty 'thymeleaf-layout-dialect.version', '2.2.2' bomProperty 'thymeleaf-extras-data-attribute.version', '2.0.1' bomProperty 'thymeleaf-extras-java8time.version', '3.0.0.RELEASE' } } } bootRepackage { mainClass = 'ksbysample.webapp.lending.Application' } dependencies { def spockVersion = "1.1-groovy-2.4" def domaVersion = "2.16.1" def lombokVersion = "1.16.18" def errorproneVersion = "2.0.15" def powermockVersion = "1.7.0" // dependency-management-plugin によりバージョン番号が自動で設定されるもの // Appendix A. Dependency versions ( http://docs.spring.io/platform/docs/current/reference/htmlsingle/#appendix-dependency-versions ) 参照 compile("org.springframework.boot:spring-boot-starter-web") compile("org.springframework.boot:spring-boot-starter-thymeleaf") { exclude group: "org.codehaus.groovy", module: "groovy" } compile("org.springframework.boot:spring-boot-starter-data-jpa") compile("org.springframework.boot:spring-boot-starter-freemarker") compile("org.springframework.boot:spring-boot-starter-mail") compile("org.springframework.boot:spring-boot-starter-security") compile("org.springframework.boot:spring-boot-devtools") compile("org.springframework.session:spring-session") compile("com.google.guava:guava") compile("org.apache.commons:commons-lang3") compile("org.codehaus.janino:janino") compile("com.h2database:h2") testCompile("org.springframework.boot:spring-boot-starter-test") testCompile("org.springframework.security:spring-security-test") testCompile("org.yaml:snakeyaml") testCompile("org.mockito:mockito-core") // dependency-management-plugin によりバージョン番号が自動で設定されないもの、あるいは最新バージョンを指定したいもの compile("com.integralblue:log4jdbc-spring-boot-starter:1.0.1") testCompile("org.dbunit:dbunit:2.5.3") testCompile("com.icegreen:greenmail:1.5.5") testCompile("org.assertj:assertj-core:3.8.0") testCompile("org.spockframework:spock-core:${spockVersion}") testCompile("org.spockframework:spock-spring:${spockVersion}") testCompile("com.google.code.findbugs:jsr305:3.0.2") // for lombok compileOnly("org.projectlombok:lombok:${lombokVersion}") testCompileOnly("org.projectlombok:lombok:${lombokVersion}") // for Doma compile("org.seasar.doma:doma:${domaVersion}") domaGenRuntime("org.seasar.doma:doma-gen:${domaVersion}") // for Error Prone ( http://errorprone.info/ ) errorprone("com.google.errorprone:error_prone_core:${errorproneVersion}") compileOnly("com.google.errorprone:error_prone_annotations:${errorproneVersion}") // PowerMock testCompile("org.powermock:powermock-module-junit4:${powermockVersion}") testCompile("org.powermock:powermock-api-mockito:${powermockVersion}") } bootRun { jvmArgs = ['-Dspring.profiles.active=develop'] } test { jvmArgs = ['-Dspring.profiles.active=unittest'] } // for Doma-Gen task domaGen { doLast { // まず変更が必要なもの def rootPackageName = 'ksbysample.webapp.bootnpmgeb' def daoPackagePath = 'src/main/java/ksbysample/webapp/bootnpmgeb/dao' def dbUrl = 'jdbc:h2:mem:bootnpmgebdb' def dbUser = 'sa' def dbPassword = '' def tableNamePattern = '.*' // おそらく変更不要なもの def importOfComponentAndAutowiredDomaConfig = "${rootPackageName}.util.doma.ComponentAndAutowiredDomaConfig" def workDirPath = 'work' def workDaoDirPath = "${workDirPath}/dao" // 作業用ディレクトリを削除する clearDir("${workDirPath}") // 現在の Dao インターフェースのバックアップを取得する copy() { from "${daoPackagePath}" into "${workDaoDirPath}/org" } // Dao インターフェース、Entity クラスを生成する ant.taskdef(resource: 'domagentask.properties', classpath: configurations.domaGenRuntime.asPath) ant.gen(url: "${dbUrl}", user: "${dbUser}", password: "${dbPassword}", tableNamePattern: "${tableNamePattern}") { entityConfig(packageName: "${rootPackageName}.entity", useListener: false) daoConfig(packageName: "${rootPackageName}.dao") sqlConfig() } // 生成された Dao インターフェースを作業用ディレクトリにコピーし、 // @ComponentAndAutowiredDomaConfig アノテーションを付加する copy() { from "${daoPackagePath}" into "${workDaoDirPath}/replace" filter { line -> line.replaceAll('import org.seasar.doma.Dao;', "import ${importOfComponentAndAutowiredDomaConfig};\nimport org.seasar.doma.Dao;") .replaceAll('@Dao', '@Dao\n@ComponentAndAutowiredDomaConfig') } } // @ComponentAndAutowiredDomaConfig アノテーションを付加した Dao インターフェースを // dao パッケージへ戻す copy() { from "${workDaoDirPath}/replace" into "${daoPackagePath}" } // 元々 dao パッケージ内にあったファイルを元に戻す copy() { from "${workDaoDirPath}/org" into "${daoPackagePath}" } // 作業用ディレクトリを削除する clearDir("${workDirPath}") } } /* ----------------------------------------------------------------------------- * メソッド定義部 ---------------------------------------------------------------------------- */ void clearDir(String dirPath) { delete dirPath }
Application.java
package ksbysample.webapp.bootnpmgeb; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration; import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.ImportResource; import org.springframework.session.config.annotation.web.http.EnableSpringHttpSession; import java.text.MessageFormat; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.Set; /** * ??? */ @ImportResource("classpath:applicationContext-${spring.profiles.active}.xml") @SpringBootApplication(exclude = {JpaRepositoriesAutoConfiguration.class, HibernateJpaAutoConfiguration.class}) @ComponentScan("ksbysample") @EnableSpringHttpSession public class Application { ..........
@EnableRedisHttpSession
→@EnableSpringHttpSession
に変更します。@EnableGlobalMethodSecurity(prePostEnabled = true)
を削除します。
ControllerAndEventNameLogger.java
@Around(value = "execution(* ksbysample.webapp.bootnpmgeb.web..*.*(..)) && @annotation(loggingEventName)" , argNames = "pjp, loggingEventName") public Object logginControllerAndEventName(ProceedingJoinPoint pjp, LoggingEventName loggingEventName) throws Throwable { ..........
execution(* ksbysample.webapp.lending.web..*.*(..))
→execution(* ksbysample.webapp.bootnpmgeb.web..*.*(..))
に変更します。
MethodLogger.java
@SuppressWarnings({"PMD.UnusedPrivateMethod"}) @Pointcut("execution(* ksbysample.webapp.bootnpmgeb.web..*.*(..))" + "&& @within(org.springframework.stereotype.Controller)") private void pointcutControllerMethod() { } @SuppressWarnings({"PMD.UnusedPrivateMethod"}) @Pointcut("execution(* ksbysample.webapp.bootnpmgeb.service..*.*(..))" + "&& @within(org.springframework.stereotype.Service)") private void pointcutServiceMethod() { }
execution(* ksbysample.webapp.lending.web..*.*(..))
→execution(* ksbysample.webapp.bootnpmgeb.web..*.*(..))
に変更します。execution(* ksbysample.webapp.lending.service..*.*(..))
→execution(* ksbysample.webapp.bootnpmgeb.service..*.*(..))
に変更します。
RequestAndResponseLogger.java
private static final String POINTCUT_ALL_CLASS_AND_METHOD_UNDER_APPLICATION_PACKAGE = "execution(* ksbysample.webapp.bootnpmgeb..*.*(..))";
execution(* ksbysample.webapp.lending..*.*(..))
→execution(* ksbysample.webapp.bootnpmgeb..*.*(..))
に変更します。
ApplicationConfig.java
package ksbysample.webapp.bootnpmgeb.config; import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.MessageSource; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.validation.Validator; import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean; import javax.sql.DataSource; /** * ??? */ @Configuration public class ApplicationConfig { private final MessageSource messageSource; /** * @param messageSource {@link MessageSource} bean */ public ApplicationConfig(MessageSource messageSource) { this.messageSource = messageSource; } /** * Controller クラスで直接 {@link Validator} を呼び出すために Bean として定義している * また Hibernate Validator のメッセージを ValidationMessages.properties ではなく * messages.properties に記述できるようにするためにも使用している * * @return new {@link LocalValidatorFactoryBean} */ @Bean public Validator mvcValidator() { LocalValidatorFactoryBean localValidatorFactoryBean = new LocalValidatorFactoryBean(); localValidatorFactoryBean.setValidationMessageSource(this.messageSource); return localValidatorFactoryBean; } /** * @return Tomcat JDBC Connection Pool の DataSource オブジェクト */ @Bean @ConfigurationProperties("spring.datasource.tomcat") public DataSource dataSource() { return DataSourceBuilder.create() .type(org.apache.tomcat.jdbc.pool.DataSource.class) .build(); } }
- 以下の Bean のみ残します。
- mvcValidator Bean
- dataSource Bean
WebSecurityConfig.java
package ksbysample.webapp.bootnpmgeb.config; import org.springframework.boot.autoconfigure.security.SecurityProperties; import org.springframework.context.annotation.Configuration; import org.springframework.core.annotation.Order; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; /** * ??? */ @Configuration @Order(SecurityProperties.ACCESS_OVERRIDE_ORDER) public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() // 認証の対象外にしたいURLがある場合には、以下のような記述を追加します // 複数URLがある場合はantMatchersメソッドにカンマ区切りで対象URLを複数列挙します // .antMatchers("/country/**").permitAll() // // この Web アプリケーションでは Spring Security を CSRF対策で使用したいだけなので、 // 全ての URL を認証の対象外にする .antMatchers("/**").permitAll() .anyRequest().authenticated(); } }
履歴
2017/07/22
初版発行。