20200725のJavaに関する記事は14件です。

Spring Boot で TextWebSocketHandler を継承したクラスで Autowired したフィールドが NULL になる

1.環境

Spring Boot:v2.2.5

2.困ったこと

Spring Boot でチャット機能を作成するため、WebSocket を利用。

TextWebSocketHandler を継承したクラスを作成し、その中で DB にアクセスするためにリポジトリクラスを Autowired しようとしたが、フィールドに宣言したリポジトリクラスの変数が NULL。

以下が TextWebSocketHandler を継承した WebSocketChatEndpoint クラス。

WebSocketChatEndpoint.java
@ServerEndpoint("/api/chat")
@Component
public class WebSocketChatEndpoint extends TextWebSocketHandler {

  @Autowired
  private ChatRepository chatRepository; //NULL

  @OnOpen
  public void onOpen(Session session) {
  

実行時、chatRepository が NULL。

3.対応

フィールドインジェクションをセッターインジェクションに変更。

WebSocketChatEndpoint.java
@ServerEndpoint("/api/chat")
@Component
public class WebSocketChatEndpoint extends TextWebSocketHandler {

  private static ChatRepository chatRepository; //Autowiredされてる

  @Autowired
  public void setChatRepository (ChatRepository chatRepository ) {
        WebSocketChatEndpoint.chatRepository = chatRepository;
  }

  @OnOpen
  public void onOpen(Session session) {
  

コンストラクタインジェクションは試してません。

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

javaでM-SOLUTIONS プロコンオープン 2020を解く

M-SOLUTIONS プロコンオープン 2020お疲れ様でした!
公式ページ

今回の自分の書いたコードはこちら
結果はA-DまでACできました。なんとか4問ACでした、問題Dに苦戦しました・・・

以下簡単に解説します。

問題A

特定の点数の時に何級という条件を求める問題。
そのままif文でもいいですが、よく見ると200点区切りになっているので、
点数を200で割った余りを10から引くと簡単に求められます。

問題B

数字が3つ与えられて、数字を倍にする操作をK回以内に
赤の数字<緑の数字<青の数字・・・(条件*)
にできるかという問題。

数字が7以下だったので、もう単純に条件*を満たすための操作数をカウントして、Kと比較して回答しました。

問題C

テストの点数が直近K回の掛け算で与えられ、テストの点が上がったかを判定する問題。
直近K回の掛け算といっても、かけられるK個の数のうちK-1個は共通です。

A × B × C × D \\
B × C × D × E

上の図の場合、AとEを比較すればOKです。

問題D

株価の変動が与えられ、どれくらい儲けられるかという問題。
いまいち解き方には自信がないのですが、これも期間が80ということで、地道に解きました。

  • 株価の極小値を求める
  • 持っている金額で株価を買う
  • 株価の極大値を求める
  • 持っている株を全て売り払う

というのをwhile文でループさせました。

あと、これ桁あふれでWAになりましたので、longに変えました。
なかなか桁あふれするって気づかなかったです。

問題E

正答率低かったので問題も読んでいません、、、

問題F

200000という制約が無理!
N^2の計算量であれば解けましたが・・・まあ間に合わないでしょう。


感想

めっちゃ久しぶりに参加できました。。やっぱり楽しいですね。
レーティングは978→967とサボってたツケが回ってきましたかね・・・次回で1000奪還したい:cry:

E問題が難しいのもあって、D問題までのスピードがいまいちだったのも残念、、

最後まで読んでくださり、ありがとうございます!

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

Google Cloud Storage上にMavenインハウスリポジトリを構築する

はじめに

Google Cloud Storage (以下GCS)上にMavenインハウスリポジトリを構築して利用する方法のまとめです。
ドキュメントに書いてあることの二番煎じ的な感じもしますが、インハウスリポジトリの作り方や、作った後のjarファイルの転送方法から使用方法まで総合的にまとめてある記事が見当たらなかったので、備忘録として残しておきます。

ちなみに自分はGradleユーザなので、Gradleを使った場合の方法についてまとめています。

試してみるといいかもな人

  • 開発/運用で既にGCPを使っている人
    GCSのバケット作って権限の設定とかするだけでよいので簡単に導入できます!

  • Gitのサブモジュールを使ったGradleのサブプロジェクト構成に疲れた人
    Mavenセントラルからjarファイルを引っ張ってくるのと同じ感覚で使えるため楽です!

  • 既に Sonatype Nexus などのインハウスリポジトリを立てているが、維持/保守に疲れた人
    GCSはマネージドなサービスなので面倒はGoogle側で見てくれます!

構築方法および使い方

Gradleのドキュメント

公式のドキュメントは こちら から。
ちなみに リリースノート によるとバージョン4.2で追加された機能のようです。
結構前からあったんですね、知らなかったです・・・。 :sweat_drops:

インハウスリポジトリの構築

コマンド打ってバケット作成するだけです。

$ export BUCKET_NAME='your-inhouse-repository'
$ gsutil mb -c standard -l asia-northeast1 gs://${BUCKET_NAME}

自分一人で作業する分にはこれだけでOKです。
複数人で開発を行っている場合は、開発者へバケットへのアクセス権を付与してあげてください。

以下、バケット名は your-inhouse-repository で、その下にMaven用のパス maven を切って、Gradleからは gcs://your-inhouse-repository/maven を参照する前提で話を進めます。

認証方法

インハウスリポジトリなので外部には公開しません。
バケットに対する権限があるアカウントのみアクセスできるように認証を行いますが、ドキュメントにはこんな記載があります。

When using a Google Cloud Storage backed repository default application credentials will be used with no further configuration required

「アプリケーションのデフォルトの認証情報」ってなんだ?って感じですが、どうやらそういう概念があるらしいです。
GCPでは ADC と呼ばれています。

ローカルで作業する際は gcloud init して gcloud auth application-default login を行えばOKです。
それでADCとやらが適切な場所に配置され、あとはGradleが勝手にそれを使用して認証してくれます。

$ gcloud init
$ gcloud auth application-default login

jarファイルのアップロード

ライブラリ側のサンプルコードです。
Maven Publishプラグイン を使用してjarファイルをアップロードできます。

build.gradle
plugins {
    id 'java-library'
    id 'maven-publish'
}

group = 'your.libs'
version = '1.0.0'

publishing {
    publications {
        maven(MavenPublication) {
            from components.java
        }
    }
    repositories {
        // アップロード先としてインハウスリポジトリを指定する。
        maven {
            url 'gcs://your-inhouse-repository/maven'
        }
    }
}
settings.gradle
rootProject.name = 'example-library'
$ gradle publish

jarファイルの使用

ライブラリを使う側のサンプルコードです。
repositories に参照先のインハウスリポジトリを追加し、 dependencies に依存関係を定義するだけです。

build.gradle
repositories {
    // インハウスリポジトリを参照先として追加する。
    maven {
        url 'gcs://your-inhouse-repository/maven'
    }
}

dependencies {
    // あとはjarを依存関係として追加するだけで、Gradleが勝手に見つけてきてくれる。
    implementation 'your.libs:example-library:1.0.0'
}

認証情報が切り替わらない際のTips

自分はGCPのアカウントを個人用と業務用で複数所持しているのですが、 gcloud initgcloud auth application-default login をして認証情報を切り替えても、Gradleが切り替える前の情報を参照するという問題に遭遇・・・。
原因が分からず1日くらい無駄にしました。 :sweat_drops:

分かってしまえば単純ですが、原因はGradleのデーモンが起動していてそれが古い認証情報を握ったままでした。

なのでデーモンを一度停止すれば、その後は切り替えた後の認証情報を使ってくれます。

$ gradle --stop

もしくはデーモンを使用しないように明示的に指示すれば、現在の認証情報を参照してくれます。

$ gradle publish --no-daemon

余談

2020年7月25日現在、ビルドアーティファクトの管理に特化した Artifact Registry というサービスがβ版で公開されています。
Mavenリポジトリ としても使えるようですが、こちらはまだα版のようなのでこれからが楽しみといったところですね。

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

javaで席替え

Javaで男性12人と女性8人の席替え

実現したいこと

・配置はランダム
・横一列のどこかに女性一人以上を配置したい
・目の悪い人が入れば前に固定
・分かりやすいコード

結果

シャッフルされたリストから、get()で取り出す。
System〜printlnで、座席に見えるようにした

・配置はランダム
 →リストをCollections.shuffle()で毎回結果が変わる
・横一列のどこかに女性一人以上を配置したい
 →あらかじめ、女性が来るのか男性がくるのか、配置される場所を決めた
・目の悪い人の固定
 →リストから外し、”〜get()”のとこを消して固定する人の名前にする

※プログラムを実行すると一瞬で終わるのでちょっと退屈
※一度隣同士になった人を避けるなどは出来てない

コード

import java.util.ArrayList;
import java.util.Collections;

public class Sekigae4 {
        public static void main(String[] args) {

                ArrayList<String> man = new ArrayList<String>();
                man.add("男性1  ");
                man.add("男性2  ");
                man.add("男性3  ");
                man.add("男性4  ");
                man.add("男性5  ");
                man.add("男性6  ");
                man.add("男性7  ");
                man.add("男性8  ");
                man.add("男性9  ");
                man.add("男性10 ");
                man.add("男性11 ");
                man.add("男性12 ");

                ArrayList<String> woman = new ArrayList<String>();
                woman.add("女性1 ");
                woman.add("女性2 ");
                woman.add("女性3 ");
                woman.add("女性4 ");
                woman.add("女性5 ");
                woman.add("女性6 ");
                woman.add("女性7 ");
                woman.add("女性8 ");

                Collections.shuffle(man);
                Collections.shuffle(woman);

                System.out.println("--並び替え後--");
                System.out.println(woman.get(0) + " | " + man.get(0)   + " | " + man.get(1)   + " | "+ man.get(2));
                System.out.println(woman.get(1) + " | " + man.get(3)   + " | " + man.get(4)   + " | "+ woman.get(2));
                System.out.println(man.get(5)   + " | " + man.get(6)   + " | " + man.get(7)   + " | "+ woman.get(3));
                System.out.println(woman.get(4) + " | " + woman.get(5) + " | " + man.get(8)   + " | "+ man.get(9));
                System.out.println(man.get(10)  + " | " + man.get(11)  + " | " + woman.get(6) + " | "+ woman.get(7));
        }
}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Windows + JavaのUNICODE ZIPへの対応状況をざっと確認

概要

マルチ プラットフォームに向け仕様改定があったはずなのに、未だに思ったほど普及が進んでいない様に思える、UNICODE ZIP。コロナの禍中で在宅ワークも増えて、ZIPファイルでの情報交換がより増えているはずで、UNICODE ZIPの必要性はより高まっていると思う。

ふとmacOS周りの事情やマルチプラット フォームのアーカイバが気になっり、
そもそも JavaのUNICODE ZIPの対応状況はどうなのだろう? と思い、軽く調べてみた。

結論

  • Java 7 以降はUNICODE ZIPの圧縮に対応している。
    • JDK 6 で ビルドしたプログラムでもJRE 7 以降で実行すれば、UNICODE ZIPが作れる。
      targetオプションなどで 7以上を対象にするのが望ましそう
  • Java 6 以前は非対応。Apach Commons Compressで対応可能。
  • WEBアプリでのZIPの文字化け対策は、適切にUNICODE ZIPをしっかり使うこと。
    • WEBアプリはマルチ プラットフォームがそもそもの本懐。
    • WEBアプリが今更MS932で圧縮なんてしてはいけない。
      ( 馬鹿げている と言っても過言ではないくらい、随分と昔に対応されているため)
    • UNICODE ZIPに対応していない、旧時代の圧縮解凍ソフトを使うのを辞める。
      • 解凍に対応:Windows Explorer, 7zip, Explzh, ...
      • 解凍に非対応:Lhasa, Lhaplus

※ 窓の杜さん、マジでいつまでもサイトTOPのオススメ ソフトに、
UNICODE ZIPに対応していないLhaplusを掲載するの辞めてください。。。
せっかくWindows 8からExplorerがUNICODE ZIPに対応しているのに、完全にスポイルされ続けているしている。。。

検証

確認環境

  • Windows 10
  • ビルド
    • JDK 6, 7,
    • Open JDK 7, 14
  • 実行
    • JRE 6, 7, 8
    • Open JDK 7, 14

確認方法

  • Javaで圧縮するサンプル プログラムを作成。
  • 各JDKに同梱されているJREなどでそれぞれ実行し、ファイル名に日本語を含むサンプル ファイルを圧縮。
  • 7zipで開き、特性カラムを確認。
    • UNICODEの記載がある
      ⇒ Language encoding flag (EFS) が立っている
      ⇒ 正常なUNICODE ZIP
    • UNICODEの記載がない
      ⇒ Language encoding flag (EFS) が立っていない
      ⇒ 旧来のZIP
      (OSの文字コードに依存するため、圧縮時と解凍時のOSのシステム文字コードが一致している必要がある)

7zipで確認.png

参考資料

結果表

閾値が割と見えたので、総当たりは行っていない。
(JDKを揃えるのが大変なので)

ビルド
(javac)
実行
(java)
Language
encoding
flag
(EFS)
備考
JDK 6 JRE 6 なし NG
UTF-8のOSで圧縮しただけのZIP状態
JDK 6 JRE 7 あり OK
JDK 6 JRE 8 あり OK
JDK 6 Open JDK 7 あり OK
JDK 6 Open JDK 14 あり OK
JDK 7 JRE 6 - 実行不可
JDK 7 JRE 7 あり OK
JDK 7 JRE 8 あり OK
JDK 7 Open JDK 7 あり OK
JDK 7 Open JDK 14 あり OK
Open JDK 7 JRE 6 - 実行不可
Open JDK 7 JRE 7 あり OK
Open JDK 7 JRE 8 あり OK
Open JDK 7 Open JDK 7 あり OK
Open JDK 7 Open JDK 14 あり OK
Open JDK 14 JRE 6 - 実行不可
Open JDK 14 JRE 7 - 実行不可
Open JDK 14 JRE 8 - 実行不可
Open JDK 14 Open JDK 7 - 実行不可
Open JDK 14 Open JDK 14 あり OK

JavaはASCII文字のファイル名の場合でも、EFSを付ける様子。
7Zipは非ASCII文字以外を含む場合のみのため、ちょっとした違い。
ただし、UNICODE ZIPはUTF-8を使用しており、ASCII部分には互換があるため、EFSの有無はあまり影響は無い。

結果表 (Linux)

ちょうど手元にUbuntu 20をインストールした仮想マシンがあったので、ついうっかりLinux版OpenJDKも軽く試してみた。

ビルド
(javac)
実行
(java)
Language
encoding
flag
(EFS)
備考
Windows
JDK 6
Linux
Open JDK 7
あり OK
Windows
JDK 6
Linux
Open JDK 8
あり OK
Windows
JDK 6
Linux
Open JDK 14
あり OK
Windows
JDK 7
Linux
Open JDK 7
あり OK
Windows
JDK 7
Linux
Open JDK 8
あり OK
Windows
JDK 7
Linux
Open JDK 14
あり OK
Windows
Open JDK 14
Linux
Open JDK 7
あり OK
Windows
Open JDK 14
Linux
Open JDK 8
あり OK
Windows
Open JDK 14
Linux
Open JDK 14
あり OK
Linux
Open JDK 7
Windows
JRE 6
- 実行不可
Linux
Open JDK 7
Windows
JRE 7
あり OK
Linux
Open JDK 7
Windows
JRE 8
あり OK
Linux
Open JDK 7
Windows
Open JDK 7
あり OK
Linux
Open JDK 7
Windows
Open JDK 14
あり OK
Linux
Open JDK 7
Linux
Open JDK 7
あり OK
Linux
Open JDK 7
Linux
Open JDK 8
あり OK
Linux
Open JDK 7
Linux
Open JDK 14
あり OK
Linux
Open JDK 8
Windows
JRE 6
- 実行不可
Linux
Open JDK 8
Windows
JRE 7
- 実行不可
Linux
Open JDK 8
Windows
JRE 8
あり OK
Linux
Open JDK 8
Windows
Open JDK 7
- 実行不可
Linux
Open JDK 8
Windows
Open JDK 14
あり OK
Linux
Open JDK 8
Linux
Open JDK 7
- 実行不可
Linux
Open JDK 8
Linux
Open JDK 8
あり OK
Linux
Open JDK 8
Linux
Open JDK 14
あり OK
Linux
Open JDK 14
Windows
JRE 6
- 実行不可
Linux
Open JDK 14
Windows
JRE 7
- 実行不可
Linux
Open JDK 14
Windows
JRE 8
- 実行不可
Linux
Open JDK 14
Windows
Open JDK 7
- 実行不可
Linux
Open JDK 14
Windows
Open JDK 14
あり OK
Linux
Open JDK 14
Linux
Open JDK 7
- 実行不可
Linux
Open JDK 14
Linux
Open JDK 8
- 実行不可
Linux
Open JDK 14
Linux
Open JDK 14
あり OK

概ねWindows版と同様の想定通りの結果だったので、macのJavaでも同様になる期待が高い。

圧縮検証プログラムのサンプルコード

急ごしらえのため、雑コード

java
import java.io.Closeable;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.io.IOException;

import java.util.zip.ZipOutputStream;
import java.util.zip.ZipEntry;

public class Main {
    private static void closeQuietly(final Closeable o) {
        try{
            if(o != null) {
                o.close();
            }
        } catch(Exception e){
        }
    }

    public static void main(String[] args) throws IOException {
        System.out.println("hoge");
        System.out.println("java version=" + System.getProperty("java.version"));
        System.out.println("args[0]=" + args[0]);
        System.out.println("args[1]=" + args[1]);
        debugZipArc(args[0], args[1]);
        System.exit(0);
    }

    private static void zipArc(final ZipOutputStream zoStream, final File obj, final String parentDirPath) throws IOException {
        final String currentName =  parentDirPath + obj.getName();
        if(obj.isFile()) {
            FileInputStream fiStream = null;
            try {
                byte buf[] = new byte[4096];
                int len;
                ZipEntry entry = new ZipEntry(currentName);
                fiStream = new FileInputStream(obj);
                zoStream.putNextEntry(entry);
                while((len = fiStream.read(buf)) > 0) {
                    zoStream.write(buf, 0, len);
                }
            } finally {
                closeQuietly(fiStream);
            }
        } else if(obj.isDirectory()) {
            for (File child : obj.listFiles()) {
                zipArc(zoStream, child, currentName + "/");
            }
        }
    }

    private static void debugZipArc(final String inDirPath, final String outFilePath) throws IOException {
        FileOutputStream foStream = null;
        ZipOutputStream zoStream = null;
        try {
            File obj;
            foStream = new FileOutputStream(outFilePath);
            zoStream = new ZipOutputStream(foStream);
            obj = new File(inDirPath);
            zipArc(zoStream, obj, "");
        } finally {
            closeQuietly(zoStream);
            closeQuietly(foStream);
        }
    }
}

補足① JRE6とサロゲート ペア

解凍ツールによっては任意の文字コードでファイル名を展開してくれるものもある。
JRE6ではUTF-8で格納はされている様だけど。?? が化けてしまっている。サロゲート ペアを処理する能力は持ち合わせていないのかな、と思われる。
(JavaVMの問題?)
JRE6のZIPの文字化け.png

補足② UNICODE絵文字の表示能力

手元のマシンによっては、UNICODE絵文字が豆腐になるものもあった。同じWindows10、同じ7zipで豆腐になる、ならないがあり、またWinRARでも同様だった。なので、フォントのインストール状況の差異で表示だけの問題かと思われる。
(調査中)
UNICODE絵文字の豆腐.png

補足③ UNICODE対応

それまでシステム文字コードで処理していたのが、国際対応によってUNICODEに置き換わっているものは、ZIPに限らず色々ある。UNICODE ZIPに対応するということは、それらの歩みと同じであり、国際文字対応に於いて非常に意味のある対応である。

※ 日本語文字も国際文字である。

  • 実行ファイル(ネイテイブ) ⇒ Win20000あたりから、内部文字コードがUNICODE (WCHAR)での処理に対応。
  • 実行ファイル(VM) ⇒ Java、.NET CLRはUNICODE (UCS2)で処理。
  • ID3Tag ⇒ 2.3以降でUNICODEに対応。
  • APE Tag ⇒ APEv2でUNICODEに対応。

UNICODEに対応することでシステム文字コードに関わらず、一意の処理で国際文字を扱うことができる。

感想

Javaが割と真っ当にUNICODE ZIPに対応していたのは驚いた。そのため、それなのに未だにUNICODE ZIPが普及出来ていないのはなぜ?と、更に謎が深まった。りあえずJava 7以降であれば標準機能でUNICODE ZIPが使える様なので、マルチ プラットフォームなZIPユーティリティを作るならJavaが結構良さげに感じた。

また、OS側のZIP圧縮機能でUNICODE ZIPに対応しないのもなぜだろう。恐らくmacの方もwinやjavaなどと同様にシステム文字コードで圧縮しただけの、従来の圧縮してるだけの様子。しかし、そもそも ZIPファイルはmac向けではない 以上、クロス プラットフォームを無視できないはずなのに、macですらもUNICODE ZIPにしないのがホント謎。

最もmacの場合、ZIPファイルにリソース フォークぶっ込んできている段階で、ルール違反感も否めない。ファイル構成を仕様に盛り込んでる段階で、JARやOffice Open XMLみたいに、表向きだけでもZIPを名乗るの辞めたほうが良いじゃないの?とか思ったりしないでもない。

参考

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

未経験がJava Silver 11を取得するためにした学習法

はじめに

エンジニア志望の著者は、就活の過程で著者はスキルも何もなく、現在のコロナ下での就職は難しいとのアドバイスをいただき、ひとつずつ身に着けられるスキルなどをできるところから学んでいこうとの思いで、まずは教えていただいたJava Silverから取得しようと考えました。

そして、つい先日Java Silver 11の資格を取得しましたので、取得までの学習法を共有したいと思います。

結果としては89%(合格正答率63%)で合格できました:relaxed:

対象の方

・様々な理由でJava Silverを取得しようとしている方

そもそもJava SE認定資格とは?

オラクル社が実施しているJavaプログラマ向けの資格です。
レベルとして「Bronze」「Silver」「Gold」があり、各レベルごとに現在のスキルのレベルの証明となります。

レベル 概要
Bronze Java言語を使用したオブジェクト指向プログラミングの基本的な知識を有するレベル
Silver Javaアプリケーション開発に必要とされる基本的なプログラミング知識を有し、上級者の指導の下で開発業務を行うことができるレベル
Gold 設計者の意図を正しく理解して独力で機能実装が行えるスキル

今回はSilverを取得したので、Silverの学習法をメインに取り上げます。

学習環境と学習期間

言語学習 資格学習
期間 約一か月 約一か月
使用参考書 「すっきりわかるJava入門」「独習Java」 「黒本」「紫本」
学習法 「すっきりわかるJava入門」で基本的な部分を理解して、「独習Java」で再理解と補足知識として吸収 解説をよく読み、問題に対して正しい答えへのアプローチの方法を身に着ける。

大まかな学習法は上記のような形になります。

ここから掘り下げて、具体的にどのような学習をしてきたかを見ていきたいと思います。

学習方法

Javaのみならずプログラミングの学習法として重要だと感じているのは「なぜそうなるのか」理解していくことだとかんがえています。

例えば・・・

Main.java
public class Main {
  String str; // null

  public static void main(String[] args) {
    Main m = new Main();
    System.out.println(m.str); // null が出力される
  }
}

Another.java
public class Another {
  String str; // null

  public static void main(String[] args) {
    Main m = new Main();
    System.out.println(m.str.length()); // 実行時エラーになる(NullPointerException)
  }
}

上記のような二つのファイルがあります。

String型のstrには初期値としてnullを持っているのはどちらとも共通です。

二つのファイル間での相違点は以下の通りです。
・Main.javaではメンバ変数strの値を呼び出している。
・Another.javaではメンバ変数strの値の文字数をメソッドを使って呼び出している。

詳しくはここでは書きませんが、nullを持つ参照型変数にメソッドを使用するとNullPointerExceptionという例外が発生します。

なので、Another.javaではnullをもつstrに文字数を確認する.length()メソッドを使用しているため例外が発生します。

このようにプログラミング言語には「なぜそうなるのか」ということがたくさんあります。
「なぜ」→「○○という理由でこうなる」→「だからこのような結果になる!」という感じで理解していくと定着率も格段に上がりますし、理解度も増していきます。

Javaの学習方法もこのようにしていくと間違いないですし、これに尽きます。

学習を進めていく際は最初はわからなくてもいいのでこれを意識してみてください。

資格参考書の模試

上記の方法で学習し、ある程度理解できて来たら、模試で腕試しです。
著者は黒本、紫本の各章の問題を2周、それぞれ2回分の模試がついているので計4回分の模試をそれぞれ2周しました。

基準正答率はJava Silverでは63%(80問中50問の正答率)です。
計4回の模試で正答率平均が約72%(80問中58問の正答率)あれば問題ないかなと感じています。

復習の比率的には模試の内容に関しては黒本の模試:紫本の模試 = 7 : 3
解説の内容に関しては黒本の解説:紫本の解説 = 5 : 5で再確認していくのがおすすめです。

注意すべきなのは、あくまでも基準正答率を超えなくてはならないので、凡ミスなどは好ましくありません。
問題へのアプローチもしっかり対策していきましょう。

重要問題部分

Java Silverを学習するにあたって、著者が特に気を付けた部分をいくつかご紹介します。

  • データ型(プリミティブ型、参照型)、型変換、var変数
  • 多次元配列
  • 継承、ポリモーフィズムによる挙動
  • コンパイルエラーと実行時エラーとの違いと例外処理
  • オーバーライドとオーバーロード
  • アクセス修飾子とfinal修飾子
  • nullリテラルの扱い方
  • スコープ

他にも重要な部分はありますが、主に気を付けた部分を挙げました。
参考にしてみてください!

まとめ

これからSilverの資格取得を目指している方の参考になれば幸いです。

受験料がけっこうお高いので、確実に取得しに行きましょう!

ご意見、ご質問等があればこちらまでお願いします。

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

Springで自作Validation

背景

Formにアノテーションをつける以外(二重チェック等)のバリデーションの方法をメモしておきます。今回はBean ValidationではなくSpring Validatorを使用します。

方法

SessionForm
public class SessionForm {

    private CheckForm checkForm;
    //エラー出力用変数
    private String error1;

    private String error2;
    //セッター等省略

CheckValidation
@Component
                             //インターフェース実装
public class CheckValidation implements Validator {
    //Checkにヘルパーを使う場合は注入
    @Autowired
    Helper helper;

    @Override
    public boolean supports(Class<?> clazz) {
        //チェックしたいFormを入れる(セッションアトリビュートしたクラス)
        //isAssignableFromは継承したクラスもすべて
        return SessionForm.class.isAssignableFrom(clazz);
    }

    @Override
    public void validate(Object target, Errors errors) {
        //対象クラスをいったん作成
        SessionForm form = (SessionForm) target;
        //form.checkForm.~とすることで入れ子の要素も使用可能
        if (条件式) {
                errors.rejectValue(
                       //フォームに指定した変数
                       "error1",
                       //別のファイルにメッセージ定義してない場合Null
                        null, 
                       "出力したいメッセージ");
            }

        //別のチェックをする
        if (条件式) {
                errors.rejectValue(
                        "error2", 
                         null, 
                        "出力したいメッセージ");
                }
}


Controller
@Controller
@SessionAttributes(names = "sessionForm")
public class ExampleController {
    //Key設定用
    private static final String FORM_NAME = "sessionForm";

    //自作バリデーションクラスをインジェクション
    @Autowired
    CheckValidation checkValidation;

    //WebDataBinderに追加
    @InitBinder("sessionForm")
    public void initBinder(WebDataBinder binder) {
        binder.addValidators(checkValidation);
    }

    //メソッドにつけるモデアトは呼び出し前にモデルに場所を追加してくれる
    @ModelAttribute(value = "sessionForm")
    public SessionForm sessionForm() {
        return new SessionForm();
    }

//a
@RequestMapping(path="リダイレクトに入れたパス", method=RequestMethod.GET)
    public String putInformation(@ModelAttribute(FORM_NAME) SessionForm session, BindingResult result,ModelMap model) {

        String key = BindingResult.MODEL_KEY_PREFIX + FORM_NAME;
        //リダイレクト時にモデルにエラーがあれば
        if(model.containsKey("errors")) {
            //Keyに設定したフォームにマップ形式でエラー格納
            model.addAttribute(key, model.get("errors"));
            model.addAttribute("sessionForm" , session);
            return "遷移したいJSP等";
        }
        //他省略
}

//b
@RequestMapping(path="入力確認画面等", method=RequestMethod.POST)
    public String confirmInfomation(@Validated SessionForm session, BindingResult result, Model model, RedirectAttributes ra)throws Exception {

            if(result.hasErrors()) {
            ra.addFlashAttribute("errors", result);
            //入力画面へリダイレクト
            return "redirect:/{呼び出したいコントローラのパスへ}";
        }
        //他省略
}
JSP
<form:errors path="error1" />
<form:errors path="error2" />

メモ

・まず全部盛りのフォームにエラー用変数作成。
・バリデータクラスでその変数に情報格納。
・コントローラでWebDataBinderにバリデータを追加することによりBeanValidation呼び 出し後に追加したバリデータが呼び出され自作のチェックが行われる。Autowiredも忘れない。
・BindingResultにエラーがあればその情報を保持したままリダイレクト(入力の確認画面へ遷移する前の部分等でチェック)。メソッドの流れはa→b→aの順。
・リダイレクト先のメソッドでエラーの有無で分岐し、あればエラー情報をモデルに格納しJSPと共有する。
・JSPでformタグのerrorsを使用し、パスとセッション用フォームの変数を一致させエラーメッセージを出力。

まとめ

今回、試行錯誤しながら作成したのでもっと良いやり方があるとは思いますが、一応動きはしたのでメモしておきます。バリデータのクラスでDBから持ってきた情報(日付等)との比較とかもできたのでバリデータは結構自由度が高いのかなと思いました。もしSpring以外でバリデータを実装する場合はフィルターとか使って条件書くのかと思いました。

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

VPSにWebApplicationServer(Java)を構築する

Serverのお勉強のためにWebServerを構築し、JavaApplicationを実行するところまでやってみた。

目次

  1. 動作環境
  2. やること
  3. 構築手順
  4. 参考サイト

1. 動作環境

  • Cent OS7

2. やること

調べたところ、以下をすれば、とりあえず動かすことはできるみたい。

  • Javaの実行環境構築
  • サーブレットコンテナの準備
  • WebServerの構築
  • Javaアプリケーションの配置

3. 構築手順

Javaの実行環境構築

サーバー上でJava実行を実行するために、JDKをインストールする。
以下のサイトが分かりやすかった。
■参考: CentOS 7 に Tomcat 9 を入れてみた

サーバーで以下のコマンドを実行してインストール(JDK8)。

# yum install java-1.8.0-openjdk-devel.x86_64

(他のJDKを検索したい場合は、以下コマンドを実行。)

# yum search openjdk

インストールされていることを以下コマンドで確認。

# java -version

以下のような出力が出ればOK。

openjdk version "1.8.0_252"
OpenJDK Runtime Environment (build 1.8.0_252-b09)
OpenJDK 64-Bit Server VM (build 25.252-b09, mixed mode)

サーブレットコンテナの準備

Javaサーブレット(サーバー上で動作するJavaプログラム)を動かすために、サーブレットコンテナであるtomcatをインストールする。tomcatってよく聞くけど、よくわからないまま使ってました・・・
まず、Tomcat を動かすためのユーザーを追加(ユーザー名:tomcat)。

# useradd -s /sbin/nologin tomcat

※ /sbin/nologin はログインできないユーザーを意味するらしい。ここで作ったユーザー「tomcat」は、サービス起動用のスクリプト?(systemd)で使うだけなので、ログインできる必要がないっぽい。

■参考:ログインできないユーザでコマンドを実行する方法+おまけ

次に、Tomcatのインストールのため、ファイルをサーバーにダウンロード。

# curl -O https://ftp.jaist.ac.jp/pub/apache/tomcat/tomcat-9/v9.0.37/bin/apache-tomcat-9.0.37.tar.gz

※ 「https://ftp.jaist.ac.jp/pub/apache/tomcat/tomcat-9/v9.0.37/bin/apache-tomcat-9.0.37.tar.gz」の部分は変わる可能性あり。以下で確認。
tomcatのダウンロードサイト

ダウンロードしたファイルを以下コマンドで解凍。

# tar -xzvf apache-tomcat-9.0.37.tar.gz

以下コマンドで/usr/local/tomcat に移動。

# mv apache-tomcat-9.0.37 /usr/local/tomcat

以下コマンドでユーザー所有者:グループ所有者を先ほど作成したユーザー「tomcat」に変更

# chown -R tomcat:tomcat /usr/local/tomcat

Tomcatをサーバーが実行可能なサービスとして認識させるため、以下のコマンドでsystemd unit ファイルを作成する。
※ CentOS7からsystemd というので、サービスを管理しているらしい。

■参考:これからSystemd入門する

# vi /etc/systemd/system/tomcat.service

作成したファイルに以下の内容を記載し、保存。
正直、内容はよくわかってない。こういうサービスを作るよ、ってことを宣言してるという理解。

[Unit]
Description=Apache Tomcat 9
After=syslog.target network.target

[Service]
User=tomcat
Group=tomcat
Type=oneshot
PIDFile=/usr/local/tomcat/tomcat.pid
RemainAfterExit=yes

ExecStart=/usr/local/tomcat/bin/startup.sh
ExecStop=/usr/local/tomcat/bin/shutdown.sh
ExecReStart=/usr/local/tomcat/bin/shutdown.sh;/usr/local/tomcat/bin/startup.sh

[Install]
WantedBy=multi-user.target

さらに、作成したファイルの読み込み権限・書き込み権限・実行権限を設定する

# chmod 755 /etc/systemd/system/tomcat.service

※「所有者:読み込み・書き込み・実行可能」「所有グループ:読み込み・実行可能」「それ以外(他人):読み込み・実行可能」を設定している

■参考:【 chmod 】コマンド――ファイル/ディレクトリのパーミッション(許可属性)を変更する

自動起動設定をし、サービスを有効にする

# systemctl enable tomcat
Created symlink from /etc/systemd/system/multi-user.target.wants/tomcat.service to /etc/systemd/system/tomcat.service.
# systemctl start tomcat

Tomcatを起動する。

以下のURLにアクセスし、tomcatデフォルトの画面が出たらOK。

http://サーバーのIPアドレス:8080/

スクリーンショット 2020-07-25 18.18.47.png

WebServerの構築

本来ならApatch HTTPサーバーを導入するのが良いみたいだが、
TomcatにもWebServerの機能があるようなので、それを使用する(ため、特にインストールしない)。
じゃあ、そもそもApatch HttpServerなんでいらないのでは、と思ったが、tomcatのWebサーバーはおまけみたいなものらしく、パフォーマンスとか考えると、あったほうが良いらしい。

■参考:【社内勉強会】ApacheとTomcat(2017/03/09)

Javaアプリケーションの配置

javaアプリケーションはインストールしたTomcat直下のwebapps(/usr/local/tomcat/webapps/)に配置すれば良いらしい。
この辺も普段意識してないので、よくわからなかった。
以下のサイトがとても分かりやすかった。

■参考:TomcatでHelloWorld

とりあえず、以下のコマンドでプロジェクトフォルダを作成

# mkdir /usr/local/tomcat/webapps/javaproject

あとはclassファイルとweb.xmlを作成する。
以下のコマンドで、classesディレクトリを作成。

# mkdir /usr/local/tomcat/webapps/javaproject/WEB-INF/classes

以下のコマンドで、javaソースファイルを作成。

# vi /usr/local/tomcat/webapps/javaproject/WEB-INF/classes/HelloWorld.java

以下の通り編集して保存する。

HelloWorld.java
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

public class HelloWorld extends HttpServlet {
    public void doGet(HttpServletRequest request,
    HttpServletResponse response) throws IOException, ServletException {
        PrintWriter out = response.getWriter();
        out.println("<html>");
        out.println("HelloWorld");
        out.println("</html>");
        out.close();
    }    
}

以下のコマンドでコンパイルする。

# cd /usr/local/tomcat/webapps/javaproject/WEB-INF/classes/
# javac -classpath /usr/local/tomcat/lib/servlet-api.jar HelloWorld.java 

同じディレクトリにHelloWorld.classができてたらOK。
あとはweb.xmlを作成して、URLとservletの紐付けする。
以下のコマンドで、web.xmlを作成。

# vi /usr/local/tomcat/webapps/javaproject/WEB-INF/web.xml

以下の通り編集して保存する

web.xml
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">

<web-app>
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>HelloWorld</servlet-class>
</servlet>

<servlet-mapping>
<servlet-name>
hello
</servlet-name>
<url-pattern>
/servlet/hello
</url-pattern>
</servlet-mapping>

</web-app>

やっと終わりに近づいてきた。ハマりまくったので長かった・・・
以下のコマンドでtomcatを再起動します。

# systemctl restart tomcat

以下のURLにアクセスして、HelloWorldが表示されるとOKです!

http://サーバーのIPアドレス:8080/javaproject/servlet/hello
スクリーンショット 2020-07-25 22.32.50.png

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

Java HelloWorld

1. ファイルを作成

コード 内容
System.out.println() メッセージをコンソールに出力し、新しい行を折り返します
System.out.print() メッセージをコンソールに出力しますが、改行しません
\t tabタブスペース
main(String[] args) プログラムのエントリポイント
HelloWorld.java
public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello Word");
        System.out.print("良いスタート\t");
        System.out.print("は成功の半分です。");
    }
}

2.コンパイル

javc HelloWorld.java

3.実行

実行結果
$ java HelloWorld
Hello Word
良いスタート     は成功の半分です。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

JavaでJsonをPOSTする〜HttpURLConnection〜

概要

JavaでJSONをHTTP POSTする方法をまとめた記事です

必要最低限の書き方のみまとめています。

前提

簡略化のため、JSON形式の文字列を用意しました。
JSONをjavaに変換する方法などは他の記事を参考にして下さい。

呼び出し元がこのクラスをインスタンス化し、execute()メソッドを呼び出すことを想定しています。

手順

手順は以下の通りです
1.HttpURLConnectionで接続するための設定をする
2.接続を確立する
3.リクエスとボディに書き込みを行う
4.レスポンスを受け取る
5.接続を切断する

JavaでHTTP通信する方法

Sample.java
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.HttpURLConnection;
import java.net.URL;


public class Sample {

    private HttpURLConnection conn;
    private URL url;

    private  String  URL ="https://XXX.YY-ZZZZ.com/WWW/";

    private String json =
        "{" +
            " \"searchCondition\": {" +
            " \"conditions\": [" +
                "{" +
                    " \"conditionType\": \"Name\","+
                    " \"Value\": 200," +
                " }"+
            "]" +
        "}," +
        "\"outputMethod\": \"split\","+
        "\"zipFileName\": \"DDD.zip\"" +
    "}";

    private String result;

    Sample() throws IOException{

        //1.接続するための設定をする

        // URL に対して openConnection メソッドを呼び出すし、接続オブジェクトを生成
        url = new URL(URL);
        conn = (HttpURLConnection) url.openConnection();

        // HttpURLConnectionの各種設定
        //HTTPのメソッドをPOSTに設定
        conn.setRequestMethod("POST");
        //リクエストのボディ送信を許可
        conn.setDoInput(true);
        //レスポンスのボディ受信を許可
        conn.setDoOutput(true);
        //Json形式を指定
        conn.setRequestProperty("Content-Type", "application/json; charset=utf-8");

        // 2.接続を確立する
        conn.connect();
    }

    public String execute() throws IOException{

        // 3.リクエスとボディに書き込みを行う
        //HttpURLConnectionからOutputStreamを取得し、json文字列を書き込む
        PrintStream ps = new PrintStream(conn.getOutputStream());
        ps.print(json);
        ps.close();


        // 4.レスポンスを受け取る
        //正常終了時はHttpStatusCode 200が返ってくる
        if (conn.getResponseCode() != 200) {
            //エラー処理
        }

        //HttpURLConnectionからInputStreamを取得し、読み出す
        BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));

        StringBuilder sb = new StringBuilder();
        String line;

        while ((line = br.readLine()) != null) {
            sb.append(line);
        }
        result = sb.toString();

        // 5.接続を切断する
        conn.disconnect();

        //結果は呼び出し元に返しておく
        return result;
    }
}

参考

HtppURLConnectionの設定には以下のようなメソッドを使用します。詳しくは公式リファレンスなどを参考にして下さい
セットアップパラメータを修正するには次のメソッドを使用します。
・setAllowUserInteraction
・setDoInput
・setDoOutput
・setIfModifiedSince
・setUseCaches
一般要求プロパティーを修正するには次のメソッドを使用します。
・setRequestProperty

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

書籍紹介:Spring Boot 初心者におすすめの参考書!

※記事の内容は2020年7月25日執筆時点のものです

書籍情報

今日はSpring Boot初心者におすすめの書籍を紹介したいと思います。
私自身も業務でSpring Bootを初めて使う際に大変お世話になりました。
それが↓↓こちら↓↓の書籍です。

「【後悔しないための入門書】Spring解体新書」田村達也 (著)

これからこの書籍のおすすめポイントをいくつかご紹介したいと思います。

おすすめ読者像

 この書籍はJavaでのオブジェクト指向プログラミングなど基本は理解しているけれど、Spring Bootなどを使ったフレームワーク開発は未経験という方におすすめです。
 また、時間のない方、まずはSpringについてざっくりと概要を知りたい方にもおすすめです。逆に、Springについて深く理解したい方には物足りないかもしれません。

おすすめポイント

1.表現が平易かつサンプルコードが豊富で読みやすい

 実はこの書籍の他にも何冊かSpringの関連書籍を読んだのですが、内容や言い回しが難解だったり、それぞれの機能の使い所がいまいち頭に入ってこないものがありました。その点この書籍はアプリを作る流れに沿って説明をしているので、小説を読むような感覚でサクサクと読み進めることができました。
 また、サンプルコードについては該当する箇所だけでなく、クラス宣言や前後のコードを含めて掲載してくれているほか、トピックとなる箇所には下線を引いてくれています。そのため実装のイメージが湧きやすく、読む際に迷子になることもなくスムーズに理解を深めることができました。

2.Spring初学者にとって最適なボリューム感

 前述の通りアプリを作成する流れに沿って説明しているため、実用的なトピックをハイライトで学ぶことができます。そのためすべての機能を網羅している訳ではないのですが、DI、AOP、Springセキュリティ、SpringJDBCといった主要なトピックを押さえているため、一冊理解すればアプリ開発に必要なSpring Bootの必須知識は一通りインプットできるのではないかと思います。

3.Kindle Unlimitedメンバーなら追加料金なしで読める!しかも電子書籍用レイアウト対応!

 この書籍はkindle版があり、そちらは電子書籍用レイアウトに対応していますので、デバイスに合わせて文字サイズなどのレイアウトが自動調整されます。文字などもくっきり表示され読みやすいです。ハイライトマーカーを引いたり、検索したり、目次ジャンプをすることもできるので学習の記録をしたり辞書的な使い方もできますよ。固定レイアウトだとこれらの機能がつかえず、文字も小さくなりがちで読みづらいんですよね。
 そして嬉しいのがなんとこの書籍、Kindle Unlimitedの対象書籍になっているため、契約をしていれば追加料金なしで読むことができます!ちなみにKindle Unlimitedとは、月額980円で対象の電子書籍が読み放題のサブスクリプションサービスです。技術書の他にも漫画や雑誌も読み放題ですし、一冊技術書を買うよりも安いかと思いますので、ご利用になられたことのない方は一度試してみてはいかがでしょうか。

おわりに

以上のように、Spring Boot学習の一冊目にはうってつけかと思いますのでぜひ試してみてくださいね。最後まで読んでいただきありがとうございました。

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

月度を用いて範囲の判定をしたい

問題点

月度のデータをもっているときに9月以前で取得したいが、
1,2,3月は次の年のデータなので含めたくないということがあると思います。
そのときに簡易的に取り除く方法の例をメモします。

どうやるか

以下のように比較するそれぞれの月度を変換して、
変換後の値を用いて判定することで解決できます。

(月度 + 8) % 12

例えば、9月度以前のデータを取得する際は、
取得元データの月度変換値<=基準となる月度変換値とすることで、
4,5,6,7,8,9月だけが取得できるようになります。
なぜなら変換後の値が以下のようになるためです。
9月の変換後の値は「5」なので、その値以下である4~9月が取得できます。

月度 変換後の値
1 9
2 10
3 11
4 0
5 1
6 2
7 3
8 4
9 5
10 6
11 7
12 8
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

「言語仕様上そんなこと出来るんだ」から始めるデザインパターン

始めに

GoFのデザインパターンについて,様々な方が記事にされており,私もいつも勉強させて頂いております.しかし一方で,それらの記事は「こうクラス設計をすることでこんなメリットがあります」,「従来のやり方はこういった問題があります」といったハイレベルな方を対象とした,前提をある程度共有できる方に向けた記事のような印象を受け,そもそも私のような初学者が分からない「言語仕様上,こんな書き方が出来ます」,「この様にクラス設計をすると,プログラムはこう動きます」といったような,「まず何が出来るのか」についてフォーカスしている記事は見当たらないような気がします.

そこで,今回私はJava言語で学ぶデザインパターンを題材に,まず「Javaは言語仕様上,こんなことが出来ます」という観点から,デザインパターンを見ていこうと思います.

話が逸れるかもしれませんが,ここで扱う題材は基本的にはJavaのため,他言語では既に仕様として出来るもの(例えばPythonの__iter__ など)や,逆に他言語では出来ないor出来るにしてもかなり凝った書き方をしないと出来ないもの(例えばc++の依存性注入など?)も例に挙げます.そう考えると,もはや言語共通のデザインパターンなんてものは存在せず,各言語それぞれのデザインパターンがあるのかもしれません.ただ,自分はそんなに様々なプログラムに詳しいわけではなく,かつ他言語のデザインパターンについて議論できるほどスキルがある訳でもないので,この記事では深くは突っ込まず,あくまで「Javaの言語仕様上,こんなことが出来ます」の紹介に留めておこうと思います.
それでは前置きが長くなりましたが,始めていきます.

基礎知識① 変数の種類について

GoFのデザインパターンで扱われている変数は大きく分けると以下の3種類かなあと.また,それぞれのメリット・デメリットは以下であると思われます.
|変数|使われ方|メリット|デメリット|
|---|---|---|---|
|自作クラス|8|8|8|
|公式クラス or 基本型(double,strなど)|8|8|8|
|整数型(int,bool)など|8|8|8|

a b c 2
1 2 3 3
4 5 6 3

基礎知識② 変数の扱い方について

あるメソッド内で変数を扱うには以下の4種類の方法があります.それぞれ扱える範囲と,扱う際の注意点を記載します.注意点に関しては記事の本題から外れる様な気もしますが,一方で特徴を把握しておかないとデザインパターンのメリットも見えてこない気がするので一応載せておきます.

変数の種類 扱える範囲 注意点
ローカル変数 メソッド内 最も推奨されるべき使い方ですが,一方で大きいクラスを毎回newで動的確保すると計算コストが大きくなることもあるのでパフォーマンスとも相談しましょう
メンバ変数 個々インスタンス内(staticをつければ全クラス共有) 言ってしまえばアクセスが限定されるだけのグローバル変数なので,むやみに作成しないように.カウンタ変数の使い回しなんかは絶対ダメ
引数 関数の利用側 なるべく関数内で状態が変更されることはないようにしましょう(付けられるならばconst修飾子を付ける).また,複数ステータスを持つような大きなクラスはなるべくやめましょう.
戻り値 関数の利用側 引数と同じく,あまり大きなクラスで返さないように.

変数の修飾子

そんなことが出来るんだ① 継承を使ったメソッドの動的切り替え

hoge

それは出来ないんだ① 子クラスのメソッドの親クラスからの呼び出し

以降作成途中

すみません,下書きで作成途中のものを,操作ミスで途中で投稿してしまいました.調べたところ一度投稿したものを再度下書きには出来ないそうなので,なるべく早く記事を完成させます.
それまでは皆様にはお目汚しとなってしまいますが,何卒よろしくお願いします.

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

SpringBoot アプリケーションをAWSEC2へデプロイ

Gradleを用いてSpringBootアプリケーションを作成しました。
これをAWS EC2へデプロイする手順について書きました。

実行可能jarを作成

gradleのbootJarタスクで実行可能jarをつくる
参考:https://docs.spring.io/spring-boot/docs/2.1.1.RELEASE/gradle-plugin/reference/html/#packaging-executable-and-normal

build.gradle
bootJar {
    launchScript()
}

その後コマンドラインで

$ gradle bootJar

実行すると ./build/libs/にjarファイルが作成される

このjarファイルをEC2へ転送

今回作成されたjarファイル名はWebToDoStarter-0.0.1-SNAPSHOT.jarとし、Desktopに置かれているとする

sftpを用いてこのファイルをEC2へ転送

$ sftp -i AWSキーのパス ec2-user@ IPv4パブリックIP

sftp> put Desktop/WebToDoStarter-0.0.1-SNAPSHOT.jar
Uploading Desktop/WebToDoStarter-0.0.1-SNAPSHOT.jar to /home/ec2-user/WebToDoStarter-0.0.1-SNAPSHOT.jar
Desktop/WebToDoStarter-0.0.1-SNAPSHOT.jar                                           100%   20MB   1.2MB/s   00:17   

sshでEC2へアクセス

$ ssh -i AWSキーのパス ec2-user@ IPv4パブリックIP

ファイルが転送されているか確認

$ ls
WebToDoStarter-0.0.1-SNAPSHOT.jar

あるね

JDKのインストール

試しにjava8インストールしてみる

$ sudo yum install java-1.8.0-openjdk-devel.x86_64
$ java -jar WebToDoStarter-0.0.1-SNAPSHOT.jar
Exception in thread "main" java.lang.UnsupportedClassVersionError: com/example/demo/WebToDoApplication has been compiled by a more recent version of the Java Runtime (class file version 55.0), this version of the Java Runtime only recognizes class file versions up to 52.0
    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:757)
    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
    at java.net.URLClassLoader.defineClass(URLClassLoader.java:468)
    at java.net.URLClassLoader.access$100(URLClassLoader.java:74)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:369)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:363)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:362)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:419)
    at org.springframework.boot.loader.LaunchedURLClassLoader.loadClass(LaunchedURLClassLoader.java:93)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:352)
    at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:46)
    at org.springframework.boot.loader.Launcher.launch(Launcher.java:87)
    at org.springframework.boot.loader.Launcher.launch(Launcher.java:50)
    at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:51)

