yuusuke-roughの日記

Java,SpringBoot,趣味等

プロJavaのテストケース・JavaGold取得を目指した日記

はじめに

JavaGold取得を目指して、まず月末は、昨年取得したJavaSilverの復習から入ります。

そして、MOSが取得できたので、全力で対策します。

各日記毎に分けていますが、一つずつ進めます。

 

JavaGoldはWindowsのPCでSTS(Eclipse)

プロになるJavaUbuntuのノートPCでIntellij IDEAを使用します。

 

Eclipseのショートカットで「実行」が効かない...

IntelliJ IDEAは全て使用できる...

 

※誤解していた内容も包み隠さず、記載いたしますので、日記枠にしました。

 

内容

 

アウタークラスとインナークラス

 

テーマ1:staticなインナークラスの呼び出しとstaticインナークラス外部の値へのアクセス

 

①staticなインナークラスの呼び出し

public class CH1_Q3 {

 

 private int value1 = 1;
    private static int value2 = 1;
    
    public static class judgeGetValue{
        
        private int getValue() {
         ...         

   return value2 * 1; 
        }

//----------------------------------------------------------------------

  public class Item{

        ...

  }
  }

 

上記のクラスを呼び出す時、

new CH1_Q3.judgeGetValue().getValue()でアクセスができる。

アウタークラスのCH1_Q3をインスタンス化して、static領域にあるjudgeGetValueクラスにアクセスするものと考えていたが、new CH1_Q3()...とすると動かない。

流れとしては、「new演算子でCH1_Q3をインスタンス化する。その際にCH1_Q3のコンストラクタを呼び出す」と理解していたが違うのだろうか...

 

今まで、new judgeGetValue().getValue()としていた事からも、結局同じことをしているのだろうか。

 

切り分け

staticじゃなくて、ただのインナークラスならどうか。

上記Itemクラスをインスタンス化してみる。この時、あえてItemクラスを直接インスタンス化してみる。

 

new CH1_Q3.Item()とすると...

アクセス可能な型 CH1_Q3 のエンクロージング・インスタンスがありません。型 CH1_Q3 のエンクロージング・インスタンスで割り振りを限定する必要があります (たとえば x.new A() で、x は CH1_Q3 のインスタンス)。

 

そもそも、

New演算子は初期化と記憶域の確保の2つに機能が分かれているとの事。

Javaでは初期化とオブジェクトの生成。プリミティブ型には必要ない。

 

以上の事から、

・new CH1_Q3()にてヒープ領域にアウタークラスCH1_Q3のインスタンスが生成される。

・インナークラスjudgeGetValueはスタティック領域に生成されている。

・ヒープ領域にインナークラスjudgeGetValueのインスタンスはないため、直接、static領域から呼び出さなくてはいけない。

・staticであろうとも、オブジェクトを利用する際には、プリミティブ型を除いて、初期化と記憶域の確保をしなければならない。

 

よって、new CH1_Q3.judgeGetValue().getValue()となる。

 

----------------------------

2月3日追記

変な解釈をしていた。

シンプルにstatic領域にあるクラスをインスタンスを生成しなければならない。

だから、

new com.example.demo.javaGold.CH1_Q3.judgeGetValue().getValue()

でも良い事になる。

-------------------------------

 

②staticなインナークラスの外部の値へのアクセス

上記コードのgetValue()内にて、同じstaticであるフィールドvalue2にはアクセスできる。

ただ、非staticフィールドvalue1のアクセスはできない。

 

テーマ2:非static領域からstatic領域へのアクセスとその逆

 

public static class Inner{

  

}

 

public class Inner_nonStatic{

