Get Started With JHipster6

目的

  • 未公開記事の発掘
  • JHipsterの現行バージョンはv7.9.3です Release Notes
  • 少なくとも2年以上前に書いていたらしい

目的

JHipster is 何

  • Angular と Bootstrap と Spring Boot をいい感じに統合する Web アプリケーションフレームワークです
    • 2019-05-02 に公開した JHipster 6 では Java 11 と Spring Boot 2.1.x に対応しました
      • 最新バージョンは 6.10.1 (2020-07-05)
    • 今は React や Quarkus や Micronaut にも対応しつつある
  • プロジェクトジェネレーター、ソースコードジェネレーターとして使います
    • Angular な部分は yeoman で生成してるみたい
    • Spring Boot な部分はどうしてるんだろう
  • 公式ページ
  • GitHub リポジトリ

JHipster のインストール

  • Java 11 をインストールする
    • SDKMAN! - sdk intall java 11.0.8.hs-adpt
    • Scoop - scoop install adoptopenjdk-lts-hotspot
  • Git をインストールする
    • Scoop - scoop install git
  • Node.js(LTS) をインストールする
    • Scoop - scoop install nodejs-lts
  • JHipster をインストールする
    • NPM - npm install -g generator-jhipster

プロジェクトの作成

jhipster コマンドは今のディレクトリにソースコードを生成します。

プロジェクトのディレクトリを作成、移動してから jhipster コマンドを実行します。対話的にいろいろと入力します。

質問 回答
type of application Monolithic application
WebFlux ? No
base name jhipsterblog
package name org.bitbucket.yujiorama.jhipsterblog
type of authentication JWT authentication
type of database SQL
production database PostgreSQL
development database H2
Spring cache Ehcache
Hibernate 2nd level cache Yes
building the backend Maven
Client framework Angular
Bootswatch theme Default JHipster
internationalization support Yes
native language Japanese
additional language English
testing framework Protractor
other generators No
MINGW64 ~/.go/src/bitbucket.org/yujiorama/jhipster-blog  (master +)
$ jhipster

INFO! Congratulations, JHipster execution is complete!
MINGW64 ~/.go/src/bitbucket.org/yujiorama/jhipster-blog  (master +)
$

もろもろ完了したらすでに git add した状態になっているので最初のコミットを作成します。

git commit -m init

環境変数 JAVA_HOMEJava 11 を指定しているのを確認します。

$ echo $JAVA_HOME
C:/Users/user/scoop/apps/adoptopenjdk-lts-hotspot/current

Java 11 に対応するため pom.xml を編集します。

pom.xml

@@ -21,8 +21,8 @@

     <properties>
         <!-- Build properties -->
         <maven.version>3.3.9</maven.version>
-        <java.version>1.8</java.version>
+        <java.version>11</java.version>
         <node.version>v12.16.1</node.version>
         <npm.version>6.14.5</npm.version>
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

@@ -418,8 +418,7 @@
                     <artifactId>maven-compiler-plugin</artifactId>
                     <version>${maven-compiler-plugin.version}</version>
                     <configuration>
-                        <source>${java.version}</source>
-                        <target>${java.version}</target>
+                        <release>${java.version}</release>
                         <annotationProcessorPaths>
                             <path>
                                 <groupId>org.springframework.boot</groupId>

依存ライブラリを最新化するため pom.xml を編集します。

./mvnw versions:update-properties

pom.xml

@@ -43,7 +43,7 @@
         <jhipster-dependencies.version>3.9.0</jhipster-dependencies.version>
         <!-- The spring-boot version should match the one managed by
         https://mvnrepository.com/artifact/io.github.jhipster/jhipster-dependencies/${jhipster-dependencies.version} -->
-        <spring-boot.version>2.2.7.RELEASE</spring-boot.version>
+        <spring-boot.version>2.3.3.RELEASE</spring-boot.version>
         <!-- The hibernate version should match the one managed by
         https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-dependencies/${spring-boot.version} -->
         <hibernate.version>5.4.15.Final</hibernate.version>
