質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.59%

Spring bootにおけるビルド失敗2

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 4,879

sanezane

score 85

お世話になっております。Spring bootにおけるビルド失敗のもう1つのエラーについて質問させていただきます。
前回と同じステージで止まっており一部のユーザーの方に大変お世話になっております。
よろしければ、この問題についてもご意見を頂戴したく質問致します。

 エラー内容

 Error creating bean with name 'webSecurityConfig': Unsatisfied dependency expressed through field 'userDetailsService'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'reservationUserDetailsService': Unsatisfied dependency expressed through field 'userRepository'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userRepository': Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Failed to create query for method public abstract mrs.domain.model.User mrs.domain.repository.user.UserRepository.findOne(java.lang.String)! No property findOne found for type User!

エラーログより、
Failed to create query for method public abstract mrs.domain.model.User mrs.domain.repository.user.UserRepository.findOne(java.lang.String)! No property findOne found for type User!
とあるため、UserRepositoryクラスのfindOneメソッドの引数がうまく渡っていない?と漠然と認識しています。
それがわかったところで以降のアプローチがわかりません。

・findOneメソッドを定義しているUserRepositoryを修正?
・引数がうまく渡っていないためUserモデルを修正?

package mrs.domain.repository.user;

import org.springframework.data.jpa.repository.JpaRepository;
import mrs.domain.model.User;

public interface UserRepository extends JpaRepository<User, String> {

    User findOne(String username);
}
package mrs.domain.model;

import javax.persistence.*;

@Entity
@Table(name = "usr")
public class User {
    @Id
    private String userId;
    private String password;
    private String firstName;
    private String lastName;
    @Enumerated(EnumType.STRING)
    private RoleName roleName;

    public String getUserId() {
        return userId;
    }

    public void setUserId(String userId) {
        this.userId = userId;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public RoleName getRoleName() {
        return roleName;
    }

    public void setRoleName(RoleName roleName) {
        this.roleName = roleName;
    }

}
package mrs.domain.service.user;

import mrs.domain.model.User;
import mrs.domain.repository.user.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

@Service
public class ReservationUserDetailsService implements UserDetailsService {
    @Autowired
    UserRepository userRepository;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = userRepository.findOne(username);
        if (user == null) {
            throw new UsernameNotFoundException(username + " is not found.");
        }
        return new ReservationUserDetails(user);
    }
}

宜しくお願い致します。

■追加情報
テーブル一覧キャプチャ追加
イメージ説明

11月25日
githubリンク

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • sanezane

    2018/11/24 23:25

    findOneを使うこと自体が間違っているということでしょうか?ご意見が噛み砕けず申し訳ございません。

    キャンセル

  • asahina1979

    2018/11/25 01:07

    ようみたらアノテーションしてないなリポジトリ

    キャンセル

  • sanezane

    2018/11/25 02:06

    @Repositoryアノテーションを追加してみたのですがエラー内容は変わらずでした。。。初めてeclipseからgithubへプロジェクトを公開してみたのでもしよろしければ確認をお願い致します。。。本当に勉強になります。ありがとうございます。

    キャンセル

回答 1

checkベストアンサー

+2

Spring使ったことないけどちょっと調べてみました。

  • メソッド名からクエリを生成するので、Repositoryのインタフェース定義にメソッドの定義はいらないようです。
  • 独自実装のクエリを使用する場合は「UserRepositoryCustomインタフェース+UserRepositoryImplクラス」の組み合わせで作成するようです。
  • Repositoryのインタフェース定義のメソッドを削除したら、以下のコンパイルエラーが出るようになりました。
.../Mrs/Mrs/src/main/java/mrs/domain/service/user/ReservationUserDetailsService.java:18: エラー: インタフェース QueryByExampleExecutor<T> メソッド findOneは指定された型に適用できません。
                User user = userRepository.findOne(username);
                                          ^
  期待値: Example<S>
  検出値: String
  理由: 型変数Sを推論できません
    (引数の不一致: StringをExample<S>に変換できません:)
  S,Tが型変数の場合:
    メソッド <S>findOne(Example<S>)で宣言されているSはUserを拡張します
    インタフェース QueryByExampleExecutorで宣言されているTはObjectを拡張します

上記サンプルコードに合わせて以下のように修正すると、実行時エラーは出なくなります。(他二つのRepositoryについても同様に修正する必要あり)

package mrs.domain.service.user;

import mrs.domain.model.User;
import mrs.domain.repository.user.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

@Service
public class ReservationUserDetailsService implements UserDetailsService {
        @Autowired
        UserRepository userRepository;

        @Override
        public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
                // 検索条件をエンティティにセット
                User probe = new User();
                probe.setUserId(username);

                // 検索条件からExampleインスタンスを生成
                Example<User> example = Example.of(probe);
                User user = userRepository.findOne(example).get();

                if (user == null) {
                        throw new UsernameNotFoundException(username + " is not found.");
                }
                return new ReservationUserDetails(user);
        }
}

キー指定してエンティティを取得するのであれば、以下の記述でよいのではないかと思います。

                User user = userRepository.findById(username).get();

【補足】

質問のタイトルが「ビルド失敗」となっていますが、ビルドは成功して実行時のDIで失敗しています。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/11/25 15:41

    解決の手順まで丁寧に書いて下さりありがとうございます。
    大変勉強になりました。

    User user = userRepository.findById(username).get();へ修正したところうまく動いてくれました。
    ありがとうございました。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.59%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る