エラーだ、どうやらjava8ではバージョンが古いようだ

クラスファイルのバージョンとJREのバージョン

クラスファイルのバージョン JREバージョン
49 Java 5
50 Java 6
51 Java 7
52 Java 8
53 Java 9
54 Java 10
55 Java 11
56 Java 12
57 Java 13
58 Java 14

Java 8より高いバージョンのJDKを探す

$ sudo yum search java
============================================================================ N/S matched: java =============================================================================
〜省略〜
java-1.8.0-openjdk-devel.x86_64 : OpenJDK Development Environment 8
〜省略〜
java-11-amazon-corretto.x86_64 : Amazon Corretto development environment

java-11-amazon-correttoならjava11まで使える

java-11-amazon-correttoのインストール

$ sudo yum install -y java-11-amazon-corretto.x86_64

インストールしただけではダメ

バージョンを切り替える

$ sudo alternatives --config java

2 プログラムがあり 'java' を提供します。

 選択         コマンド

*+ 1       java-1.8.0-openjdk.x86_64 (/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.242.b08-0.amzn2.0.1.x86_64/jre/bin/java)
   2         /usr/lib/jvm/java-11-amazon-corretto.x86_64/bin/java

Enter を押して現在の選択 [+] を保持するか、選択番号を入力します:2   
$ java --version
openjdk 11.0.7 2020-04-14 LTS
OpenJDK Runtime Environment Corretto-11.0.7.10.1 (build 11.0.7+10-LTS)
OpenJDK 64-Bit Server VM Corretto-11.0.7.10.1 (build 11.0.7+10-LTS, mixed mode)

これで実行できる

Java Servletを実行するためのサーブレットコンテナであるTomcatは今回インストールする必要がない。
組み込みTomcatで実行可能なjarファイルでデプロイしているためである。

$ java -jar WebToDoStarter-0.0.1-SNAPSHOT.jar

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.1.1.RELEASE)

ちなみにアプリケーションのport番号を変更するには

application.yml
server:
  port: 8081

を追加

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