  new Inner();

}

 

上記のように非static領域からstatic領域へのアクセスはできる。

しかし、その逆はできない。

CH1_Q2(アウタークラス)からインスタンス化して生成する。

 

ローカルクラス

ローカル変数とローカルクラスのライフサイクルの違いについて、検証したかったができなかったので、ひとまず、下記を意識する。

・ローカルクラス内で、ローカル変数を扱うときは実質的にfinalでなくてはならない。

・使用するローカル変数の宣言は、ローカルクラスの先にしなければならない。

※いつかちゃんと理解したい...

 

 

感想

上記に手こずり、プロJavaがあまり進めなかったうえにJavaGoldもテストケースを考える余裕がなかった...

入力した年、月、日のintの値をLocalDateに変換し、formattedで指定した書式で返すというメソッドを作り、テストケースを作成のみ。

 

まだ読んでいる段階なので記載していませんが、logging含めた独学であまり触れていなかった範囲が刺さった。

進め方にまだまだ無駄な時間があるので、引っ越し日までに安定させたい。

プロになるJavaの学習日記 2日目

はじめに

プロJava 2回目の日記です。

転職に当たり、業界の基礎知識について勉強を始めました。

開発の分類からイメージできるものとできないものがあるので、概要を抑える程度に読みたいと思います。

 

どのようにしたら良いテスター、プログラマーシステムエンジニアになれるのか、いまだ想像が付きません。

趣味から入ったゆえに、私に足りないのはプログラミングに対する厳密さだと思いますが、その先駆けとして、Junitを通したJavaの理解は大事な一歩だと思います。

 

今、業界でしっかりと業務をできるように様々な方面から準備をしておりますが、楽しいです。ただ、抜かりなくと考えるあまり、自分で考える事を放棄するようにはならないようにしたいと思います。対して、自己完結しないよう気をつけて程よいラインを見つけられたらと思います。適応する事の難しさを感じます。

 

内容

Junitを使い始めて、用意されているメソッドがどのような値を返すのか一つ一つ学んでいます。

 

コード

public LocalDate getPlusDays(int value) {
        return LocalDate.now().plusDays(value);
    }
    
    public String formattedDate(LocalDate date) {
        return "%tY年%<tm月%<td日".formatted(date);
    }
    
    public String formattedDateTime(LocalDateTime date) {
        return "%tY年%<tm月%<td日 %<tH時%<tM分".formatted(date);
    }

 

テスト

@Test
    void tommorow() {
        assertEquals(LocalDate.parse("2023-01-27"), new CH2_practice().getPlusDays(1)); 
        assertEquals(LocalDate.parse("2023-01-26"), new CH2_practice().getPlusDays(0));
        assertEquals(LocalDate.parse("2023-01-25"), new CH2_practice().getPlusDays(-1));
    }
    
    @Test
    void formattedDate() {
        assertEquals("2021年09月14日", new CH2_practice().formattedDate(LocalDate.of(2021, 9, 14)));
        //assertEquals("0年0月0日", new CH2_practice().formattedDateTime(LocalDate.of(0, 0, 0))); DateTimeException
        //assertEquals("2021年02月29日", new CH2_practice().formattedDateTime(LocalDate.of(2021, 2, 29))); DateTimeException
    }
    
