- 投稿日:2019-10-21T22:54:51+09:00
単純なコールバックを作ってみる
〇概要
Androidアプリでアーキテクチャーが複雑化してくると非同期の情報を行うクラスとそれを使うクラスが分かれてきます。
そうなると非同期で得たデータを取得したタイミングで別クラスに教えてあげなければならないわけですが結構面倒。
というわけで、サポートライブラリのAsyncTaskLoaderとかイベントバスを扱うライブラリ(EventBusやRxJavaなど)が色々あるわけですが、インターフェースを利用した原始的なコールバックの作り方の情報があまりなかったのでまとめてみました。〇サンプルソース
〇クラス一覧
MainActivity
・メインクラス
・TasksRepositoryとTasksBackgroundDataSourceのインスタンスを生成。
・シンプルにするためにViewの表示関数もここに入れてあります。TasksRepository
・データを保持して操作するクラス。
・生成時にTasksBackgroundDataSourceのインスタンスを取得しています。
・データ取得の依頼をTasksBackgroundDataSourceに投げたり、コールバックを受け取りMainActivityに表示の依頼を投げる。TasksBackgroundDataSource
・非同期でデータを持ってくるクラス。
・TasksDataSourceインターフェースをimplementsしている。
・(ネットワークからデータを持ってくる処理を書くと処理が煩雑になるので、別スレッド立ててデータ埋め込んでいるだけ)TasksDataSource
・データ取得の処理関係をまとめたインターフェース。
Task
・取得した値を管理するデータクラス。
〇コールバック部分抜粋
(注)理解しやすいために上のクラス一覧とは逆順に記載
データ取得の関数とコールバックとして呼ばれる関数を定義
TasksDataSourcepublic interface TasksDataSource { // コールバックとして呼ばれる関数 interface LoadTasksCallback { void onTasksLoaded(List<Task> tasks); void onDataNotAvailable(); } // データ取得関数(別に書かなくてよいがまとめて書いておく) void getTasks(@NonNull LoadTasksCallback callback); }データ取得関数getTasksを実装
取得後はコールバック関数を呼んであげるTasksBackgroundDataSourcepublic class TasksBackgroundDataSource implements TasksDataSource { @Override public void getTasks(@NonNull final LoadTasksCallback callback) { final Handler handler = new Handler(); // スレッド立ち上げ Thread thread = new Thread(new Runnable() { @Override public void run() { // Handlerを使用してメインスレッドに処理を依頼する(View更新のため) handler.post(new Runnable() { @Override public void run() { // データ取得 // ・ // ・ if (tasks.isEmpty()) { // データがない時の処理 callback.onDataNotAvailable(); } else { // データがあった時の処理 callback.onTasksLoaded(tasks); } } }); } }); thread.start(); } }TasksBackgroundDataSourceのgetTaskを呼び出して引数にLoadTasksCallbackのインスタンスを生成して呼び出してほしい関数を実装して渡す。
TasksRepositorymTasksBackgroundSource.getTasks(new TasksDataSource.LoadTasksCallback() { // データ取得後に呼ばれる処理(データありの時) @Override public void onTasksLoaded(List<Task> tasks) { MainActivity.showTextMsg(changeTasksToString(tasks)); } // データ取得後に呼ばれる処理(データなしの時) @Override public void onDataNotAvailable() { Log.w("DEBUG_DATA","TaskRepository onDataNotAvailable"); } });〇まとめ
結局はこれ呼んどいてね!ってデータ取得する関数に処理を実装したインスタンスを投げてるだけですが、それを実現するための設計が複雑ですね。
これはGoogleのMVPサンプルを元につくったのですが、そこでは
PresenterがRepositoryのgetTaskを呼び、そうするとDataSourceのgetTaskが呼ばれてと、数珠つなぎでcallbackが呼ばれていくという仕組みでした。
取得先も増えてくるとわけわからなくなってくるので、やっぱりライブラリを使いましょうということですね。
とりあえず基本をまとめてみました。〇参考
- 投稿日:2019-10-21T22:49:19+09:00
Java 8 lambda expression Feature
Java 8 introduced lambda expression to move toward functional programming. A lambda expression is an anonymous function that doesn’t have a name and doesn’t belong to any class.
Where to use the Lambda Expression
A lambda expression can only be used where the type they are matched against is a single abstract method(SAM) interface or functional interface.To use a lambda expression, you can either create your own functional interface or use the predefined functional interface provided by Java.
Example of a pre-defined interface: Runnable, callable, ActionListener, etc.
Pre Java 8: Use anonymous inner classes.
Post-Java 8: Now use lambda expression instead of anonymous inner classes.Points to remember
Lambda expression is also known as a closure that allows us to treat functionality as a method arguments (passing functions around) or treat code as data.
Lambda expression concept was first introduced in the LISP programming language.
Lambda expression is used to provide an implementation of a functional interface or Single Method Interface.
Lambda expression treated as a function so the compiler does not create .class file.
Lambda expression doesn’t need to define a method again for implementation.
Lambda expression benefit is less coding.
Java Lambda expression Syntax
To create a lambda expression, On the left side of the symbol lambda operator(->) specify input parameters (if there are any), and on the right side place the expression or block of statements.(parameter_list) -> {function_body}
For example, the lambda expression (x, y) -> x + y specifies that lambda expression takes two arguments x and y and returns the sum of these.Note:
Optional type declaration: No need to declare the data type of a parameter. The compiler can inference the data type from the value of the parameter.
The optional parenthesis around parameter: No needs to declare a single parameter in parenthesis. For multiple parameters, parentheses are required.
Optional curly braces: For a single line of the statement, No need to use curly braces in the expression body.
Optional return keyword: The compiler automatically returns the value if the body has a single expression statement to return the value. Curly braces are required to indicate that expression statement returns a value.
Here is some Lamda expression example according to a number of arguments.No Argument Syntax
()->{
//write some statemnet here
}
One Argument Syntax(arg1)->{
//write some statemnet here
}
Two Argument Syntax(arg1,arg2)->{
//write some statemnet here
}
Method vs Lambda Expression in Java
A function (or method) in Java has four main parts:
1. Name
2. Parameter list
3. Body
4. return type.A lambda expression has these main parts:
Lambda expression only has a parameter list and body.
1. No name – Lambda expression is an anonymous function that doesn’t have a name.
2. Parameter list
3. Body – This is the main part of the function where implementation is written.
4. No return type – Don’t need to write a return statement explicitly. The compiler is able to infer the return type by checking the code.Related on
- 投稿日:2019-10-21T21:21:51+09:00
Eclipse - Springboot
環境
- Elipcse 2018-09(4.9) ※Pleiades All in oneを使用
- Java 8
EclipseにSTSを入れる
Spring Tools 4をインストール
Eclipseのパースペクティブを表示する
プロジェクト作成
- メニュー「ファイル→新規作成→Springスタータープロジェクト」を選択する
- 次へを押す
- 依存関係を追加指定し完了を押す
- 依存関係のインポートを待つ
- pom.xmlの1行目で不明なエラーが出たらmaven pluginのバージョン指定を追加する
pom.xml<properties> <java.version>1.8</java.version> <!-- 下の1行を追加する --> <maven-jar-plugin.version>3.1.1</maven-jar-plugin.version> </properties>動作確認
Controllerを作成する
HelloController.javapackage com.example.demo; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; @Controller public class HelloContoller { @RequestMapping("/") public String hello() { return "hello"; } }HTMLを作成する
hello.html<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Spring demo</title> </head> <body> <h1>Hello</h1> </body> </html>ツールバー実行から「実行→Spring bootアプリケーション」を選択して「http://localhost:8080」にアクセスする
- 投稿日:2019-10-21T20:51:45+09:00
Talendコンポーネント活用(5)コンポーネントを自作する
Talendのコンポーネントを自作する
以前に標準コンポーネントでは実現できない処理をカスタムコンポーネントで使用する方法を紹介しましたが、今回はコンポーネントを作成する方法を紹介いたします。
Talendバージョン7以降ではコンポーネント作成手法が変更
Talendのバージョン6以前ではTalendStudioにComponent Designerという機能が付随されており、これを使ってコンポーネントの作成ができるようになっていました。
しかしバージョン7以降ではComponent Designerが廃止され、EclipseやIntelliJなどのJava統合開発環境で開発する方法に変更されました。開発環境準備
コンポーネントの開発にはTalend Component Kitが必要になりますので、プラグインが利用可能なIntelliJを使用します。
IntelliJを起動して空のプロジェクトを作成し、メニューのファイルから設定画面を開き、プラグインのマーケットプレイスの検索タブからTalendを入力するとTalend Component Kitが表示されますので、これを選択してインストールしてIntelliJを再起動します。
なお、JavaはJava JDK1.8.xが必須となります。プロジェクトの新規作成
IntelliJ IDEA へようこそ画面からプロジェクトの新規作成をクリックし、Talend Component Kitを選択して次へをクリックします。
下図のTalend STARTER TOOLKITが表示されます。
メタデータの定義
Talend STARTER TOOLKIT画面ではコンポーネントとプロジェクトのメタデータを定義します。
今回は下図の内容を設定します。
各項目を入力し画面左側の③Add A ComponentをクリックするとConfigration画面が表示されます。
コンポーネントの標準定義設定
Configration画面ではコンポーネントの名前と入出力設定を行います。
今回は下図のように名前のみをLoggerに変更し入出力はデフォルト設定で行います。
次へをクリックすると下図のプロジェクト名と保存場所の設定画面が表示されますので、必要に応じて変更して完了ボタンをクリックします。
プロジェクトの確認
STARTER TOOLKITが完了するとIntelliJのプロジェクト画面に移行します。
この時点でコンポーネントの作成に必要な最低限の設定は完了しています。
プロジェクトからLoggerProcessor.javaを開くと、コンポーネント作成に必要なコードの下地が既に作成されています。
コンポーネントのコンパイルとデプロイ
この時点では特に何も機能しないコンポーネントではありますが、TalendOpenStudioへのデプロイまで実行してみます。
IntelliJのターミナルでmvnw clear installを入力してコンパイルを実行します。
下図のようにコンパイルが実行され正常に終了します。
続いて、mvnw talend-component:deploy-in-studio -Dtalend.component.studioHome="C:\Talend\7.1.1_TOS_DI"を入力してTalendOpenStudioへのデプロイを実行します。
ダブルクォーテーションで囲まれているパスには、デプロイするコンポーネントを使用するTalendOpenStudioのホームのパスを設定します。
下図のようにデプロイが実行され正常に終了します。
TalendOpenStudioから作成したコンポーネントを使用する
デプロイ先に指定したTalendOpenStudioを起動して空のジョブを作成します。
PaletteのMiscを開くと、STARTER TOOLKITのメタデータで定義したSampleFamilyが表示され、デプロイしたコンポーネントSampleFamilyLoggerが使用できるようになっていますので、これをジョブに配置して使用できることを確認します。
入力内容を表示するコードを追加する
このままでは実行しても見た目の結果が何もないコンポーネントなので、入力内容を表示するコンポーネントに変更します。
TalendOpenStudioを終了してIntelliJに戻り、LoggerProcessor.javaを開いて@ElementListenerを探して以下の2行を追加します。
//Log to the console
System.out.println("Input["+defaultInput+"]");
先ほどと同様にターミナルからコンパイルとデプロイを実行します。
再びTalendOpenStudioを起動して、先ほどのジョブを開いてコンポーネントのInput側にtFileInputDelimitedeを追加してジョブを実行すると、実行結果にファイルからの入力内容が表示されます。
まとめ
IntelliJとTalend Component Kitを使用することにより、簡単にコンポーネントの下地を作成することができました。
次回はもう少し深堀してコンポーネントを作成したいと考えてます。
- 投稿日:2019-10-21T19:53:38+09:00
【Kotlin】Kotlin 1.4未満では型パラメータに対するアノテーションが機能しない【BeanValidation】
TL;DR
内容はタイトルの通りです。
ただし、「バージョン1.4
未満」としたのは暫定の表現で、実際に解決されるか、解決されるとして具体的にいつになるかなど、具体的なことは定かではありません。前提
SpringBoot
等でよく利用されるBeanValidation
は、リスト等の型パラメータ(型引数、Type Argument
とも)に対してアノテーションを振ることで、内容に対するバリデーションが可能です1。Javaで型パラメータにアノテーションを付与したフィールドの例private final List<@Size(max = 255, message = "{max}文字以内で入力してください。") String> hoge;問題点
Kotlin
で同じように書いてもバリデーションが機能しません。Kotlinで型パラメータにアノテーションを付与したフィールドの例(機能しない)private val hoge: List<@Size(max = 255, message = "{max}文字以内で入力してください。") String>このことは既に
issue
になっています。問題解決の目処
KT-13228には
Target Versions: 1.4
が指定されていますが、少なくともこの問題は3年以上放置されています。参考にさせていただいた記事
- How do we do kotlin data class validation on Collection? - Stack Overflow
- Java EE 8新機能解説 -Bean Validation 2.0編-
この機能がサポートされたのは
BeanValidation 2.0
から。 ↩
- 投稿日:2019-10-21T19:53:38+09:00
【Kotlin】Kotlin 1.4.x未満では型パラメータに対するアノテーションが機能しない【BeanValidation】
TL;DR
内容はタイトルの通りです。
ただし、「バージョン1.4.x
未満」としたのは暫定の表現で、実際に解決されるか、解決されるとして具体的にいつになるかなど、具体的なことは定かではありません。前提
SpringBoot
等でよく利用されるBeanValidation
は、リスト等の型パラメータ(型引数、Type Argument
とも)に対してアノテーションを振ることで、内容に対するバリデーションが可能です1。Javaで型パラメータにアノテーションを付与したフィールドの例private final List<@Size(max = 255, message = "{max}文字以内で入力してください。") String> hoge;問題点
Kotlin
で同じように書いてもバリデーションが機能しません。Kotlinで型パラメータにアノテーションを付与したフィールドの例(機能しない)private val hoge: List<@Size(max = 255, message = "{max}文字以内で入力してください。") String>このことは既に
issue
になっています。問題解決の目処
KT-13228には
Target Versions: 1.4
が指定されていますが、少なくともこの問題は3年以上放置されています。参考にさせていただいた記事
- How do we do kotlin data class validation on Collection? - Stack Overflow
- Java EE 8新機能解説 -Bean Validation 2.0編-
この機能がサポートされたのは
BeanValidation 2.0
から。 ↩
- 投稿日:2019-10-21T18:49:43+09:00
replaceトラップ
だまされたわ
メールで試してみる
MailTemplate.javapackage mail; public class MailTemplate { /** from */ private String from; /** to */ private String to; /** cc */ private String cc; /** title */ private String title; /** body */ private String body; public String getFrom() { return from; } public void setFrom(String from) { this.from = from; } public String getTo() { return to; } public void setTo(String to) { this.to = to; } public String getCc() { return cc; } public void setCc(String cc) { this.cc = cc; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getBody() { return body; } public void setBody(String body) { this.body = body; } }本文を作成するならこんな感じですよね
Test1.javapackage test; import mail.MailTemplate; /** * test * * @author me * */ public class Test1 { /** mail template */ private static MailTemplate mail = new MailTemplate(); /** body template */ private static final String BODY = "[time]に[place]でまちあわせな。\r\nこなかったら[kill]。"; /** * main * @param args */ public static void main(String[] args) { System.out.println(join(createMail())); } private static String join(MailTemplate mail) { String crlf = "\r\n"; return mail.getFrom() + crlf + mail.getTo() + crlf + mail.getCc() + crlf + mail.getTitle() + crlf + mail.getBody(); } /** * create * @return */ private static MailTemplate createMail() { // from mail.setFrom("おくりぬし"); // to mail.setTo("おくりさき"); // cc mail.setCc("ほかのひと"); // title mail.setTitle("けんめい"); // body mail.setBody(replaceBody(BODY)); return mail; } /** * replace * @param text * @return */ private static String replaceBody(String text) { text.replace("[time]", "2019/12/25"); text.replace("[place]", "東京駅"); text.replace("[kill]", "びんた"); return text; } }で、結果
おくりぬし おくりさき ほかのひと けんめい [time]に[place]でまちあわせな。 こなかったら[kill]。replaceって
Getter Setterみたいにできないわけですね
ただしくは
Test2.javapackage test; import mail.MailTemplate; /** * test * * @author me * */ public class Test2 { /** mail template */ private static MailTemplate mail = new MailTemplate(); /** body template */ private static final String BODY = "[time]に[place]でまちあわせな。\r\nこなかったら[kill]。"; /** * main * @param args */ public static void main(String[] args) { System.out.println(join(createMail())); } private static String join(MailTemplate mail) { String crlf = "\r\n"; return mail.getFrom() + crlf + mail.getTo() + crlf + mail.getCc() + crlf + mail.getTitle() + crlf + mail.getBody(); } /** * create * @return */ private static MailTemplate createMail() { // from mail.setFrom("おくりぬし"); // to mail.setTo("おくりさき"); // cc mail.setCc("ほかのひと"); // title mail.setTitle("けんめい"); // body mail.setBody(replaceBody(BODY)); return mail; } /** * replace * @param text * @return */ private static String replaceBody(String text) { text = text.replace("[time]", "2019/12/25") .replace("[place]", "東京駅") .replace("[kill]", "びんた"); return text; } }結果
おくりぬし おくりさき ほかのひと けんめい 2019/12/25に東京駅でまちあわせな。 こなかったらびんた。しっかり上書きしないとなんも変わらないの、以外と盲点でキレそう
- 投稿日:2019-10-21T18:16:06+09:00
Maven Dependency Plugin で system スコープの jar ファイルもひとつにまとめる
概要
- 依存する JAR ファイルをローカルに置いて pom.xml で <scope>system</scope> を指定している状況を想定
- mvn package コマンドで作成する JAR ファイルに、依存 JAR ファイル内のすべてのクラスファイルが入るように設定する
- 今回の環境: Apache Maven 3.6.2
方法
Maven Dependency Plugin で以下にように設定する。
- phase: prepare-package
- goal: unpack-dependencies
- outputDirectory: コンパイルしたクラスファイルが置かれるディレクトリを指定
- includeArtifactIds: JAR ファイルに含めたいライブラリの artifactId をカンマ区切りで指定
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-dependency-plugin</artifactId> <executions> <execution> <phase>prepare-package</phase> <goals> <goal>unpack-dependencies</goal> </goals> <configuration> <outputDirectory>${project.build.directory}/classes</outputDirectory> <includeArtifactIds>ajd4jp,jdom</includeArtifactIds> </configuration> </execution> </executions> </plugin>この設定で mvn package を実行すると、JAR ファイルを作成する前に、ライブラリなどの依存 JAR ファイルからクラスファイル等が展開され、outputDirectory で指定したディレクトリにコピーされる。
JAR ファイルを作成する際には、依存 JAR ファイルの中にあったクラスファイルもひとつの JAR ファイルにまとめられる。実例
pom.xml ファイルを用意。
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.example</groupId> <artifactId>sample</artifactId> <packaging>jar</packaging> <version>1.0.0</version> <name>sample</name> <build> <finalName>${project.artifactId}</finalName> <plugins> <!-- Apache Maven Dependency Plugin --> <!-- https://maven.apache.org/plugins/maven-dependency-plugin/ --> <!-- https://mvnrepository.com/artifact/org.apache.maven.plugins/maven-dependency-plugin --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-dependency-plugin</artifactId> <executions> <execution> <phase>prepare-package</phase> <goals> <goal>unpack-dependencies</goal> </goals> <configuration> <outputDirectory>${project.build.directory}/classes</outputDirectory> <includeArtifactIds>ajd4jp,jdom</includeArtifactIds> </configuration> </execution> </executions> </plugin> </plugins> </build> <dependencies> <dependency> <groupId>ajd4jp</groupId> <artifactId>ajd4jp</artifactId> <version>1.4.6.2019</version> <scope>system</scope> <systemPath>${project.basedir}/lib/ajd4jp-1.4.6.2019.jar</systemPath> </dependency> <dependency> <groupId>jdom</groupId> <artifactId>jdom</artifactId> <version>1.1.3</version> <scope>system</scope> <systemPath>${project.basedir}/lib/jdom-1.1.3.jar</systemPath> </dependency> </dependencies> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>11</maven.compiler.source> <maven.compiler.target>11</maven.compiler.target> </properties> </project>mvn package コマンドで JAR ファイルを作成する。
$ mvn package作成した target/sample.jar を展開すると、指定したライブラリの jar ファイルに含まれていたクラスファイルが入っていることがわかる。
$ unzip target/sample.jar Archive: target/sample.jar creating: META-INF/ inflating: META-INF/MANIFEST.MF creating: orrery/ creating: iso/ creating: org/ creating: org/jdom/ creating: org/jdom/xpath/ creating: org/jdom/input/ creating: org/jdom/output/ creating: org/jdom/adapters/ creating: org/jdom/filter/ creating: org/jdom/transform/ creating: ajd4jp/ creating: ajd4jp/orrery/ creating: ajd4jp/orrery/tool/ creating: ajd4jp/iso/ creating: ajd4jp/util/ creating: ajd4jp/format/ creating: format/ creating: com/ creating: com/example/ inflating: orrery/package-info.class inflating: Copyright.txt inflating: iso/package-info.class inflating: org/jdom/IllegalAddException.class inflating: org/jdom/DefaultJDOMFactory.class inflating: org/jdom/EntityRef.class (後略)Maven Assembly Plugin と組み合わせる
Maven Assembly Plugin も導入することで system スコープを指定した JAR ファイルだけでなく、リポジトリにある依存 JAR ファイルも一緒にまとめることができる。
pom.xml ファイルを用意。
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.example</groupId> <artifactId>sample</artifactId> <packaging>jar</packaging> <version>1.0.0</version> <name>sample</name> <build> <finalName>${project.artifactId}</finalName> <plugins> <!-- Apache Maven Dependency Plugin --> <!-- https://maven.apache.org/plugins/maven-dependency-plugin/ --> <!-- https://mvnrepository.com/artifact/org.apache.maven.plugins/maven-dependency-plugin --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-dependency-plugin</artifactId> <executions> <execution> <phase>prepare-package</phase> <goals> <goal>unpack-dependencies</goal> </goals> <configuration> <outputDirectory>${project.build.directory}/classes</outputDirectory> <includeArtifactIds>ajd4jp,jdom</includeArtifactIds> </configuration> </execution> </executions> </plugin> <!-- Apache Maven Assembly Plugin --> <!-- http://maven.apache.org/plugins/maven-assembly-plugin/ --> <!-- https://mvnrepository.com/artifact/org.apache.maven.plugins/maven-assembly-plugin --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-assembly-plugin</artifactId> <version>3.1.1</version> <executions> <execution> <phase>package</phase> <goals> <goal>single</goal> </goals> </execution> </executions> <configuration> <descriptorRefs> <descriptorRef>jar-with-dependencies</descriptorRef> </descriptorRefs> <archive> <manifest> <mainClass>com.example.App</mainClass> </manifest> </archive> </configuration> </plugin> </plugins> </build> <dependencies> <dependency> <groupId>ajd4jp</groupId> <artifactId>ajd4jp</artifactId> <version>1.4.6.2019</version> <scope>system</scope> <systemPath>${project.basedir}/lib/ajd4jp-1.4.6.2019.jar</systemPath> </dependency> <dependency> <groupId>jdom</groupId> <artifactId>jdom</artifactId> <version>1.1.3</version> <scope>system</scope> <systemPath>${project.basedir}/lib/jdom-1.1.3.jar</systemPath> </dependency> <dependency> <groupId>org.twitter4j</groupId> <artifactId>twitter4j-core</artifactId> <version>4.0.7</version> <scope>compile</scope> </dependency> </dependencies> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>11</maven.compiler.source> <maven.compiler.target>11</maven.compiler.target> </properties> </project>mvn package コマンドで JAR ファイルを作成する。
$ mvn package作成した target/sample-jar-with-dependencies.jar を展開すると、system スコープと compile スコープで指定したライブラリの jar ファイルに含まれるクラスファイルが入っていることがわかる。
$ unzip target/sample-jar-with-dependencies.jar Archive: target/sample-jar-with-dependencies.jar inflating: META-INF/MANIFEST.MF creating: twitter4j/ creating: twitter4j/util/ creating: twitter4j/util/function/ creating: twitter4j/auth/ creating: twitter4j/management/ creating: twitter4j/json/ creating: twitter4j/api/ creating: twitter4j/conf/ creating: META-INF/maven/ creating: META-INF/maven/org.twitter4j/ creating: META-INF/maven/org.twitter4j/twitter4j-core/ creating: orrery/ creating: iso/ creating: org/ creating: org/jdom/ creating: org/jdom/xpath/ creating: org/jdom/input/ creating: org/jdom/output/ creating: org/jdom/adapters/ creating: org/jdom/filter/ creating: org/jdom/transform/ creating: ajd4jp/ creating: ajd4jp/orrery/ creating: ajd4jp/orrery/tool/ creating: ajd4jp/iso/ creating: ajd4jp/util/ creating: ajd4jp/format/ creating: format/ creating: com/ creating: com/example/ creating: META-INF/maven/com.example/ creating: META-INF/maven/com.example/sample/ inflating: META-INF/LICENSE.txt inflating: twitter4j/JULLoggerFactory.class inflating: twitter4j/SymbolEntity.class inflating: twitter4j/MediaEntity.class inflating: twitter4j/TwitterBase.class inflating: twitter4j/Dispatcher.class inflating: twitter4j/HttpClientBase.class (後略)参考資料
- 投稿日:2019-10-21T17:58:20+09:00
【Java】MySQLに接続する
概要
MySQL : 5.7
Java : 8.1
Mac
Eclipse始める前に以下条件をクリアしている
・MySQLで既にtableなどができている。
・ターミナルなどで難なく接続できているJDBCをダウンロード
MySQLのJDBCをダウンロード
https://dev.mysql.com/downloads/connector/j/「Platform Independent (Architecture Independent), Compressed TAR Archive」 をダウンロード
解凍したファイルに
mysql-connector-java-5.1.48-bin.jar
があるから、
Tomcatの/Tomcat/lib
に入れる
(私の場合、/Users/namari/apache-tomcat-9.0.27/lib
)接続してみる
プロジェクトの中に、
SqlTest.java
を適当に作ってみる。SqlTest.javapackage chapter14; import java.io.*; import java.sql.*; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.*; /** * Servlet implementation class SqlTest */ @WebServlet("/SqlTest") public class SqlTest extends HttpServlet { private static final long serialVersionUID = 1L; protected void doGet( HttpServletRequest request, HttpServletResponse response ) throws ServletException, IOException { // 今回は、localhostにあるbook のデータベース String url = "jdbc:mysql://localhost/book"; try{ Class.forName("com.mysql.jdbc.Driver"); Connection conn = DriverManager.getConnection(url, "ユーザー名", "パスワード"); // データベースに対する処理 msg = "ok"; } catch (SQLException | ClassNotFoundException e){ msg = "NG"; } response.getWriter().println(msg); } }
- 投稿日:2019-10-21T13:37:18+09:00
[Java]StringからPath型に変換して、パスを取得する方法
Java8で、ファイルパスを取得する際にPathクラスというものが必要になったのだが、処理中にStringのものも混在していて逐一変換しないといけない状態があったのでメモ書き。
結論から言うと、Pathクラスのresolveメソッドで、引数にStringの文字列を渡してあげればパス全体をPath型として認識させてあげることができる。
参考サイト:Path (Java Platform SE 8 )
https://docs.oracle.com/javase/jp/8/docs/api/java/nio/file/Path.htmlresolveメソッドで指定した引数を追加された状態で、ファイルパスの全体を設定することができる。
具体例:Path型で指定したパス→/test/pathTest
Stringで追加したいパス→hoge.txt結果:resolveメソッドを使用した結果→/test/pathTest/hoge.txt
※区切り文字は「/」と仮定もし解釈が違っていたとか、もっと楽な方法があるのでしたら教えていただけると幸いです。
- 投稿日:2019-10-21T13:29:31+09:00
Jacksonとは?
こんにちは。
ぽんぽこです。本日はJacksonについてお話しします。
では本編へ。
Jacksonとは?
JacksonはJavaで使えるJSONライブラリです。
JSON形式の文字列をJavaのオブジェクトに直接マッピングしたり、
逆にJavaオブジェクトをJSON文字列に変換できたりします。HTTPレスポンスをパースしたりオブジェクトをBase64エンコーディングする時などに便利です。
要するにすごーーーく便利な物です!
Jacksonを使うメリット
Jacksonを使えるとJSONを簡単に扱えます。
Jsonを使えるようになると、とても色々なことができるようになり、世界が大きく広がります。
なぜなら、TwitterやFacebook、GoogleなどのWEBサービスとはJSONでやりとりするからです。つまり、JSONが分かれば、世の中にあるWEBサービスの色々な機能を自分で使えるようになります!!
Jsonの良さについては別の記事で紹介します!
Jacksonの使い方
Jacksonを利用するにはライブラリのダウンロードが必要です。
別の記事で紹介したMavenを利用する場合は以下を依存関係に指定します。Mavenで利用する場合
<groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.2.3</version>Mavenを利用しない場合は以下のjarをダウンロードします。
jackson-databind-2.9.9-sources.jar
jackson-annotations-2.9.0-sources.jar
jackson-core-2.9.9-sources.jar上記の方法でJacksonを使用することができるので
みなさんも試してみてください!では次回、Jsonとは?でお会いしましょう。
では。
- 投稿日:2019-10-21T12:47:52+09:00
H2 Databaseのコンソールタイムアウト(セッションタイムアウト)を設定する
TL;DR
- H2 DatabaseのWebコンソールのセッションタイムアウトは、デフォルトで30分
- これを延長する場合は、システムプロパティ
h2.consoleTimeout
で秒数を指定するコンソールタイムアウト
H2 Databaseを起動すると、
http://localhost:8082
でアクセス可能なWebコンソールが起動します。これのことですね。
このセッションタイムアウトは、デフォルトで30分になっています。
人によっては、短いと感じるかもしれません。少し放置する時間があって、タイムアウトするとそれまで書いていたクエリがなくなったりするわけです。
h2.consoleTimeout
を設定するWebコンソールのタイムアウトを設定するには、
CONSOLE_TIMEOUT
を設定すればよいみたいです。デフォルトは
1800000
で、実際にシステムプロパティとして指定する時はh2.consoleTimeout
を指定します。
SysProperties
のプロパティのid
が、このキーになっていましたね、記事を書いていて気づきました。
https://www.h2database.com/javadoc/org/h2/engine/SysProperties.html#h2.consoleTimeout
これを、H2 Databaseの起動時にシステムプロパティとして指定します。
指定方法は、こちらを参考に。
Settings Read from System Properties
H2 Databaseのバージョン1.4.200で実行しました。
$ java -cp bin/h2-1.4.200.jar -Dh2.consoleTimeout=[秒数] org.h2.tools.Console以下は、デフォルト値の30分(1800000秒)を明示的に指定した例です。
$ java -cp bin/h2-1.4.200.jar -Dh2.consoleTimeout=1800000 org.h2.tools.Consoleこれで、コンソールのタイムアウト(セッションタイムアウト)を変更することができるようになります。
確認に使用したJavaのバージョンは、こちらです。
$ java -version openjdk version "1.8.0_222" OpenJDK Runtime Environment (build 1.8.0_222-8u222-b10-1ubuntu1~18.04.1-b10) OpenJDK 64-Bit Server VM (build 25.222-b10, mixed mode)
- 投稿日:2019-10-21T11:15:04+09:00
【Java】フィルターを作成
重複する内容はフィルターを作成してスッキリとしたコードに!!!
EncodingFilter.javapackage tool; import java.io.IOException; import javax.servlet.*; import javax.servlet.annotation.WebFilter; @WebFilter(urlPatterns = { "/*" }) public class EncodingFilter implements Filter { public void doFilter( ServletRequest request, ServletResponse response, FilterChain chain ) throws IOException, ServletException { request.setCharacterEncoding("UTF-8"); response.setContentType("text/html; charset=UTF-8"); System.out.println("フィルター処理前"); chain.doFilter(request, response); System.out.println("フィルター処理後"); } public void init(FilterConfig filterconfig) {} public void destory() { } }
- 投稿日:2019-10-21T08:41:04+09:00
StringUtils.isBlank作ってみた
つくってみました
StringUtils.javapackage practice; import java.util.Arrays; import java.util.List; import java.util.Objects; import java.util.Optional; import java.util.function.Consumer; import java.util.function.Predicate; import java.util.stream.Collectors; /** * Utils * * @author me * */ public class Practice { /** String list */ private static final List<String> INTEGER_LIST = Arrays.asList(null, "", " ", "0", "1", "2"); /** * main * * @param args */ public static void main(String[] args) { try { run(INTEGER_LIST); } catch (NumberFormatException e) { echo.accept("・ω・v"); } } /** * run * * @param list <E> The element type of this list. * @throws NumberFormatException if conversion to numeric number is impossible. */ private static void run(List<String> list) throws NumberFormatException { echo.accept(list.stream().filter(notBlank).map(Integer::parseInt) .collect(Collectors.summingInt(Integer::intValue))); } /** not null */ static Predicate<String> notNull = v -> Optional.ofNullable(v).isPresent(); /** not space */ static Predicate<String> notSpace = v -> !v.equals(" "); /** StringUtils.isBlank */ static Predicate<String> notBlank = v -> notNull.test(v) && !v.isEmpty() && Arrays.asList(v.split("")).stream().anyMatch(notSpace); /** out */ static Consumer<Object> echo = v -> System.out.println(v); }結果
3
結論
なんだかんだ自作できてもライブラリ追加した方が早くね問題
けど数行で終わるならいちいち使わなくてもいいですよね
ぶっちゃけもうjava既存のでなんでも解決できそうな気分になってます
最近apache.common.lang全然見ない...
- 投稿日:2019-10-21T05:28:25+09:00
java 状態マシン 自動車
目次 ⇒ Javaアルゴリズムライブラリ-Artery-サンプル
Q08_01.javapackage jp.avaj.lib.algo; import jp.avaj.lib.test.ArTest; /** ArStateMechine-状態マシン-自動車 ・状態マシンのごく簡単なサンプルとして自動車を取り上げる ・実際の自動車と比較すれば、簡単すぎるが、次の動作をする ・アクセルを踏む⇒エンジンが回転する⇒車輪が回転する ・アクセルを離す⇒エンジンが停止する⇒車輪が停止する ・本サンプルではArStateMachineの実装としてArStateMachineDefaultを使用している ・ArStateMachineDefaultは状態マシンが変化した時に、さらにイベントを発生させることができる ・アクセル⇒エンジン⇒車輪のイベント伝達は、この機能を利用している. */ public class Q08_01 { public static void main(String[] args) { // 車輪の状態マシン ArStateMachineDefault wheel = new ArStateMachineDefault(); { // 状態遷移マトリックス ArStateTransition[] matrix = new ArStateTransition[] { // 回転中に停止イベント⇒停止する new ArStateTransition(WheelState.ROTATE,WheelEvent.OFF,WheelState.STOP,null), // 停止中に動作イベント⇒回転する new ArStateTransition(WheelState.STOP,WheelEvent.ON,WheelState.ROTATE,null), }; // 初期設定する,最初は停止状態 wheel.init(WheelState.STOP, matrix); } // エンジンの状態マシン ArStateMachineDefault engine = new ArStateMachineDefault(); { // 状態遷移マトリックス ArStateTransition[] matrix = new ArStateTransition[] { // 回転中に停止イベント⇒停止する、WheelEvent.OFFを出す new ArStateTransition(EngineState.ROTATE,EngineEvent.OFF,EngineState.STOP,WheelEvent.OFF), // 停止中に起動イベント⇒回転する、WheelEvent.OFFを出す new ArStateTransition(EngineState.STOP,EngineEvent.ON,EngineState.ROTATE,WheelEvent.ON) }; // 初期設定する、最初は停止状態 engine.init(EngineState.STOP,matrix); // 車輪と結びつける(trueは接続する,falseは接続断する)⇒イベントが送信される engine.connect(wheel,true); } // アクセルの状態マシン ArStateMachineDefault accel = new ArStateMachineDefault(); { // 状態遷移マトリックス ArStateTransition[] matrix = new ArStateTransition[] { // 踏込んだ状態で離すイベント⇒OFFになる,EngineEvent.OFFを出す new ArStateTransition(AccelState.ON,AccelEvent.OFF,AccelState.OFF,EngineEvent.OFF), // 離した状態で踏込むイベント⇒ONになる,EngineEvent.ONを出す new ArStateTransition(AccelState.OFF,AccelEvent.ON,AccelState.ON,EngineEvent.ON) }; // 初期設定する、最初は離した状態 accel.init(AccelState.OFF,matrix); // エンジンと結びつける(trueは接続する,falseは接続断する)⇒イベントが送信される accel.connect(engine,true); } // テストケースを開始する ArTest.startTestCase("Q08_01"); // アクセルを踏み込む accel.sendEvent(AccelEvent.ON); // エンジンが回転していることを確認する ArTest.equals("accel:on","expected",EngineState.ROTATE,"engine",engine.getState()); // 車輪が回転していることを確認する ArTest.equals("accel:on","expecteed",WheelState.ROTATE,"wheel",wheel.getState()); // アクセルを離す accel.sendEvent(AccelEvent.OFF); // エンジンが停止していることを確認する ArTest.equals("accel:off","expected",EngineState.STOP,"engine",engine.getState()); // 車輪が停止していることを確認する ArTest.equals("accel:off","expecteed",WheelState.STOP,"wheel",wheel.getState()); // テストケースを終了する ArTest.endTestCase(); } /** アクセルの状態. */ static enum AccelState { ON,OFF; } /** アクセルへのイベント. */ static enum AccelEvent { ON,OFF; } /** エンジンの状態. */ static enum EngineState { ROTATE,STOP; } /** エンジンへのイベント. */ static enum EngineEvent { ON,OFF; } /** 車輪の状態. */ static enum WheelState { ROTATE,STOP; } /** 車輪へのイベント. */ static enum WheelEvent { ON,OFF; } }結果は次のとおり。
result.txt**** Q08_01 start **** OK accel:on:expected=ROTATE:engine=ROTATE OK accel:on:expecteed=ROTATE:wheel=ROTATE OK accel:off:expected=STOP:engine=STOP OK accel:off:expecteed=STOP:wheel=STOP **** Q08_01 summary **** test count = 4 success = 4