@@ -52,8 +52,8 @@
         <javassist.version>3.24.0-GA</javassist.version>
         <!-- The liquibase version should match the one managed by
         https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-dependencies/${spring-boot.version} -->
-        <liquibase.version>3.9.0</liquibase.version>
-        <liquibase-hibernate5.version>3.8</liquibase-hibernate5.version>
+        <liquibase.version>4.0.0</liquibase.version>
+        <liquibase-hibernate5.version>4.0.0</liquibase-hibernate5.version>
         <h2.version>1.4.200</h2.version>
         <validation-api.version>2.0.1.Final</validation-api.version>
         <jaxb-runtime.version>2.3.3</jaxb-runtime.version>
@@ -65,18 +65,18 @@
         <maven-javadoc-plugin.version>3.2.0</maven-javadoc-plugin.version>
         <maven-eclipse-plugin.version>2.10</maven-eclipse-plugin.version>
         <maven-enforcer-plugin.version>3.0.0-M3</maven-enforcer-plugin.version>
-        <maven-failsafe-plugin.version>3.0.0-M4</maven-failsafe-plugin.version>
+        <maven-failsafe-plugin.version>3.0.0-M5</maven-failsafe-plugin.version>
         <maven-idea-plugin.version>2.2.1</maven-idea-plugin.version>
-        <maven-resources-plugin.version>3.1.0</maven-resources-plugin.version>
-        <maven-surefire-plugin.version>3.0.0-M4</maven-surefire-plugin.version>
-        <maven-war-plugin.version>3.2.3</maven-war-plugin.version>
+        <maven-resources-plugin.version>3.2.0</maven-resources-plugin.version>
+        <maven-surefire-plugin.version>3.0.0-M5</maven-surefire-plugin.version>
+        <maven-war-plugin.version>3.3.1</maven-war-plugin.version>
         <maven-checkstyle.version>3.1.1</maven-checkstyle.version>
-        <checkstyle.version>8.32</checkstyle.version>
-        <spring-nohttp-checkstyle.version>0.0.4.RELEASE</spring-nohttp-checkstyle.version>
+        <checkstyle.version>8.35</checkstyle.version>
+        <spring-nohttp-checkstyle.version>0.0.5.RELEASE</spring-nohttp-checkstyle.version>
         <frontend-maven-plugin.version>1.10.0</frontend-maven-plugin.version>
-        <git-commit-id-plugin.version>4.0.0</git-commit-id-plugin.version>
+        <git-commit-id-plugin.version>4.0.2</git-commit-id-plugin.version>
         <jacoco-maven-plugin.version>0.8.5</jacoco-maven-plugin.version>
-        <jib-maven-plugin.version>2.4.0</jib-maven-plugin.version>
+        <jib-maven-plugin.version>2.5.2</jib-maven-plugin.version>
         <lifecycle-mapping.version>1.0.0</lifecycle-mapping.version>
         <properties-maven-plugin.version>1.0.0</properties-maven-plugin.version>
         <sonar-maven-plugin.version>3.7.0.1746</sonar-maven-plugin.version>

NoHttpCheck モジュールのプロパティ名を修正するため checkstyle.xml を編集します。

checkstyle.xml

@@ -9,7 +9,7 @@
     <property name="fileExtensions" value=""/>
     <!-- For detailed checkstyle configuration, see https://github.com/spring-io/nohttp/tree/master/nohttp-checkstyle -->
     <module name="io.spring.nohttp.checkstyle.check.NoHttpCheck">
-        <property name="whitelist" value="http://maven.apache.org/POM/4.0.0&#10;
+        <property name="allowlist" value="http://maven.apache.org/POM/4.0.0&#10;
             http://www.w3.org/2001/XMLSchema-instance&#10;http://maven.apache.org/maven-v4_0_0.xsd"/>
     </module>
     <!-- Allow suppression with comments

