jrunscript

jrunscript

今更ながらjavaの組み込みjavascriptを試す。

javaのクラス(パッケージは)簡単に呼び出せる。

java標準のクラスは、特に気にすること無く、普通に呼び出せる。

1
2
java.lang.System.out.println('test message');
java.swing.JOptionPane.showMessageDialog(null, 'Test Message');

Java標準以外のクラスは、Packagesから始めて呼び出す必要がある。

1
2
var log = Packages.org.apache.commons.logging.LogFactory.getLog('my-script.js');
log.info('message');

上の例では、commons-loggingを利用しているので、jrunscript引数の-cpまたは-classpathで、commons-logging.jarとロガーを指定する必要がある。
クラスパスの指定で、jarを*でディレクトリごと指定することはできない。個別に.jarを羅列する。

Java標準クラスをPackagesから辿ることもできる。

1
2
java.lang.String.format('Test. %04.3f', 12.3);
Packages.java.lang.String.format('Test. %04.0f', 13);

なお、Javaでは何もしなくてもインポートされているjava.langは、jrunscriptではインポートされていない。
Object,Boolean,Stringなどがjavascriptとjavaで当たってしまうためらしい。

jrunscriptでもimportを行えば、クラス名だけでクラスを指定することができる。

1
2
importClass(java.util.ArrayList);
importPackage(javax.swing);

クラス毎のimportと、パッケージ単位のimportができる。
このimport方法だとスクリプト内のすべてで有効になってしまうため、不都合があるかもしれない。
そんなときは、JavaImporterを利用することで、狭い範囲のインポート宣言を行える。

1
2
3
4
5
6
7
var mylib = new JavaImporter(
    java.lang,
    javax.swing
);
with (mylib) {
    JOptionPane.showMessageDialog(null, String.format('Test. %s', 'NN'));
}

度々、String.formatのサンプルで書いているが、javascriptの数値はjavaのDoubleとして変換される。
したがって、String.formatでjavascriptの数値を変換するときはfを利用する。

jrunscriptでは、外部のjavascriptファイルを簡単に呼び出すことができる。

1
load('myCommon.js');

面倒な処理があるばあいは、共通処理として出しておければ良いと思う。
内部処理的には、ファイルを開いてevalしているらしい。

注意すべきところ

javaのメソッドを呼び出して返ってきたStringはあくまでもjava.lang.String。
したがって、javascriptの文字列との比較でアンマッチになることがある。
if (a == b) は、問題なく比較できる。
Arrayにpushし、indexOfで存在確認すると、アンマッチになった。

まとめ

結構、普通に使えた。
ただ、Java7に付属するRhinoでは、javaのリストのイテレートがが面倒。
Java8からのNashornになると、イテレートがfor inでできるようになるので使い易いと思う。

Javaクラスを呼び出せばなんでもできてしまうが、javascriptそのものが非力なため、ファイルの一覧を処理するような場合は、jythonを使ったほうがずっと手軽にできた。

ただ、まったく新しい言語を覚えなくても、公用語とも言えるjavascriptでjavaのAPIを自由に使えるのはとても良いと思った。

同じタグの記事
同じカテゴリの記事

High Sierraに更新したらgitコマンドが使えなくなった

High Sierraに更新したらgitコマンドが使えなくなった。

久々に、個人サイトの更新をしようと思い、git pullすると、エラーになった。

1
2
MacBookAir:program user$ git pull
xcrun: error: invalid active developer path (/Library/Developer/CommandLineTools), missing xcrun at: /Library/Developer/CommandLineTools/usr/bin/xcrun

atomのgitも動かない。

どうやら、Command Line Toolsが正常に動作しなくなったようだ。

次のコマンドを実行し、Command Line Toolsをインストールしたら、今まで通り動くようになった。

1
2
MacBookAir:program user$ xcode-select --install
xcode-select: note: install requested for command line developer Tools

なお、Command Line Toolsをインストールしたら、すぐにCommand Line Toolsのアップデートが来た。

同じタグの記事
  • ありません。
同じカテゴリの記事

macでスクリーンショットを撮る

macでスクリーンショットを撮る

macでもスクリーンショット(画面のハードコピー)を取得したい。

画面全体のスクリーションショット

control + command + 3

