20200404のJavaに関する記事は4件です。

lombokでデフォルトコンストラクタが無くてNoSuchMethodException

凡ミスの記録。

lombokを使用して以下のコードを実行したところ、実行時エラーになった。

@Data
@AllArgsConstructor
public class Person {
  ...
Caused by: java.lang.InstantiationException: kagamihoge.springbatchsample.Person
    at java.base/java.lang.Class.newInstance(Class.java:571) ~[na:na]
    at org.springframework.batch.item.file.mapping.BeanWrapperFieldSetMapper.getBean(BeanWrapperFieldSetMapper.java:248) ~[spring-batch-infrastructure-4.2.1.RELEASE.jar:4.2.1.RELEASE]
    ... 53 common frames omitted
Caused by: java.lang.NoSuchMethodException: kagamihoge.springbatchsample.Person.<init>()
    at java.base/java.lang.Class.getConstructor0(Class.java:3350) ~[na:na]
    at java.base/java.lang.Class.newInstance(Class.java:556) ~[na:na]
    ... 54 common frames omitted

原因は、引数無しのデフォルトコンストラクタが無いのでリフレクションによるインスタンス生成に失敗していた。

というわけで、lombokで引数無しコンストラクタも生成するように指定した。

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Person {
  ..
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Spring Boot 2 Filter内でSessionScopeBeanをDIする

前置き

最近Spring BootでWeb開発をしています。直接HttpSessionを利用する方法ではなく、できるだけ@SessionScopeでセッションを管理したいと思っています。Filter内で@SeesionScope Beanを参照する方法を調査しました。

構成

名前 バージョン
macOS Catalina 10.15.4
IntelliJ IDEA 2019.3.4 (Community Edition)
Java "11.0.2" 2019-01-15
Spring Boot 2.2.6
Kotlin 1.3.71

サンプルコードやプロジェクトをGitHubに公開しています。よろしければご覧ください。

結論

いろいろな情報があり調査した内容も後述しますが、最初に結論から書きます。
シンプルな構成であれば@Autowiredのみで実現可能でした。

UserInfo.kt(@SessionScope)
@Component
@SessionScope
data class UserInfo(
        var name: String?
) : Serializable
SessionFilter.kt(OncePerRequestFilter)
@Component
class SessionFilter : OncePerRequestFilter() {

    // ControllerでDIするのと同様でした。
    @Autowired
    private lateinit var userInfo: UserInfo

    override fun doFilterInternal(request: HttpServletRequest, response: HttpServletResponse, filterChain: FilterChain) {
        println("name: ${userInfo.name}")
        filterChain.doFilter(request, response)
    }
}

結論までの経緯

Spring Boot 2の書籍ではありませんが、Spring界隈では有名と思われるSpring徹底入門 Spring FrameworkによるJavaアプリケーション開発ではDelegatingFilterProxyにフィルターを登録することをXMLで定義する方法が提案されていました。
そのため、まずDelegatingFilterProxyを使う方法を試行することにしました。筆者はXMLで定義する方法を好まないので、Java Config(Kotlin)で書き直しました。

SessionFilter.kt(OncePerRequestFilter)
@Component("SessionFilter")  // 名前を指定していました。
class SessionFilter : OncePerRequestFilter() {
    :
    : (結論で掲載したコドと同じ)
    :
}
WebInitializer.kt
class WebInitializer : AbstractAnnotationConfigDispatcherServletInitializer() {
    override fun getRootConfigClasses(): Array<Class<*>>? {
        return null
    }

    override fun getServletMappings(): Array<String> {
        return arrayOf("/")
    }

    override fun getServletFilters(): Array<Filter> {
        val dfp = DelegatingFilterProxy().apply {
            // SessionFilter.ktの@Componentで指定した名前を設定します。
            setTargetBeanName("SessionFilter")
        }
        return arrayOf(dfp)
    }

    override fun getServletConfigClasses(): Array<Class<*>>? {
        return arrayOf(WebConfig::class.java)
    }
}

FilterにDIできないFAQをいくつか拝見して、上記のような対処方法が紹介されていることがありましたが、筆者の環境では結論のとおり、この記述がなくても目的を達成しました。
Spring MVCとSpring Boot 2の違いがあるのかもしれませんが、情報が少なすぎて調査しきれていません。

終わりに

(決してマイナーなWebフレームワークではないと思いますが)他の有名なWebフレームワークと比較すると、Spring関連の情報は煩雑でレガシーなものが多いような印象を持ちました。そのため、何かのお役に立てたらいいなぁと思いまして、久しぶりに記事を投稿しました。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ずんどこプログラム

filename.rb
package zundokoProgram;

import java.util.Random;

public class Zundoco_random {
    public static void main(String[] args) {
        Random random = new Random();
        String[] zun_doko = { "ずん ", "どこ " };
        String zundoko = new String();

        while (!(zundoko.equals("ずん ずん ずん ずん どこ "))) {
            zundoko = "";
            for (int i = 0; i < 5; i++) {
                String s = zun_doko[random.nextInt(2)]; // 変数sにランダムで選ばれた配列sh[0,1]のどちらか1文字が入る
                zundoko = zundoko.concat(s);            // 変数scに変数sをくっつける
            }
            System.out.println(zundoko);
        }
        System.out.println("きよしぃいい!!!");

    }
}

ずんどこプログラム初めて記念に投稿させていただきたい・・・!!
3日くらいかかりました。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Javaでsuperメソッドを呼び出す

はじめに

簡単なことからコツコツとjavaのアウトプットをします。
javaシルバーに合格することを目標に勉強中。

superとは

スーパークラスのインスタンスや変数を参照する際に使用する。

superを用いての親クラスメソッドの呼び出し方

super.メソッド名

書いてみる

Main.java
//スーパークラス
class hoge {
    public void print() {
        System.out.println("hello from スーパークラス");
    }
}

//子クラス
class huga extends hoge {
    public void print() {
        System.out.println("hello from 子クラス");
    }

    public void executePrint() {
        //子クラスのprint
        print();

        //スーパークラスのprint
        super.print();
    }
}

public class Main {
    public static void main(String[] args) {
        huga obj = new huga();
        obj.executePrint();
    }
}

実行結果

hello from 子クラス
hello from スーパークラス

子クラスから親クラスのメソッドを明示的に呼び出せていることが分かる。

おわりに

コンストラクタの場合は子クラスをインスタンス化すると
スーパークラスのコンストラクタ子クラスのコンストラクタが実行される。

詳細は別の記事で書く予定。

参考文献

この記事は以下の情報を参考にして執筆しました。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む