20210612のJavaに関する記事は7件です。

【Jackson】共通のunboxするシリアライズ処理を実装する

TL;DR 当該の抽象型向けのStdSerializerを定義し、適切に登録することで実現できる 中身の型ごとのシリアライズは、SerializerProvider::findValueSerializerで取得したシリアライザーで行える やること 以下のような、値をラップする抽象型が有るとします。 用途としては、DDDでいう値オブジェクトを定義する時、共通の振る舞いを持たせるために基底となる型を作る場合を想定しています。 package com.wrongwrong.values; public abstract class AbstractValue<T extends Comparable<T>> { public abstract T getValue(); } このクラスは、以下のように継承されて使われます。 intでの継承例 package com.wrongwrong.values; public class Foo extends AbstractValue<Integer> { private final int value; public Foo(int value) { this.value = value; } @Override public Integer getValue() { return value; } } この型をfooというフィールドに設定した場合、そのままJSONにシリアライズした結果は以下のようになります。 { "foo": { "value": 10 } } 一方、この型はあくまでサーバーサイドの都合でラップするためのものであるため、フロントへ渡すシリアライズ結果は以下のようにunboxされた形になっている方が望ましいです。 { "foo": 10 } このunboxするシリアライズ処理は、個別に書くと大変で、かといってAbstractValue側にJsonValueアノテーションを設定するのも不適切です1。 そこで、Jacksonを用いて共通のunboxするシリアライズ処理を実装します。 やり方 ここではAbstractValueをシリアライズするStdSerializerを実装し、SimpleModuleを介してObjectMapperに登録する方法を紹介します。 シリアライザーの実装 シリアライザーの実装は以下の通りです。 package com.wrongwrong.ser; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.ser.std.StdSerializer; import com.wrongwrong.values.AbstractValue; import java.io.IOException; public class AbstractValueSerializer extends StdSerializer<AbstractValue<?>> { public AbstractValueSerializer() { // AbstractValueがジェネリクスを持つ関係で、dummyフラグを設定する必要が有る super(AbstractValue.class, true); } @Override public void serialize(AbstractValue<?> value, JsonGenerator gen, SerializerProvider provider) throws IOException { Object unboxed = value.getValue(); if (unboxed == null) { gen.writeNull(); } else { // findValueSerializerは必ず何かしらのシリアライザーを返す JsonSerializer<Object> serializer = provider.findValueSerializer(unboxed.getClass()); serializer.serialize(unboxed, gen, provider); } } } 注意点 Java上の値からJSONへシリアライズする時には、以下のように様々なロジックが絡みます。 文字列は"で囲む 数字・booleanなどは"で囲まない オブジェクトはその型ごとにシリアライズ方法を取る必要が有る e.g. JsonValueアノテーションが設定されている場合 今回のサンプルで取り上げているAbstractValueはComparableなら何でも設定可能なため、これらのロジックを考慮する必要が有ります。 これを行っているのが以下の2行です。 JsonSerializer<Object> serializer = provider.findValueSerializer(unboxed.getClass()); serializer.serialize(unboxed, gen, provider); シリアライザーの登録 シリアライザーの登録は以下のように行います。 import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.module.SimpleModule; import com.wrongwrong.values.AbstractValue; /* classなどは省略 */ SimpleModule module = new SimpleModule(); JsonSerializer<AbstractValue<?>> serializer = new AbstractValueSerializer(); module.addSerializer(serializer); ObjectMapper mapper = new ObjectMapper(); mapper.registerModule(module); 実際の環境では、恐らく1インスタンスのObjectMapperが使い回されているため、そこにコンフィグ等でModuleを登録する形になると思います。 Springでは、WebMvcConfig辺りで設定することができます。 動かしてみる 最後に、実際に動かした様子を紹介します。 型ごとに適切なシリアライズが行われていることが分かります。 シリアライズ対象のフィールドとなるクラス 中身はint package com.wrongwrong.values; public class Foo extends AbstractValue<Integer> { private final int value; public Foo(int value) { this.value = value; } @Override public Integer getValue() { return value; } } 中身はString public class Bar extends AbstractValue<String> { private final String value; public Bar(String value) { this.value = value; } @Override public String getValue() { return value; } } 中身はObject package com.wrongwrong.values; import lombok.Data; public class Baz extends AbstractValue<Baz.InnerObject> { @Data public static class InnerObject implements Comparable<InnerObject> { private final int f1; private final String f2; public InnerObject(int f1, String f2) { this.f1 = f1; this.f2 = f2; } @Override public int compareTo(InnerObject o) { int temp = Integer.compare(f1, o.f1); return temp == 0 ? f2.compareTo(o.f2) : temp; } } private final InnerObject value; public Baz(InnerObject value) { this.value = value; } @Override public InnerObject getValue() { return value; } } シリアライズ対象クラス package com.wrongwrong; import com.wrongwrong.values.Bar; import com.wrongwrong.values.Baz; import com.wrongwrong.values.Foo; import lombok.Data; @Data public class Pojo { private Foo foo; private Bar bar; private Baz baz; public static Pojo generateSample() { Pojo pojo = new Pojo(); pojo.foo = new Foo(5); pojo.bar = new Bar("bar"); pojo.baz = new Baz(new Baz.InnerObject(10, "f2")); return pojo; } } テストコード package com.wrongwrong.ser; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.module.SimpleModule; import com.wrongwrong.Pojo; import com.wrongwrong.values.AbstractValue; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; public class SerializerTest { @Test void test() throws JsonProcessingException { SimpleModule module = new SimpleModule(); JsonSerializer<AbstractValue<?>> serializer = new AbstractValueSerializer(); module.addSerializer(serializer); ObjectMapper mapper = new ObjectMapper(); mapper.registerModule(module); // -> {"foo":5,"bar":"bar","baz":{"f1":10,"f2":"f2"}} assertEquals( "{\"foo\":5,\"bar\":\"bar\",\"baz\":{\"f1\":10,\"f2\":\"f2\"}}", mapper.writeValueAsString(Pojo.generateSample()) ); } } AbstractValueに表示用ロジックが入ってしまうのは責務が漏れていると言えるため。 ↩
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Javaでグラフを描く(72要素をチャートにする)

今回の作業履歴 https://github.com/jamcookjapan/grapy/commit/23856753ab76f3722cfd9333d5f6452fe518d491 少しずつグラフをブラッシュアップしたことと、折線グラフの説明を表示可能にしました。また30要素固定表示していたものを、入力によってX軸を動かします。 試しにフジシールインターナショナルさんの4/1〜6/11までの始値と終値をグラフにしてみましたが、X軸のラベル間隔が気になりなることとY軸が微妙にズレて描画しているように思います。肝心の株価推移ですがしばらく下落基調だったものが少し上向きになってきました。そのうちX0日平均株価線も実装しようかと思っています。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

新入社員研修用にWebアプリを作ろうとしているお話【Spring Bootでページを作る話】

前回の続き。 今回はとりあえず実装したじゃんけんの画面を実装してみる。 参考文献 今回は下記の書籍を参考にして画面を実装した。 あまりに単純すぎたか、現状では最初の数十ページしか参考にしていない。 WebGUIの実装に向けて とりあえず、現時点ですべきことを列挙してみる。 今はデータベースは使っていないので、こんな感じだろう。 WebGUIの(現時点での)ToDoリスト じゃんけんを行う画面の実装 じゃんけん前の画面の実装 勝敗を表示する画面の実装 じゃんけんを行う画面の実装 書き忘れていたが、このプロジェクトはWindows上で、Eclipse IDEにSpling tools4をインストールした環境で開発している。 他の開発環境やOSであれば適宜読み替えてほしい。 なお、面倒だったから英語のトラブルシューティングにあたっても大丈夫なように日本語化はしていない。 プロジェクトの設定 まずは現時点で必要なspring bootの設定を列挙してみよう。 Spring web webページを表示するために必要 Thymeleaf じゃんけんの結果を表示するために、値をページに紐付ける必要がある どうやらspring bootで一度プロジェクトを作ってしまえば後で設定を変えることができるみたいなので、 プロジェクトを右クリックしてから下記のスクリーンショットのように選択して、上記のライブラリを追加した。 HTMLの実装 まずはHTMLの実装……の前に、プロジェクト全体のエンコーディングをUTF-8に変更しておこう。 Thymeleafを使用し、HTMLを書き換えるのに使うエンコーディングはUTF-8のようなので、 動作確認の時点で慌ててエンコーディングを変更する羽目になる(なった)。 プロジェクトを右クリック、もしくはAlt+Enterでプロパティを表示し、テキストファイルのエンコーディングをUTF-8を指定しよう。 そしてsrc/main/resources/templatesの直下に次のようなHTMLを持つindex.htmlを作った。 index.html <!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"></meta> <title>練習用じゃんけんアプリケーション</title> </head> <body> <h1>じゃんけんしましょう</h1> 下記の3つのボタンからどれか選んでね。 <hr> <table><td> <form method="post" action="/result"> <input type="hidden" name="hand" value="1"> <input type="submit" value="グーを出す"> </form></td><td> <form method="post" action="/result"> <input type="hidden" name="hand" value="2"> <input type="submit" value="チョキを出す"> </form></td><td> <form method="post" action="/result"> <input type="hidden" name="hand" value="3"> <input type="submit" value="パーを出す"> </form></td></table> </body> </html> 全部のボタンは同じコードを実行するけど、「hidden」を持つインプットフォームにじゃんけんの手のデータをもたせる事により、 プレイヤーの手を認識できるようにしてある。 このボタンを押した先のhtmlもstart/result.htmlに実装する。 参考文献をもとにページを作っているため、若干フォルダの切り方がおかしくなっている気もするが気にしないでおく。 result.html <!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"></meta> <title>練習用じゃんけんアプリケーション</title> </head> <body> <h1>じゃんけんぽん</h1> <hr> あなたの手は<div th:text="${player}"></div>、コンピュータの手は<div th:text="${cpu}"></div> <p> 結果は<div th:text="${result}"></div>です。 </p> <hr> <a href="./start">もう一回行う</a> </body> </html> コントローラの実装 画面は実装できたから、それを制御するコードを実装する。 適当にクラス名はJankenControllerとしよう。 そして「依存性の注入」とやらでJankenModelを紐付け……する必要が無いなこれ。JankenModelのインスタンスを結果画面以外で使わないな。 勝敗履歴の表示や蓄積もページを跨いでインスタンスを持っておく必要がまったくないから、そのような機能は次の課題にしておくか。 ということで、各画面ごとの処理を実装したのがこちら。 JankenController.java package personal.mickie.janken; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestParam; import personal.mickie.janken.Model.JankenHands; import personal.mickie.janken.Model.JankenModel; import personal.mickie.janken.Model.JankenResult; @Controller public class JankenController { @GetMapping(value="/start") public String startPage() { return "index"; } @PostMapping("/result") public String postHand(@RequestParam("hand") int hand_code, Model model) { JankenModel cpu = new JankenModel(); JankenHands player = JankenHands.GetHandFromCode(hand_code); cpu.setCpuHand(); JankenResult result = cpu.checkResult(player); model.addAttribute("cpu", cpu.getCpuHandName()); model.addAttribute("player", player.getHandName()); model.addAttribute("result", result.toString()); return "start/result"; } } 参考文献を読んでいたら特にいうべきことも無いと思う。 動作確認 プロジェクトをビルド、実行して、 http://localhost:8080/startにアクセスすれば下記画面にアクセスできる。 ちょっと懐かしさを感じるシンプルさですね。 もちろんボタンをクリックすれば結果が出る。 無駄に改行されてしまっているのは20年前のHTMLの知識を使ってしまっているからだろう。ちょっと調べておきます。 ソースコードはここに保存してあります。 現状のToDoリストと次回の更新予定 今までの実装状況はこんな感じ。次はとりあえずデータベース周りをどうにかしようか。 じゃんけんのToDoリスト じゃんけんを行う CPUの手をセットする 数字を指定すれば対応する手になる 数字を指定しなければランダムに出す プレイヤーの手をセットする じゃんけんの3すくみを行う あいこを実装する ヘルプを表示する単純だからいらないかな? 3つの手があることをわかるようにする 過去の勝率を表示する 通算成績を表示する 最近10戦を表示する WebGUIのToDoリスト じゃんけんを行う画面の実装 じゃんけん前の画面の実装 勝敗を表示する画面の実装 過去の勝率を表示する画面の実装 何らかの画面をまたぐ要素の実装を行う 次に出す手の予告機能とか?
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

手軽く iOS push 通知

Bark というアプリを利用 ダウンロード: ソースはこちら サーバーのソースはこちら サーバーは Golang 製なので、自分は Golang 分からない。Java で実装可能かを試したらできました。 iOS push 通知必要な情報はここに公開されている: Key ID: LH4T9V5U4R TeamID: 5U8LBRXG3A AuthKey_LH4T9V5U4R_5U8LBRXG3A.p8 ← ファイルをダウンロード プッシュサーバーの実装はこちらを参考 利用するライブラリーはこちら 尚、プッシュするために、お持ちの iOS デバイストークンが必要なので、Docker で上記のサーバーを起動し、iOS 端末から自分のサーバーを追加し、1回プッシュ通知を試す。 そうすると、bark-data のフォルダに、bark.db というファイルに、デバイストークンが保存されているので、boltbrowser というソフトで見ることができる。 push server の java ソース(pushy ほぼそのまま) .p8 ファイルは、作者のサイトからダウンロード。有効期限は無限らしい。 package jp.co.syslinks.ios_push; import java.io.File; import java.util.concurrent.ExecutionException; import com.eatthepath.pushy.apns.ApnsClient; import com.eatthepath.pushy.apns.ApnsClientBuilder; import com.eatthepath.pushy.apns.PushNotificationResponse; import com.eatthepath.pushy.apns.auth.ApnsSigningKey; import com.eatthepath.pushy.apns.util.ApnsPayloadBuilder; import com.eatthepath.pushy.apns.util.SimpleApnsPayloadBuilder; import com.eatthepath.pushy.apns.util.SimpleApnsPushNotification; import com.eatthepath.pushy.apns.util.TokenUtil; import com.eatthepath.pushy.apns.util.concurrent.PushNotificationFuture; public class App { public static void main(String[] args) throws Exception { final String teamID = "5U8LBRXG3A"; // 作者サイトから取得 final String keyId = "LH4T9V5U4R"; // 作者サイトから取得 final String topic = "me.fin.bark"; // ソースから取得 final String tokenString = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; // iOS デバイストークン。docker の bark.db から取得 final ApnsClient apnsClient = new ApnsClientBuilder() // .setApnsServer(ApnsClientBuilder.PRODUCTION_APNS_HOST) // pro ★★★ここ注意、本番環境で設定★★★ //.setApnsServer(ApnsClientBuilder.DEVELOPMENT_APNS_HOST) // dev //.setMetricsListener(new MyCustomMetricsListener()) // dev .setSigningKey(ApnsSigningKey.loadFromPkcs8File(new File("AuthKey_LH4T9V5U4R_5U8LBRXG3A.p8"), teamID, keyId)) // p8File, TeamID, Key ID .build(); final ApnsPayloadBuilder payloadBuilder = new SimpleApnsPayloadBuilder(); payloadBuilder.setAlertBody("Example!"); //本文 payloadBuilder.setAlertTitle("Title!"); //タイトル payloadBuilder.setSound("minuet.caf"); //サウンド設定 SimpleApnsPushNotification pushNotification = new SimpleApnsPushNotification(TokenUtil.sanitizeTokenString(tokenString), topic, payloadBuilder.build()); final PushNotificationFuture<SimpleApnsPushNotification, PushNotificationResponse<SimpleApnsPushNotification>> sendNotificationFuture = apnsClient.sendNotification(pushNotification); try { final PushNotificationResponse<SimpleApnsPushNotification> pushNotificationResponse = sendNotificationFuture.get(); if (pushNotificationResponse.isAccepted()) { System.out.println("accepted"); } else { System.out.println("rejected: " + pushNotificationResponse.getRejectionReason()); pushNotificationResponse.getTokenInvalidationTimestamp().ifPresent(timestamp -> { System.out.println("\t…invalid " + timestamp); }); } } catch (final ExecutionException e) { System.err.println("Failed"); e.printStackTrace(); } sendNotificationFuture.whenComplete((response, cause) -> { if (response != null) { // Handle the push notification response as before from here. } else { // Something went wrong when trying to send the notification to the // APNs server. Note that this is distinct from a rejection from // the server, and indicates that something went wrong when actually // sending the notification or waiting for a reply. cause.printStackTrace(); } }); apnsClient.close(); /*final CompletableFuture<Void> closeFuture = apnsClient.close(); closeFuture.whenComplete((response, cause) -> { if (response != null) { } else { cause.printStackTrace(); } });*/ } } これで、iOS 端末に、通知がいくようになる。 以上。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Java】九九表を作成(桁数を合わせる)

九九表を作成する。 Test1.java public class Test1{ public static void main(String[] args) { for(int i=1; i<=9; i++) { System.out.println(); for(int j=1; j<=9; j++) { System.out.printf(" %3d", (i * j)); } } } } 実行結果. 1 2 3 4 5 6 7 8 9 2 4 6 8 10 12 14 16 18 3 6 9 12 15 18 21 24 27 4 8 12 16 20 24 28 32 36 5 10 15 20 25 30 35 40 45 6 12 18 24 30 36 42 48 54 7 14 21 28 35 42 49 56 63 8 16 24 32 40 48 56 64 72 9 18 27 36 45 54 63 72 81 流れ ↓こんな感じ、伝われっっっ!!! iが1~9に増加  iのn(1~9番目)が終わったら改行する  iがn(1~9)の時にjが1~9に増加   今のiの値とjの値を掛け算する   掛け算の結果を出力(スペース & 3桁で統一) (なんとなく)拡張してみたw iとjの上限値を18まであげただけ。 覚えられるといいね(^^)/ Test2.java public class Test2{ public static void main(String[] args) { for(int i=1; i<=18; i++) { System.out.println(); for(int j=1; j<=18; j++) { System.out.printf(" %3d", (i * j)); } } } } 実行結果. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 3 6 9 12 15 18 21 24 27 30 33 36 39 42 45 48 51 54 4 8 12 16 20 24 28 32 36 40 44 48 52 56 60 64 68 72 5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80 85 90 6 12 18 24 30 36 42 48 54 60 66 72 78 84 90 96 102 108 7 14 21 28 35 42 49 56 63 70 77 84 91 98 105 112 119 126 8 16 24 32 40 48 56 64 72 80 88 96 104 112 120 128 136 144 9 18 27 36 45 54 63 72 81 90 99 108 117 126 135 144 153 162 10 20 30 40 50 60 70 80 90 100 110 120 130 140 150 160 170 180 11 22 33 44 55 66 77 88 99 110 121 132 143 154 165 176 187 198 12 24 36 48 60 72 84 96 108 120 132 144 156 168 180 192 204 216 13 26 39 52 65 78 91 104 117 130 143 156 169 182 195 208 221 234 14 28 42 56 70 84 98 112 126 140 154 168 182 196 210 224 238 252 15 30 45 60 75 90 105 120 135 150 165 180 195 210 225 240 255 270 16 32 48 64 80 96 112 128 144 160 176 192 208 224 240 256 272 288 17 34 51 68 85 102 119 136 153 170 187 204 221 238 255 272 289 306 18 36 54 72 90 108 126 144 162 180 198 216 234 252 270 288 306 324 課題 上記のコードには課題がありました。 それは「実行結果の1行目が改行されてしまっている」こと。 僕の知識(というか考え方?)では、ぱっと改善できなかったので、紙とペンを用意して流れを書いてみました。。。 ◆Test1.javaの流れ(分かりにくいけどw)  1. i=1の処理開始  2. 改行  3. j=1~9の処理開始  4. 1~3の繰り返し 簡単に言葉で書くとこんな感じ。 2の改行で出力結果の1行目が改行されてしまう。 てことは、2の改行を消す? そしたら、i=1の時の処理が終わった後に改行されずに1行にすべて出力されるからNG 理想の出力結果は、j=1~9の処理が終わった後に、改行すること。 (感の悪い僕は、この辺で気づきましたw) j=1~9の処理が終わった後に、改行するようにしたコードは? Test3.java public class Test2{ public static void main(String[] args) { for(int i=1; i<=9; i++) { //System.out.println(); //ここじゃなくて for(int j=1; j<=9; j++) { System.out.printf(" %3d", (i * j)); } System.out.println(); //ここ } } } 実行結果. 1 2 3 4 5 6 7 8 9 2 4 6 8 10 12 14 16 18 3 6 9 12 15 18 21 24 27 4 8 12 16 20 24 28 32 36 5 10 15 20 25 30 35 40 45 6 12 18 24 30 36 42 48 54 7 14 21 28 35 42 49 56 63 8 16 24 32 40 48 56 64 72 9 18 27 36 45 54 63 72 81 うん、いいね、できた!!!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

sonarcloudとGitHubをつなげて静的コード解析を手に入れる

概要 SpringBoot2.5によるRestAPIのサンプルプロジェクトを作っていて、色々調べ物をしていたときに、この記事に出会いました。 https://qiita.com/nagareboshi/items/04e3c0be148b5dd9feee この記事で紹介されている、GitHubのコードはPublicで公開した方が良い理由の1つにsonarcloudの利用が挙げられていました。 ・sonarcloudが無料で使えます 書いたコードの品質を自動でレビューし、指摘箇所があればなぜ悪いのかを理由付きで教えてくれます このサービスを初めて知り、GitHubのPublic公開リポジトリであれば、無料で利用できるということなので、組み込んでみようというのがこの記事の趣旨です。 まずはsonarcloudで色々設定する sonarcloudとGitHubを連携 sonarcloudのサイトへアクセスし、GitHubのボタンを押下する。 https://sonarcloud.io/ sonarcloudとGitHubを関連づけるためAuthorize SonarCloudボタンを押下して認証する。 GitHubのリポジトリをsonarcloudへインポート 自分のGitHubでPublic公開しているリポジトリをsonarcloudへインポートする。 Import projects from GitHubボタンを押下。 All repositoriesという選択肢もあるようですが、分析したいのはあくまでもSpringBootで開発しているRestAPIのプロジェクトだけなので、今回はOnly select repositoriesを選択して、RestAPIプロジェクトのリポジトリを選択し、Installボタンを押下する。 GitHub側のパスワード認証を求められるため、パスワードを入力してConfirm passwordボタンを押下 sonarcloud側に組織情報を定義 Keyは、組織を一意に識別するためのコードを指定し、組織名や個人の名前など、どのようなものでもOKとのこと。 ただし、一度指定したら、変更することができないため、testみたいな適当な名前はやめといた方が良さそうです。 GitHubのPublicリポジトリ1つのみを選択しているため、Free Planで問題ないはず。 FreePlanを選択してCreate Organizationボタンを押下 分析するプロジェクトを選択 sonarcloudで分析するプロジェクトにチェックをつけてSet Upボタンを押下 Preparing Analysisとか表示されてしばらくすると、ConfigureタブにいくつかのAnalysis Methodが表示されます。 sonarcloudの分析処理へ連携するための設定(GitHub Actions) sonarcloudで分析処理をさせるために、何らかの処理をトリガーを設定する必要があります。 各種CIにも対応しているようですが、ここではGitHub Actionsを利用した方法を採用します。 GitHub Actions用のSecretを作成 Analyze with a GitHub Actionというページで、1つ目の手順としてはCreate a GitHub Secretという手順(設定)をします。 In your GitHub repository, go to Settings > Secrets and create a new secret with the following details: とのことなので、GitHubの自分のリポジトリの設定で、指定された通り、静的コード解析をしたいGitHubのリポジトリに遷移します。 対象となるリポジトリの Settingsタブに遷移し、New repository secretボタンを押下。 GitHub Actionsで利用するためのSecretを作成します。 Analyze with a GitHub Actionのページに表示されていた値を利用して設定する。 Name : In the Name field, enter SONAR_TOKEN と表示されていた部分の値 Value : In the Value field, enter ********* と表示されていた部分の値 GitHub Actionsのbuild.ymlファイルを作成 1.Create a GitHub Secretの手順が完了すると、今度はCreate or update a .github/workflows/build.yml fileの手順(設定)を行います。 私の場合はMavenでプロジェクトの構成管理を行っています。そのため、ここでは Mavenを選択して手順を進めていきます。 Mavenを選択すると、Update your pom.xml file with the following propertiesという項目が表示され、pom.xmlの<properties>に3つの定義を追加する必要があるとのこと。 内容をそのままコピーして、自分のプロジェクトのpom.xmlに追加します。 続いて、Create or update your .github/workflows/build.ymlという指示があり、そのbuild.ymlの内容について次のような指定があります。 GitHubのリポジトリに遷移し、Actionsタブにアクセスして、New Workflowからbuild.ymlファイルを作成し、内容を次のように指定します。 .github/workflows/build.yml name: Build on: push: branches: - main # ← sonarcloudの指定だとmasterとなっているが、GitHubのデフォルトがmainなので注意 pull_request: types: [opened, synchronize, reopened] jobs: build: name: Build runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 with: fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis - name: Set up JDK 11 uses: actions/setup-java@v1 with: java-version: 11 - name: Cache SonarCloud packages uses: actions/cache@v1 with: path: ~/.sonar/cache key: ${{ runner.os }}-sonar restore-keys: ${{ runner.os }}-sonar - name: Cache Maven packages uses: actions/cache@v1 with: path: ~/.m2 key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }} restore-keys: ${{ runner.os }}-m2 - name: Build and analyze env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} run: mvn -B verify org.sonarsource.scanner.maven:sonar-maven-plugin:sonar GitHubのmainリポジトリにpushしてGitHub Actionsを動かす とりあえず、適当にコードなどを修正して、それをGitHubのmainリポジトリにpushする。 すると、定義したGitHub Actionsが動作してしばらくするとグリーンのチェックに変わる。 (過去2回エラーが出ているのは、pom.xmlの定義が悪かったり、テストコードに不具合があったりしたためエラーがでていました。) sonarcloudでの分析結果を確認する 以下にアクセスして分析結果を確認してみます。 https://sonarcloud.io/projects RestController Sampleのプロジェクト内にアクセスするとOverviewタブでこのように表示されました。 Bugsのリンク先に遷移すると、静的コード解析の結果、Bugのあるコードを指摘してくれています。 さらに中に遷移するとこんな感じ なんかこうやって毎回数値化されて状況が確認できるだけで、ワクワクするし開発のモチベーションにもなるし、 もうちょっと顧客向けのレポートとか出せるなら、顧客向けの開発進捗状況の報告用にも使えそうでいいですね。 Surefire Reportとかも出せないかしら。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[Javaメモ]Listの中に複数の数字を一気に格納する方法

Listの中に数字を格納する。 格納する数字は1~10までとする。 ※下記は、エラー出ないけど、初心者が書いたってバレるコードw  ちゃんとしたのは「Test2.java」ね。(もしかしたらダメなのかもw) Test.java import java.util.ArrayList; import java.util.List; public class Test{ public static void main(String[] args) { List<Integer> list = new ArrayList<>(); { { for(int i=1; i<=10; i++) { list.add(i); } } }; System.out.println(list); } } 実行結果. [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 中括弧はいらない!? 上記コード(Test.java)のListの下に記載している中括弧は不要みたいです。 Test2.java import java.util.ArrayList; import java.util.List; public class Test2{ public static void main(String[] args) { List<Integer> list = new ArrayList<>(); for(int i=1; i<=10; i++) { list.add(i); } System.out.println(list); } } 実行結果. [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] なんで中括弧つけてた?? 参考書で見たまま覚えてたみたいです(脳死) ・・・調べてみると、この中括弧は、 匿名クラスと初期化ブロックって言うらしい。 あとさっき気づいたけど、Listの最後に「;」あるから普通に中括弧いらなかったw (@shiracamus さん、ご指摘ありがとうございます。。。) Sample. { //匿名(無名)クラス { //初期化ブロック       //何らかの処理    } //初期化ブロック }; //匿名(無名)クラス
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む