選択範囲のスクリーンショット

control + command + 4

選択したウィンドウのスクリーンショット

control + command + 4 からの Space

マウスカーソルがカメラに変わるので、スクリーンショットを取得したいウィンドウをクリックする。

同じタグの記事
  • ありません。
同じカテゴリの記事

EclipseLinkでJPA

EclipseLinkでJPA

EclipseLinkを利用し、JPAでデータベース更新をしようと考えた。
サンプルを作成し、動かしてみたが下記のような課題が検出された。

実装について

  • データ登録(INSERT)

事前に作成しておいたEntityクラスのインスタンスを作成し、そのプロパティをセット→EntityManager.persist(entity)で
レコードの登録ができる。お手軽。
EntityTransaction.commit()を実行しないとデータ更新はされない。

  • データ更新(UPDATE)

更新対象レコードのEntityをEntitiManager.find(Entity.class, pk)で取得し、取得できたEntityのプロパティを更新するだけで、
レコードの更新ができる。お手軽。
更新はEntityManager.persistする必要もない。
EntityTransaction.commit()を実行すればよい。
登録のアクションが必要ないのは不安に思われることもあるかもしれないが、
エラー時はEntityManager.rollback()すれば更新されないので、更新忘れがなくて良い仕様だと思う。

  • データ削除(DELETE)

これもとても簡単。EntityManager.find()で取得したentityをEntityManager.remove(entity)するだけ。

  • データ取得(SELECT)

キーで取得するのは簡単。EntityManager.find(Entity.class, pk)で取得できる。簡単。
リストで取るときは、多少癖がある。
また、いくつか異なるアクセス方法がある。

1.SQLを使う方法
2.JPQLを使う方法
3.CriteriaQueryを使う方法

1.はコンパイラ警告が出るので使わないほうが良いかと思う。(SuppressWarningsして使ってもいいけど)
2.の方法がとっつきやすい気がする。
3.CriteriaQuery、Root、などなど、よくわからないクラスを使う。サンプルを見ながらでも、どのクラスがどの役割なのかわかりにくい。

  • Entity作成にあたって

Entityクラスを生成するのは結構面倒。
特に複合主キーの場合。キーのみをクラス(内部クラスでも可)として定義する必要がある。
JPAでは主キーを単一項目にすることが推奨されているらしい。
すでに複合キーのテーブルで検証したため、なかなか面倒だった。

1
2
3
4
5
6
7
CREATE TABLE T01 (
    C01 CHAR(10) NOT NULL,
    C02 CHAR(2) NOT NULL,
    C03 VARCHAR2(100),
    C04 VARCHAR2(100),
    PRIMARY KEY (C01, C02)
)

上記のテーブルの場合、Entityは下記のようになる。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
package entity;

import javax.persistence.Column;
import javax.persistence.Embeddable;
import javax.persistence.EmbeddedId;
import javax.persistence.Entity;

@Entity(name = "T01")
public class T01 {

    @EmbeddedId
    public PK pk;

    @Embeddable
    public static class PK {
        @Column(name = "C01", nullable = false)
        public String c01;

        @Column(name = "C02", nullable = false)
        public String c02;

        public boolean equals(Object obj) {
            PK tgt = (PK) obj;
            return c01.equals(tgt.c01) && c02.equals(tgt.c02);
        }

        public int hashCode() {
            return (c01 + c02).hashCode();
        }
    }

    @Column(name = "C03", nullable = false)
    public String c03;

    @Column(name = "C04", nullable = false)
    public String c04;
}

実行環境について

  • EclipseLinkのバージョン

最新バージョンは2.7.0。これはjava8以降で動作する。
あえてjava7で利用したい場合は、2.6.4を利用する。

  • Entityをjarファイルにまとめている場合

Entityクラスがjarファイルに入っている場合は、persistence.xmlに設定が必要。
classファイルのまま、クラスパスにおいてある場合は、@Entityのクラスを自動的に読んでくれる。

jarファイルに入っている場合は、

1.Entityクラスをとして宣言しておく。
これはすべてのクラスをここに書かなくてはならないので、追加・変更時のメンテンナンスがなかなか大変。

2.Entityクラスが入っているjarファイルをに宣言しておく。
これであれば、jarファイル内の@EntityのクラスをEntityとして自動的に読んでくれる。