テストが成功するのを確認します。

./mvnw verify

アプリを起動します。

./mvnw

別のプロンプトで Protractor による e2e テストが成功するのを確認します。

npm run e2e

ブラウザで http://localhost:8080 にアクセスしていろいろ確認します。

  • ユーザー名 admin パスワード admin でログインできる
  • 管理メニューからいろいろ見れる
    • ユーザー管理ページ http://localhost:8080/admin/user-management
    • メトリクス監視ページ http://localhost:8080/admin/metrics
      • JVM メトリクス(ヒープ、GC、スレッド、CPU)
      • アプリケーションメトリクス(HTTP リクエスト統計、エンドポイント統計、キャッシュ統計、データベース統計)
    • ヘルスチェック http://localhost:8080/admin/health
      • データベース
      • ディスク
      • アプリケーション
    • 設定値一覧 http://localhost:8080/admin/configuration
    • 監査ログ http://localhost:8080/admin/audits
      • ユーザー認証の成否、日時など
    • ログレベル設定 http://localhost:8080/admin/logs
    • Swagger Editor http://localhost:8080/admin/docs
    • H2 Database Web コンソール http://localhost:8080/h2-console/

エンティティの生成

エンティティを追加するために必要なリソース

JHipster はこれらのリソースを自動生成します。 エンティティに関連があるときは外部キー制約なども生成します。

エンティティを自動生成する方法

  • サブジェネレーター
    • CLI ツール
    • 対話的に必要な情報を入力します
  • JDL-Studio
    • Web アプリ
    • JHipster ドメイン言語(JDL)で ER 図を見ながら必要な情報を記述します
    • ファイルに保存しておきます blog.jdl

エンティティの生成

import-jdl サブコマンドで JDL ファイルからエンティティを生成します。

jhipster import-jdl blog.jdl

ローカル PC でアプリを実行します。 * src/main/resources/config/application-dev.yamlliquibase.contextfaker が追加されているため、ダミーデータが生成されています * ダミーデータを生成しない場合は faker の記述を削除します * 一度生成してしまっている場合は H2 データベースファイルを初期化するため ./mvnw clean を実行します

./mvnw

ブログの作成と記事の作成

ブラウザでアクセスしてデータを登録します。

  • admin のブログを作成します
  • 作成したブログに記事を作成します
  • user のブログを作成します
  • 作成したブログに記事を作成します

ビジネスロジックの追加

  • 目的
    • admin としてログインした状態でブログ一覧ページ http://localhost:8080/blog にアクセスすると、user のブログも見えてしまう状態です。
    • ログインしているユーザーのブログだけが表示されるように、ビジネスロジックを改修します。

プロジェクトのインポートとビルドエラーの解消

プロジェクトを IntelliJ IDEA にインポートします。

次の部分がビルドエラーになるはずなので、アノテーションを追加して解消します。

IntelliJ IDEA の Spring ビルダーが解決できないだけで正常です

src/main/java/org/bitbucket/yujiorama/jhpister_blog/config/LiquibaseConfiguration.java

@@ -35,6 +35,7 @@ public class CacheConfiguration {
                 .build());
     }