    @Test
    void formattedDateTime() {
        assertEquals("2021年09月14日 14時30分", new CH2_practice().formattedDateTime(LocalDateTime.of(2021, 9, 14, 14, 30)));
        }

 

不正な値を入れるとLocalDate.of()やLocalDateTime.of()はDateTimeExceptionがでる。

プロになるJavaの学習日記 1回目

はじめに

IntelliJ IDEAはUbuntuを入れているPCにインストールしていました。

Swingがクラスファイルからは実行できるけれど、JShellから入力だと実行できない現象についてリベンジしたり、復習に時間を費やしました。前者は徒労に終わり、後者はオートマトンやツリー探索をメインに進めたので楽しかったです。

 

今回は、JUnitについて触れていきます。(1/23)

22日、23日共に、別の資格の試験と賃貸探しに時間がかかりました。

25日でひとまず、プログラミング以外の資格については終わりです。

 

内容

 

3章

足し算、掛け算、割り算、文字列を指定した回数繰り返して表示する処理のテストを考えました。コメントアウトしている部分は、異常になりそうな値や境界になりそうな値を入れてみました。

 

循環小数についてはDoubleのisFiniteやisInfiniteで対応不可

org.opentest4j.AssertionFailedError: Expected java.lang.ArithmeticException to be thrown, but nothing was thrown.

 

値は...1.6666666666666667

 

一方で、BigDecimalで試すも下記例外発生のため、そのまま使用する事に(正しいのかな)

jshell> BigDecimal.valueOf(5).divide(BigDecimal.valueOf(3));
|  例外java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.
|        at BigDecimal.divide (BigDecimal.java:1780)
|        at (#1:1)

 

JVMで出す例外については、触れる必要はないとアドバイスを頂き修正(1/23)

プロJavaの8章「異常値のテスト」や「不安な箇所」の項目にも記載有。

 

プロJavaP49までのコードとテストコード(1/23:修正済)

 

コード

 

public class CH2_practice {

    
    public int add(int a, int b) {
        return a + b;
    }
    
    
    public int minus(int a, int b) {
        return a - b;
    }
    
    public int multiply(int a, int b) {
        return a * b;
    }
    

    public double division(double a, double b) {
        return a / b;
    }
    
    public String repeatString(String str, int counts) {
        return str.repeat(counts);
    }
    
}

------------------------------------------------------------------------------------------------

 

class TEST_CH2_practice {

    @Test
    @DisplayName("足し算のテスト")
    void addTest() {
        assertEquals(9 , new CH2_practice().add(7, 2), "7 + 2 = 9");
    }
    
    @Test
    @DisplayName("引き算のテスト")
    void minus() {
        assertEquals(5 , new CH2_practice().minus(7, 2), "7 - 2 = 5");
    }
    
    @Test
    @DisplayName("掛け算のテスト")
    void multiplyTest() {
        assertEquals(14 , new CH2_practice().multiply(7, 2), "7 * 2 = 14");
        assertEquals(0 , new CH2_practice().multiply(1, 0), "1 * 0 = 0");
    }

    @Test
    @DisplayName("割り算のテスト")
    void divisionTest() {
        assertEquals(5 , new CH2_practice().division(10, 2), "10 / 2 = 5");
        assertEquals(0 , new CH2_practice().division(0, 2), "0 / 2 = 0");
    }
    
    @Test
    void repeatTest() {
        assertEquals("HelloHello", new CH2_practice().repeatString("Hello", 2 ));
        assertEquals("", new CH2_practice().repeatString("Hello", 0 ));
    }
    
    
}

    

感想(1/23)

学習中に思いますが、ここからは、いかに成果に結びつくように方向性を誤らず、継続的にできるかが問題になりそうです。

ブログになるべく挙げるようにしたいと思います。

 

 

関係ない話(こちらは項目は今回で最後)

ブログ公開にあたって、関係ない話は関係ないので、書かないようにしようと思いました。

ただひたすら修正する日記 1,2,3日目 in Spring Boot

はじめに

業務に関わる学習の合間に、進めているアプリ作りの日記です。

1月16日より開始します。

学習の進度によっては、できない日もあります。

 

内容

 

①登録処理の確認メール受け取りをしていないアカウントにてorg.springframework.security.authentication.DisabledException: User is disabledが発生しログインできなくなる。

 

UserDetailsServiceにてUserを返す際に第3引数のenableがfalseになっている事で起きる。

 

UserDetails (spring-security-docs API) - Javadoc

enabled set to true if the user is enabled

上記例外が発生した際に、HTMLにて確認メールを再送信できるようにする。

 

下記コード追記で例外が発生。

 

<div th:if = "(${message} != null) || (${session[SPRING_SECURITY_LAST_EXCEPTION]} != null)">

  ${message}

    <div th:if = "${message == '登録が完了しましたので、確認メールを送らせていただきました。有効期限は24時間です。' || session[SPRING_SECURITY_LAST_EXCEPTION] == 'org.springframework.security.authentication.DisabledException: User is disabled'}" >
        <h3>登録後に確認メールが届かない際は、メール受信設定確認の上、こちらにメールアドレスを入力し再度送信してください。</h3>
        <form th:action="@{/resendConfirmationEmail}" class="forSiteUser" method=post>
            <input type="email" name=mail placeholder="メールアドレスはこちら">
            <button >再送信</button>
        </form>
    </div>
</div>

 

Could not parse as expression:(${message} != null) || (${session[SPRING_SECURITY_LAST_EXCEPTION]} != null)

...

EL1001E: Type conversion problem, cannot convert from null to boolean

 

Tutorial: Using Thymeleaf (ja)

OGNL/SpringElのエンジンが処理する記法とThymeleafが処理する記法があり、両者ともに試すが不可。

 

・(${session[SPRING_SECURITY_LAST_EXCEPTION]}) != null は動作する。

・'a' == 'a'は動作する

・ " 'a' == 'a' || 'b' == 'b' "で不可。

→「or」演算子を使用して"('a' == 'a') or ('b' == 'b') "で解決。

 

修正後もorg.springframework.security.authentication.DisabledException: User is disabledについては一致しない。

→ThymeleafにOGNL式で評価できるString.containsを使う。

${#strings.contains(session[SPRING_SECURITY_LAST_EXCEPTION], 'org.springframework.security.authentication.DisabledException: User is disabled')}で動作した。

...例外を渡すより、messageSourceを使ってメッセージにしてしまった方が簡潔な気がする。

 

確認メール再送実装も...

該当のメールアドレスの確認用トークンが存在しない問題が発生。

いずれ実装しようと思っていた期限切れトークンの自動削除処理を見据えて、トークンの再発行処理も加える。

 

if(tokenRepository.findByUser(siteUser) == null) {
            String token = UUID.randomUUID().toString();
            createVerificationTokenForUser(siteUser, token);
        }

 

...DBへの無駄な問い合わせが多い気もする。

 

 

まとめ

・#string等の式はOGNL式を使用する。

・ThymeleafはJavaと書き方が違う事もあるから都度ドキュメント確認。

・例外については、MessageSourceを使う事で冗長にならなくて済むから時間がある時に修正要。

 

CSRFトークンの実装誤りの修正

以前、「Thymeleafの場合は、${_csrf.token}でCSRFトークンを取得できる」というのを試したが、動作しなかった。そこで、CSRFトークンをHttpServletRequestから抜き出していたが、誤った実装であった。

 

${_csrf.token}のみで取得できたので、各コントローラーを修正していく。

 

その前に...

現時点でHttpServletRequestから取得していたCSRFトークンだと403エラーがでた。

Resolved [org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'POST' is not supported]

 

結果としては、Thymeleafの機能を用いたCSRFトークンの取得で改善した。

★今回は、正しい実装に戻して切り分ける方針で解決した。

具体的な原因については後日調べる予定。

CSRFトークンがリクエスト毎に変わっている。(CSRFトークンが発行されるタイミングと関わるFilterから調べる

 

以上、各Ajax通信している箇所についても同様の修正を行う。

 

 

 

 

関係のない話

ムエタイの退会手続きに行きました。

転職したら、柔道か柔術のいずれかに挑戦したいです。

 

AOP、Slf4jとtransaction in Spring Boot

はじめに

Spring解体新書で学習開始。(他、TCP/IP、プロJavaの学習継続中。Excelは「Excel 最強の教科書」にて学習中。)

今回は、あまり触れてこなかったSlf4jとtransactionをピックアップ。

サンプルアプリを使用して理解を深めたい。

 

内容

 

AOPとSlf4j

 

作成中...

 

Leetcode1回目の日記

プロJava復習につき、各文法の動作確認のため開始。

感想:解答後に閲覧できる実行速度の速い人のコードが綺麗すぎて、自分のコードに無駄なステップが多いことがわかった。

 

例えば、「文字列を受け取る→文字列を分割しListに格納する→Listに格納したものを数字に変換する→規則に合わせて、Listに格納した値を整理する→最後にList内の値を足し合わせる」と記述した。

これを、早い人は「for文内でcharAtで1文字取り出す→switchで数字に変換→その場で値を比較、整理」としている。

 

基本的な文法の学習にもなるうえに、自己完結のし易い独学の穴も埋められるのはとても良いです。

また、メモリや実行速度といった部分も考えるきっかけになりそうです。(どう考えていけばいいのだろうか、今の私では見当もつきません。)

JavaGold取得にあたり、並行して一日一問は解きたいです。

 

 

関係のない話

14日、職場の方々へのご挨拶も終わりました。

就業環境含めた生活環境には、とても恵まれていたと思います。

私の10代後半から20代前半を思うと、今は状況が天と地ほど違う心地がします。

また、気が付くと、20代後半は、結果的に私が本来したかった事の準備期間となりました。

今年10月で30歳です。ここからは思う存分、働き、プライベートで作成しているアプリも動かし、楽しみたいと思います。

認可処理で弾かれた時のエラー処理 in Spring Security

はじめに

今回は、今まで使用していた自前の認可処理を削除します。

そして、前回のカスタム認可に対して、参加者以外がルームURLにアクセスしようとした時の処理を実装します。

 

内容

 

参考:

アーキテクチャー :: Spring Security - リファレンス

Spring Security 使い方メモ CSRF - Qiita

HTTPステータスコード 完全に理解した - Qiita

 

状況:認可に弾かれる場合:例えば、参加者でないユーザーがルームのリンクを直接貼って拒否されると、Forbidden ステータスコード403を返す。

 

アーキテクチャー:: Spring Security - リファレンスの「セキュリティ例外の処理」参照

それが AccessDeniedException の場合、アクセスが拒否されますAccessDeniedHandler は、拒否されたアクセスを処理するために呼び出されます。

AccessDeniedHandler (spring-security-docs API) - Javadoc

 

 

DeniedAccessRoomHandler.java

 

public class DeniedAccessRoomHandler  implements AccessDeniedHandler{
    
    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException {

      
        response.setStatus(HttpServletResponse.SC_FORBIDDEN);
        response.setContentType("text/html; charset=UTF-8");
        try (PrintWriter writer = response.getWriter()) {
            
            writer.println("不正なリクエストです。");
        }
        
    }
    
}

 

config.java

 

http.authorizeHttpRequests(authorize -> 
                authorize.requestMatchers...

...

.exceptionHandling().accessDeniedHandler(new DeniedAccessRoomHandler());

 

上記構成に、accessDeniedPage(String url)を加えるとステータスコードが200を返してしまい、AccessDeniedHandlerを呼び出さない。

ExceptionHandlingConfigurer (spring-security-docs API) - Javadoc

 

...

.exceptionHandling(exceptionhandling -> exceptionhandling.accessDeniedHandler(new DeniedAccessRoomHandler()).accessDeniedPage("/joinRoom"))

 

に変更で、ステータス403を返し、指定したURLを表示する事ができた。

 

感想

以上、例外処理の動作確認でした。

ステータスコードや例外処理については、Csrfトークンの処理等で適宜触れてきた。

しかし、「適切な実装ができているか」と振り返ると適切とは言い難いと思う。

また、いくら調べども答えがでない事はもちろんだが、時間が足りない。

 

そこで、基礎の見直しを行いたいと思う。基礎見直し後に、改めて今回の実装を再開する。

一旦、実装にかける時間を下記に割く。

①Spring 解体新書

②プロになるJavaJava Gold対策

 

Java Goldについては、春の転職で客先面談の機会もでてくると思うが、アピールできる資格という意味でもあった方が良いと思う。

 

関係のない話

気付いたら、はてなブログLinux学習の記録の下書きがありました。

ノートパソコンにUbuntuをインストールして、コマンドを試しただけの記録なので、特に投稿する必要も感じられず没になったのでした。

 

昨日は、プログラミング以外に必要な資格取得のため、朝からお昼過ぎまで出かけておりました。移動時間は、個人Webサービスのお話をQiitaや個人ブログ、ラッコM&A等を通して読みました。プログラミングの話はもちろんですが、SEO対策やマネタイズの話もあり、興味深いです。

 

また、「はっと目覚める確率」を始めました。

昔、青チャートで解いたような気のする問題が多いですが、この本を始めてから別解を考えるのが楽しくなりました。

数列あたりの知識も抜けているので、流れとしては、数年かけて、確率・場合により数列→微分積分線形代数→統計か確率論を考えています。

業務の学習やアプリ開発に時間を割きたいので、一日一時間を上限とします。

 

マスタリングTCP/IPでは、業務でお馴染みだった光回線のお話があって面白いです。こちらも1時間を目安に読み進めていきます。目標は、概要の理解に留めます。

特定のURLで認可処理を行う in Spring Security

はじめに

※年末の記録 + 1月1日の記録に修正を加え投稿しました。

 

今回は、最終目標の「特定のURLにてルームメンバーかチェックする認可処理を行う実装」です。

 

前回はロールと権限の実装で、認可について学びました。

Role実装 in Spring Security - yuusuke-roughの日記

 

Spring Security6.0.1へ移行で書き方が変わった話

Spring Security 6.0.1にバージョンを変更した話 - yuusuke-roughの日記

 

ーー余談:実装以外の悩みーー

ドキュメントの読み込みが段々深くなった分、「作成しているアプリに必要な非機能要件って...」と思うようになりました。

今までは、気付いた課題...例えば、多重ログインやアカウント削除時のセッションの処理等は適宜対策してきました。しかし、これでは行き当たりばったりの良くない実装と思います。

そこで、先週から「ずっと受けたかったソフトウェアエンジニアリングの新人研修」を再読のうえ、外部・内部設計書の作成に取り掛かりました。

まだまだ先になりますが、完成すれば、「何が足りないのか」と意見をどなたかに伺いやすいのではないかと考えたからです。

 

※年末年始はSpringBoot3.0.0移行時に発生したエラーの調査のため一旦保留中

 

内容

今回もこちらを使用。

式ベースのアクセス制御 :: Spring Security - リファレンス

 

まずは、認可を行う式を準備

public class URLSecurity {

    
    
    private final RoomRepository roomRepository;
    
    @Autowired
    URLSecurity( RoomRepository roomRepository){
        this.roomRepository = roomRepository;
    }
    
    
    public boolean permissionToParticipate(Authentication authentication, String roomURL) {
        Room room = roomRepository.findByRoomURL(roomURL);
        
        List<RoomParticipant_users> participatingUsers = room.getParticipatingUsers();
        for(int i=0; i < participatingUsers.size(); i++) {
            String participatingUserName = participatingUsers.get(i).getParticipant().getMail();
            
            if(authentication.getName() .equals(participatingUserName)) {
                return true;
            }
            
        }
        
        return false;
        
    }

}

 

SecurityConfigには、下記を追記

...

anyRequest().authenticated()

    .requestMatchers("/room/{id}").access(new WebExpressionAuthorizationManager("@urlSecurity.permissionToParticipate"))

 

すると、下記のエラーが発生...

 java.lang.IllegalStateException: Can't configure mvcMatchers after anyRequest

anyRequestの後に追加していたため発生。requestMatchersを先に追加し修正完了。

 

次に、下記のエラーが発生...

 Failed to evaluate expression '@urlSecurity.permissionToParticipate(authentication, #roomId)'

...

No bean resolver registered in the context to resolve access to bean 'URLSecurity'

 

はじめにurlSecurityのbeanはあるのだろうか?

Springで定義済のBean名一覧を出力する - endokのブログ

 

...

httpSessionEventPublisher
urlSecurity
org.springframework.web.socket.config.annotation.DelegatingWebSocketMessageBrokerConfiguration
stompWebSocketHandlerMapping

...

 

urlSecurityはありました。

そうなると、Bean ResolverにこのBeanを登録する実装をしなければいけない可能性を考えた。

 

SpELとは...

Spring Framework コアテクノロジー - リファレンス

 

評価の仕組みについて

EvaluationContext インターフェースは、式を評価してプロパティ、メソッド、またはフィールドを解決し、型変換を実行する際に使用されます。

 

Bean Resolverとは...

BeanResolver (Spring Framework API) - Javadoc

A bean resolver can be registered with the evaluation context and will kick in for bean references: @myBeanName and &myBeanName expressions. The & variant syntax allows access to the factory bean where relevant.

 

しかし、今回はWebExpressionAuthorizationManagerで与えられた式を評価しようとしている。改めて調べると、no bean resolverの原因については下記にあった。

 

java - Spring Boot 3.0/Security 6.0 Migration - "EL1057E: No bean resolver registered in the context to resolve access to bean..." in SecurityFilterChain - Stack Overflow

Bean empFilter is registered in the ApplicationContext of the test. In Spring Security 6, WebExpressionAuthorizationManager uses an instance of DefaultHttpSecurityExpressionHandler as its SpEL expression handler. DefaultHttpSecurityExpressionHandler has no access to the application context unless explicitly configured.

 

少し遡るが、初めにBeanがApplicationContextに登録されているのは確認していた。

また、上記の通り、SpEL expression handlerとしてDefaultHttpSecurityExpressionHandlerが使用されるので、SpELについてはここで処理と考える。

そして、「設定しないとapplication contextにアクセスできない。」...ここが原因とわかった。

 

以上、カスタム認可の実装でした。

あとは、認可処理でユーザーが弾かれた場合にForbiddenになるので、その処理を実装したいです。

 

感想

実装のきっかけはリファレンスからとはいえ、リファレンスのみで完結できる問題ではありませんでした。

「no bean resolver」という言葉に引っ張られ、SpELのリファレンスにあるようなbean resolverを含める方法を考え、遠回りしました。

結果的に、SpringSecurity内でSpELを扱うというWebExpressionAuthorizationManagerのSecurityExpressionHandlerの話にたどり着き、解決しました。

 

独学の恐ろしいところは、着眼点がおかしいと時間がかかる事です。

そして、その時間を短くするために、何度も間違った調べ方、考え方を修正していく作業は少しずつ上達を実感させてくれます。

 

また、「はじめに」の項の「余談」に記載したように、新たに設計の問題が加わりました。

全方面で突き詰めていかなくてはいけない、自己完結できない問題に気づいたのは大きな一歩だと思います。

まずは、完成を目指して進めます。

 

全然関係のない話

元旦は、従弟や妹夫婦と過ごしました。

高校生になるまではよく一緒にいたので、兄弟のような感覚で、懐かしさと今も関わりのある事に不思議さを感じ、楽しいです。

 

あれ、この中で自分だけ音楽やった事ない...