ただし、jarファイルを参照するパスが独特なので注意する必要がある。
絶対パスで指定する場合は、あまり気にしなくてよいが、通常はディレクトリ構成に左右されないように相対パスで指定すると思う。

カレントディレクトリはクラスパスで最初に見つかったMETA-INF/persistence.xmlが存在するディレクトリとなる。
たとえば、top_dir/conf_dir/META-INF/persistence.xmlの様にpersistence.xmlが存在する場合、top_dir/conf_dirがカレントディレクトリとなる。
したがって、top_dir/libにエンティティが収められたjarが保存されていた場合、persistence.xmlには下記のように書く。
../lib/my_entities.jar
ここに宣言されたjarファイルはクラスパスを追って読むわけではないので注意が必要。

同じタグの記事
同じカテゴリの記事

jconsoleでリモート接続するために

jconsoleでリモート接続するために

java作成された常駐アプリが、元気に動いているかどうか確認したい場合がある。
jconsoleで接続すれば、グラフィカルにCUPやメモリの状況を確認できる。
サーバで動くアプリの場合、サーバのGUIに接続できれば、特に準備などなしにjconsoleで接続できるが、
サーバのGUIに接続できない場合、クライアントのjconsoleから接続する必要がある。
そうしたいときはjavaの常駐アプリを起動する時に引数を与えておく必要がある。

1
java -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=12345 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false test.JavaProgram

このように、test.JavaProgramを起動すると、ローカルのjconsoleからport:12345で接続できるようになる。

また、常駐アプリがtomcatの場合、setenv.shに下記の設定を追加すれば良い。

1
export CATALINA_OPTS="$CATALINA_OPTS -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=12345 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false"

なお、setenv.shは$CATALINE_HOME/binに作成すれば良い。

また、$CATALINE_HOMEはtomcatを解凍したディレクトリの事(中にbinやconf,webappsが入っているディレクトリ)。

ヒープの利用状況、GC実行状況が見えたり、CPU使用率、スレッド数など、活動状況を確認できる。
また、MBeansに接続できるので、オリジナルのアプリであれば、外部インターフェースとしても利用できる。

サーバがLinuxでssh接続できるのであれば、ssh -X で接続して、サーバのXを転送する方法もある。
しかし、Xクライアントによっては、画面は見えるけどMBeanの引数を設定できなかったりする。

同じタグの記事
同じカテゴリの記事

Template Engine Mustache を使う

Template Engine Mustache を使う

mustacheはテンプレートエンジン。
様々な言語で使えるように準備されている。
JavaScript,Python,PHP,Perl,Java…
私が普段利用する言語では一通り利用できる。

なので、一通り利用してみようと考えた。
しかし、実際に使ってみると、言語によっては準備が面倒だったりした。

ネットワークが自由に使える環境であれば、どの言語でも簡単にセットアップできるが、
ネットワークが限られている職場の環境では、モジュール一つコピーして利用するということはできなかった。
上記の一覧の中で、唯一できたのはJavaScript。

mustache.jsを使う

とりあえず、下記のサンプルコードを。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
<!DOCTYPE>
<html>

<head>
    <meta charset="utf-8">
    <title>mustache test</title>
</head>