+    @SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
     @Bean
     public HibernatePropertiesCustomizer hibernatePropertiesCustomizer(javax.cache.CacheManager cacheManager) {
         return hibernateProperties -> hibernateProperties.put(ConfigSettings.CACHE_MANAGER, cacheManager);

src/main/java/org/bitbucket/yujiorama/jhpister_blog/config/DatabaseConfiguration.java

@@ -35,6 +35,7 @@ public class DatabaseConfiguration {
      * @return the H2 database TCP server.
      * @throws SQLException if the server failed to start.
      */
+    @SuppressWarnings("ContextJavaBeanUnresolvedMethodsInspection")
     @Bean(initMethod = "start", destroyMethod = "stop")
     @Profile(JHipsterConstants.SPRING_PROFILE_DEVELOPMENT)
     public Object h2TCPServer() throws SQLException {

src/main/java/org/bitbucket/yujiorama/jhpister_blog/config/CacheConfiguration.java

@@ -29,6 +29,7 @@ public class LiquibaseConfiguration {
         this.env = env;
     }

+    @SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
     @Bean
     public SpringLiquibase liquibase(@Qualifier("taskExecutor") Executor executor,
             @LiquibaseDataSource ObjectProvider<DataSource> liquibaseDataSource, LiquibaseProperties liquibaseProperties,q

ブログ一覧ページの改修

BlogResource を改修します。

src/main/java/org/bitbucket/yujiorama/jhpister_blog/web/rest/BlogResource.java

@@ -87,8 +87,8 @@ public class BlogResource {
      */
     @GetMapping("/blogs")
     public List<Blog> getAllBlogs() {
-        log.debug("REST request to get all Blogs");
-        return blogRepository.findAll();
+        log.debug("REST request to get all Blogs posted by current user");
+        return blogRepository.findByUserIsCurrentUser();
     }

     /**

アプリを ./mvnw で実行している場合はソースコードを保存すると Spring Dev Tools の機能で自動的に再起動します。

http://localhost:8080/blog にアクセスすると、ログインしたユーザーのブログだけが表示されるようになります。

記事一覧ページの改修

同じように EntryResource も改修します。

src/main/java/org/bitbucket/yujiorama/jhpister_blog/web/rest/EntryResource.java

@@ -96,12 +97,7 @@ public class EntryResource {
     @GetMapping("/entries")
     public ResponseEntity<List<Entry>> getAllEntries(Pageable pageable, @RequestParam(required = false, defaultValue = "false") boolean eagerload) {
         log.debug("REST request to get a page of Entries");
-        Page<Entry> page;
-        if (eagerload) {
-            page = entryRepository.findAllWithEagerRelationships(pageable);
-        } else {
-            page = entryRepository.findAll(pageable);
-        }
+        Page<Entry> page = entryRepository.findByBlogUserLoginOrderByDateDesc(SecurityUtils.getCurrentUserLogin().orElse(null), pageable);
         HttpHeaders headers = PaginationUtil.generatePaginationHttpHeaders(ServletUriComponentsBuilder.fromCurrentRequest(), page);
         return ResponseEntity.ok().headers(headers).body(page.getContent());
     }

src/main/java/org/bitbucket/yujiorama/jhpister_blog/repository/EntryRepository.java

@@ -26,4 +26,6 @@ public interface EntryRepository extends JpaRepository<Entry, Long> {

     @Query("select entry from Entry entry left join fetch entry.tags where entry.id =:id")
     Optional<Entry> findOneWithEagerRelationships(@Param("id") Long id);
+
+    Page<Entry> findByBlogUserLoginOrderByDateDesc(String currentUserLogin, Pageable pageable);
 }

アプリを ./mvnw で実行している場合はソースコードを保存すると Spring Dev Tools の機能で自動的に再起動します。

http://localhost:8080/entry にアクセスすると、ログインしたユーザーの投稿だけが表示されるようになります。

UI 要素の改修

  • 目的
    • ブログなのにコンテンツをただのテキストとして描画してる
    • いい感じに描画する仕組みを追加します。

別のプロンプトで webpackdev サーバーを実行すると、Browsersync がブラウザを操作して http://localhost:9000 へアクセスします。

npm start

html をエスケープしないように改修

記事一覧ページ内容 の html をエスケープしないように改修します。Browsersync がブラウザを操作して自動的に再読み込みするはず。

src/main/webapp/app/entities/entry/entry.component.html

@@ -34,7 +34,7 @@
                 <tr *ngFor="let entry of entries ;trackBy: trackId">
                     <td><a [routerLink]="['/entry', entry.id, 'view']">{{ entry.id }}</a></td>
                     <td>{{ entry.title }}</td>
-                    <td>{{ entry.content }}</td>
+                    <td [innerHTML]="entry.content"></td>
                     <td>{{ entry.date | date:'medium' }}</td>
                     <td>
                         <div *ngIf="entry.blog">

記事一覧ページのレイアウトを変更

記事一覧ページがブログ風になるよう1列のスタックレイアウトに変更します。

src/main/webapp/app/entities/entry/entry.component.html

@@ -18,54 +18,31 @@
         <span jhiTranslate="jhipsterblogApp.entry.home.notFound">No entries found</span>
     </div>

-    <div class="table-responsive" id="entities" *ngIf="entries && entries.length > 0">
-        <table class="table table-striped" aria-describedby="page-heading">
-            <thead>
-                <tr jhiSort [(predicate)]="predicate" [(ascending)]="ascending" [callback]="reset.bind(this)">
-                    <th scope="col"  jhiSortBy="id"><span jhiTranslate="global.field.id">ID</span> <fa-icon icon="sort"></fa-icon></th>
-                    <th scope="col"  jhiSortBy="title"><span jhiTranslate="jhipsterblogApp.entry.title">Title</span> <fa-icon icon="sort"></fa-icon></th>
-                    <th scope="col"  jhiSortBy="content"><span jhiTranslate="jhipsterblogApp.entry.content">Content</span> <fa-icon icon="sort"></fa-icon></th>
-                    <th scope="col"  jhiSortBy="date"><span jhiTranslate="jhipsterblogApp.entry.date">Date</span> <fa-icon icon="sort"></fa-icon></th>
-                    <th scope="col"  jhiSortBy="blog.name"><span jhiTranslate="jhipsterblogApp.entry.blog">Blog</span> <fa-icon icon="sort"></fa-icon></th>
-                    <th scope="col"></th>
-                </tr>
-            </thead>
-            <tbody infinite-scroll (scrolled)="loadPage(page + 1)" [infiniteScrollDisabled]="page >= links['last']" [infiniteScrollDistance]="0">
-                <tr *ngFor="let entry of entries ;trackBy: trackId">
-                    <td><a [routerLink]="['/entry', entry.id, 'view']">{{ entry.id }}</a></td>
-                    <td>{{ entry.title }}</td>
-                    <td>{{ entry.content }}</td>
-                    <td>{{ entry.date | date:'medium' }}</td>
-                    <td>
-                        <div *ngIf="entry.blog">
-                            <a [routerLink]="['/blog', entry.blog?.id, 'view']" >{{ entry.blog?.name }}</a>
-                        </div>
-                    </td>
-                    <td class="text-right">
-                        <div class="btn-group">
-                            <button type="submit"
-                                    [routerLink]="['/entry', entry.id, 'view']"
-                                    class="btn btn-info btn-sm">
-                                <fa-icon icon="eye"></fa-icon>
-                                <span class="d-none d-md-inline" jhiTranslate="entity.action.view">View</span>
-                            </button>
-
-                            <button type="submit"
-                                    [routerLink]="['/entry', entry.id, 'edit']"
-                                    class="btn btn-primary btn-sm">
-                                <fa-icon icon="pencil-alt"></fa-icon>
-                                <span class="d-none d-md-inline" jhiTranslate="entity.action.edit">Edit</span>
-                            </button>
-
-                            <button type="submit" (click)="delete(entry)"
-                                    class="btn btn-danger btn-sm">
-                                <fa-icon icon="times"></fa-icon>
-                                <span class="d-none d-md-inline" jhiTranslate="entity.action.delete">Delete</span>
-                            </button>
-                        </div>
-                    </td>
-                </tr>
-            </tbody>
-        </table>
+    <div class="table-responsive" *ngIf="entries?.length > 0">
+        <div infinite-scroll (scrolled)="loadPage(page + 1)" [infiniteScrollDisabled]="page >= links['last']" [infiniteScrollDistance]="0">
+            <div *ngFor="let entry of entries; trackBy: trackId">
+                <a [routerLink]="['/entry', entry.id, 'view' ]">
+                    <h2>{{entry.title}}</h2>
+                </a>
+                <small>Posted on {{entry.date | date: 'short'}} by {{entry.blog.user.firstName}}</small>
+                <div [innerHTML]="entry.content"></div>
+                <div class="btn-group mb-2 mt-1">
+                    <button type="submit"
+                            [routerLink]="['/entry', entry.id, 'edit']"
+                            class="btn btn-primary btn-sm">
+                        <fa-icon [icon]="'pencil-alt'"></fa-icon>
+                        <span class="d-none d-md-inline" jhiTranslate="entity.action.edit">Edit</span>
+                    </button>
+                    <button type="submit"
+                            [routerLink]="['/', 'entry', { outlets: { popup: entry.id + '/delete'} }]"
+                            replaceUrl="true"
+                            queryParamsHandling="merge"
+                            class="btn btn-danger btn-sm">
+                        <fa-icon [icon]="'times'"></fa-icon>
+                        <span class="d-none d-md-inline" jhiTranslate="entity.action.delete">Delete</span>
+                    </button>
+                </div>
+            </div>
+        </div>
     </div>
 </div>

バックエンド API の安全性を高める

BlogResource へアクセスするときは、ログインしているユーザーのリソースを扱っているかどうかをチェックするようにします。結合テストも修正しましょう。

src/main/java/org/bitbucket/yujiorama/jhpister_blog/web/rest/BlogResource.java

@@ -47,11 +49,14 @@ public class BlogResource {
      * @throws URISyntaxException if the Location URI syntax is incorrect.
      */
     @PostMapping("/blogs")
-    public ResponseEntity<Blog> createBlog(@Valid @RequestBody Blog blog) throws URISyntaxException {
+    public ResponseEntity<?> createBlog(@Valid @RequestBody Blog blog) throws URISyntaxException {
         log.debug("REST request to save Blog : {}", blog);
         if (blog.getId() != null) {
             throw new BadRequestAlertException("A new blog cannot already have an ID", ENTITY_NAME, "idexists");
         }
+        if (!blog.getUser().getLogin().equals(SecurityUtils.getCurrentUserLogin().orElse(""))) {
+            return ResponseEntity.status(HttpStatus.FORBIDDEN).body("error.http.403");
+        }
         Blog result = blogRepository.save(blog);
         return ResponseEntity.created(new URI("/api/blogs/" + result.getId()))
             .headers(HeaderUtil.createEntityCreationAlert(applicationName, true, ENTITY_NAME, result.getId().toString()))
@@ -68,11 +73,14 @@ public class BlogResource {
      * @throws URISyntaxException if the Location URI syntax is incorrect.
      */
     @PutMapping("/blogs")
-    public ResponseEntity<Blog> updateBlog(@Valid @RequestBody Blog blog) throws URISyntaxException {
+    public ResponseEntity<?> updateBlog(@Valid @RequestBody Blog blog) throws URISyntaxException {
         log.debug("REST request to update Blog : {}", blog);
         if (blog.getId() == null) {
             throw new BadRequestAlertException("Invalid id", ENTITY_NAME, "idnull");
         }
+        if (blog.getUser() != null && !blog.getUser().getLogin().equals(SecurityUtils.getCurrentUserLogin().orElse(""))) {
+            return ResponseEntity.status(HttpStatus.FORBIDDEN).body("error.http.403");
+        }
         Blog result = blogRepository.save(blog);
         return ResponseEntity.ok()
             .headers(HeaderUtil.createEntityUpdateAlert(applicationName, true, ENTITY_NAME, blog.getId().toString()))
@@ -97,9 +105,14 @@ public class BlogResource {
      * @return the {@link ResponseEntity} with status {@code 200 (OK)} and with body the blog, or with status {@code 404 (Not Found)}.
      */
     @GetMapping("/blogs/{id}")
-    public ResponseEntity<Blog> getBlog(@PathVariable Long id) {
+    public ResponseEntity<?> getBlog(@PathVariable Long id) {
         log.debug("REST request to get Blog : {}", id);
         Optional<Blog> blog = blogRepository.findById(id);
+        if (blog.isPresent() &&
+            blog.get().getUser() != null &&
+            !blog.get().getUser().getLogin().equals(SecurityUtils.getCurrentUserLogin().orElse(""))) {
+            return ResponseEntity.status(HttpStatus.FORBIDDEN).body("error.http.403");
+        }
         return ResponseUtil.wrapOrNotFound(blog);
     }

@@ -110,8 +123,14 @@ public class BlogResource {
      * @return the {@link ResponseEntity} with status {@code 204 (NO_CONTENT)}.
      */
     @DeleteMapping("/blogs/{id}")
-    public ResponseEntity<Void> deleteBlog(@PathVariable Long id) {
+    public ResponseEntity<?> deleteBlog(@PathVariable Long id) {
         log.debug("REST request to delete Blog : {}", id);
+        Optional<Blog> blog = blogRepository.findById(id);
+        if (blog.isPresent() &&
+            blog.get().getUser() != null &&
+            !blog.get().getUser().getLogin().equals(SecurityUtils.getCurrentUserLogin().orElse(""))) {
+            return ResponseEntity.status(HttpStatus.FORBIDDEN).body("error.http.403");
+        }
         blogRepository.deleteById(id);
         return ResponseEntity.noContent().headers(HeaderUtil.createEntityDeletionAlert(applicationName, true, ENTITY_NAME, id.toString())).build();
     }

src/test/java/org/bitbucket/yujiorama/jhpister_blog/web/rest/BlogResourceIT.java

@@ -37,6 +38,8 @@ public class BlogResourceIT {

     @Autowired
     private BlogRepository blogRepository;
+    @Autowired
+    private UserRepository userRepository;

     @Autowired
     private EntityManager em;
@@ -52,10 +55,11 @@ public class BlogResourceIT {
      * This is a static method, as tests for other entities might also need it,
      * if they test an entity which requires the current entity.
      */
-    public static Blog createEntity(EntityManager em) {
+    public Blog createEntity(EntityManager em) {
         Blog blog = new Blog()
             .name(DEFAULT_NAME)
-            .handle(DEFAULT_HANDLE);
+            .handle(DEFAULT_HANDLE)
+            .user(userRepository.findOneByLogin("user").get());
         return blog;
     }
     /**
@@ -78,6 +82,7 @@ public class BlogResourceIT {

     @Test
     @Transactional
+    @WithMockUser
     public void createBlog() throws Exception {
         int databaseSizeBeforeCreate = blogRepository.findAll().size();
         // Create the Blog
@@ -154,6 +159,7 @@ public class BlogResourceIT {

     @Test
     @Transactional
+    @WithMockUser
     public void getAllBlogs() throws Exception {
         // Initialize the database
         blogRepository.saveAndFlush(blog);
@@ -166,9 +172,10 @@ public class BlogResourceIT {
             .andExpect(jsonPath("$.[*].name").value(hasItem(DEFAULT_NAME)))
             .andExpect(jsonPath("$.[*].handle").value(hasItem(DEFAULT_HANDLE)));
     }
-
+
     @Test
     @Transactional
+    @WithMockUser
     public void getBlog() throws Exception {
         // Initialize the database
         blogRepository.saveAndFlush(blog);
@@ -191,6 +198,7 @@ public class BlogResourceIT {

     @Test
     @Transactional
+    @WithMockUser
     public void updateBlog() throws Exception {
         // Initialize the database
         blogRepository.saveAndFlush(blog);
@@ -236,6 +244,7 @@ public class BlogResourceIT {

     @Test
     @Transactional
+    @WithMockUser
     public void deleteBlog() throws Exception {
         // Initialize the database
         blogRepository.saveAndFlush(blog);

いろいろなデプロイ

本番用のビルドでテストが成功することを確認します。

./mvnw -Pprod clean verify