<body>
    <div id="target">Loading...</div>
    <script id="template" type="x-tmpl-mustache">
        * Hello {{name}}!<br>
        # 2 * 3 = {{calc}}<br>
        {{#mapList}}
            * {{firstName}} {{lastName}}<br>
        {{/mapList}}
        {{#simpleList}}
            - {{.}}<br>
        {{/simpleList}}
    </script>

    <script src="mustache.js"></script>
    <script>
        window.setTimeout(function() {
            var template = document.getElementById('template').innerHTML;
            var data = {
                name: "Luke",
                calc: function() {
                    return 2 * 3;
                },
                simpleList: [
                    "one","two","three"
                ],
                mapList: [
                    {firstName: "fname", lastName: "lname"},
                    {firstName: "fname2", lastName: "lname2"}
                ]
            };
            var rendered = Mustache.render(template, data);
            document.getElementById('target').innerHTML = rendered;
        }, 1500);
    </script>
</body>

</html>

テンプレートとデータを準備し、下記の処理でテンプレートを展開する。

1
var rendared = Mustache.render(template, date);

簡単に利用できた。

他の言語でも、環境さえ整えることができれば同じように使えるので、
覚えておいてもいいかもしれない。

同じタグの記事
同じカテゴリの記事

perlワンライナー

perl ワンライナー

大きなファイルが存在する。この大きなファイルの中の特定の文字列を置き換えたい。
perl ワンライナーの出番。

1
$ perl -pe 's/xxx/X01/g;s/yyy/X02/g' in_file > out_file

これでxxxはX01に、yyyはX02に置換される。
本当は、こんな単純な条件で置換してしまうと、余計なところまで置換されそうなので、もう少し悩む必要がある。

ちなみに、perlのオプションの-eが直後のコマンドを実行するということ。-pはファイルを読み込んで出力すること。

ここまで簡単な編集なら、awkでもできる。

1
$ awk '{gsub("xxx", "X01");gsub("yyy", "X02");print}' in_file | tee out_file

gsubが文字列置換。検索対象文字列には正規表現が利用できる。
subという関数もあるが、こちらは最初のマッチのみを置換する。
gsubは3つ目の引数に置換対象の文字列をしていできるが、省略すると$0が入る。
printも引数を省略すると$0が入るので、行ごとに処理し、置換が終わったら出力される。

teeは標準入力をファイルに出力するコマンド。 > out_fileでも良いとは思うが、一応コマンドを使っておく。

同じタグの記事
同じカテゴリの記事

python3で数値のlistを文字列のlistに変換

python3で数値のlistを文字列のlistに変換

数値のlistを作って、画面に表示させたい時、’,’.join(num_list)が使えない。
mapを噛まlistせて、中身をstrに変換してから呼び出す。

1
2
num_list = [1, 3, 5, 7, 9]
print(",".join(map(str, num_list)))

下記の通り表示される。

1
1,2,3,4,5

なお、本当にデバッグ的な出力であれば、リストに変換することで表示できる。

1
2
num_list = [1, 3, 5, 7, 9]
print(list(map(str, num_list)))

下記の通り表示される。

1
['1', '3', '5', '7', '9']
同じタグの記事
同じカテゴリの記事

ORACLEのMERGE文 補足

ORACLEのMERGE文 補足

WHEN MATCHED THENとWHEN NOT MATCHED THENの順番は、どちらを先に書いても良い。

存在しないときはインサート、存在したら更新というイメージであれば、
WHEN NOT MATCHED THEN、WHEN MATCHED THENの順番で書けば良い。

WHEN MATCHED THENまたはWHEN NOT MATCHED THENのどちらかだけを書いても良い。

WHEN NOT MATCHED THENのみを使うことで、レコードが存在しなかったらインサート、存在した場合は何もしないというのが書ける。
少し乱暴な気がするけど、ちょっとしたツールであればこれで十分だと思う。

WHEN MATCHED THENのみ使うのは、なかなか想定できない。
UPDATE文はもともとから打ちしても、更新レコード数が0になるだけだし。

同じタグの記事
同じカテゴリの記事

コマンドラインの最大長を確認する

コマンドラインの最大長を確認する

コマンドプロンプトで実行するバッチ処理へ引数を指定する場合、コマンドラインが長くなってしまうことがある。
WindowsのCMD.exeはコマンドラインの長さの限界が短いため、気をつける必要がある。

WindowsXP以降の場合、8,191文字指定できる。
もう、動いているサーバはないと思うが、
Windows2000,NT4.0では2,047文字指定できる。

引数に環境変数を展開したりすると、コマンドラインがとても長くなってしまうことがある。
特に警告もなく、後ろが切れてしまうので注意が必要。

ちなみに、Linuxの場合はコマンドを実行して確認する。

1
2
$ getconf ARG_MAX
2621440

上記の結果は、Red Hat Enterprise Linux Server release 6.5 (Santiago)の場合。

macOS high Sierraでは

1
2
$ getconf ARG_MAX
262144

Red HatとmacOSとでは、コマンドラインの長さが一桁違った。どちらにしてもWindowsと比べたら圧倒的に長いことは確実だが。

同じタグの記事
同じカテゴリの記事