忍者ブログ
雇われるだけの人生から目指せ独立、社会人2年目なゲーム脳SEのブログ。更新頻度=週2~3回。
[1]  [2]  [3]  [4
×

[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。

○要点
  • javaとjavacのバージョンを管理するのは面倒
  • whichコマンドがあれば楽にバージョンを調査できる
  • Windowsでもwhichコマンドが使えるバッチがある
  • Eclipseを使うならば、JAVA_HOMEは常に最新のJDKを指すようにして、開発環境用のJDK設定はEclipseからやるとよい

Javaエンジニアの一番の悩みは何って?javaとjavacコマンドのバージョン管理です。JAVA_HOMEなんて環境変数はもう二度と見たくないという人、正直に手を挙げてください。・・・はーい ノシ

JDKだけならともかく、Windows環境だとJREのjavaおよびjavawが勝手にC:\WINDOWS\system32以下に配置されるので、PATHの設定を間違えると「javaはバージョン1.6(しかも参照しているtools.jarはJREのもの)だけどjavacはバージョン1.4」なんていう悪夢が発生します。
するとJDKのjavaじゃないと走らないアプリが動かなかったりだとか、何故かJava5以上で書かれたソースがコンパイルできないとかそういう地獄絵図が・・・

で、よく考えたらLinuxのwhichコマンドを使えば一発解決じゃないかと思い立ちました。
でもWindowsには標準でwhichがありません。がーん。

しかしご安心あれ。世の中には同じことを考えている先駆者が居るのです。
ウィンドウズDOSのwhichコマンド(Hishidama's Windows DOS which-command)

これで簡単にjavaの指し示すパスが確認でき、管理が容易になります。

○余談
Eclipseで開発をしており、DOS窓からantを叩いたりしないならば、
javaもjavacもJAVA_HOMEの指し示す先も最新の1.6にして、Eclipseの中で開発中のJavaアプリ向けにJDKの設定をするといい感じみたいですね。
Eclipseから実行するのであれば、Antが実行するjavacのバージョンもEclipseの設定から自由に変更できます。
PR
Mac2日目。近況報告メモだけ。

Spacesの使い勝手が恐ろしく良いことに気づく。
マウスカーソルを左下に持って行く→Space切り替え
今度は右下に持って行く→ウィンドウを選択
こんな使い方をしている。面白い。

あと.bashrcを書き換えたり。

Ubuntuのサーバを設定し直し、WebDAVでSVNリポジトリに自由にアクセスできるようにした。
SSLも導入。MacBook AirからのSSHによるログインも出来た。
これで一通り設定は揃ったかな。

詳細については後日記事を書く予定。

いまどきStruts(笑)とか音速が遅すぎますが、Strutsの内部的な動作って意外なほど知られてません。
それとも私がそんな「知られていない程度の職場」にしか行ったことがないんでしょうか?おかしいな、結構どころじゃなく有名なんだけどな、今入ってる会社・・・
閑話休題。というわけで、近頃見つけたStrutsのtipsをいくつかまとめてみました。

○HTTPRequestの内容からrequestスコープのActionFormが生成される手順について
www.fireproject.jp/feature/struts/advanced/action_to_action.html
こちらのサイトが非常に詳しいです。
ポイントは「フォワード前のexecuteでHTTP要求のパラメータにあったActionFormのフィールドを上書きしても,フォワード後のexecuteまでに再びHTTP要求のパラメータで上書きされてしまう.」というところでしょうか。

よくあるんですよね。入力されてきたActionFormの値をActionで書き換えてJSPにフォワード。でも何故かJSPで書き換えた値を出力すると書き換えられていない。原因が分からない。分からないから別の名前で書き換えたActionFormをsetAttributeしちゃえーみたいな。でも実際それが一番の解決法だったりする。


○Struts ActionForm reset()メソッドとActionForm中のBeanについて
例ではよくcheckboxの状態をリセットするために使えと書いてますが、ActionFormにBeanを内包した場合にも併用が必須です。
public void reset(ActionMapping mapping, HttpServletRequest request) {
    //HTTPリクエストからパラメータ値を読み取って
    //本ActionFormに設定する前に必ず呼ばれる
    //ここでabesiBeanのオブジェクトを生成する
    super.reset(mapping, request);
    this.abesiBean= new AbesiBean();
}
このBeanをnewする処理を怠ると、

サーブレットが"abesiBean.name=abesi"のようなカンマで区切られたパラメータ付きのPOSTを受け取る

Action.doPost()が実行される

populate()・・・HTTPリクエストパラメータからActionFormを生成しようとする

"abesiBean.name"のようにHTTPリクエストで指定されているので、BeanUtilがカンマ処理を解決しようとする

でもabesiBeanはnullです、BeanUtil.populate()にnullを指定するとエラーになります

というわけでエラー(しかも一見して何が原因か分かりづらいエラー)
 
というオチになります。1.2.6での話なので、1.3ぐらいなら直っているかもしれません。
このオチだけならデバッグして本人が解決してくれればいいんですが、このエラーを一目見て原因不明と判断してActionFormにはBeanを入れてはいけませんみたいなルールを勝手に作って意味不明な実装をしている箇所が何カ所かあって、ずいぶんと絶望させられました。ひでえ。


フレームワークに乗せられているだけでは、決して良いプログラムにはならないのですね。
いったん凍結して、iPhone向けに作り直し。とにかく動けば何でもいい。
遠大な目標なんて立てても弱い自分はすぐに折れてしまう。
3日で動くようにならなくちゃダメだと思った。3日より気力が続かないから。

ちなみに、dev_appserverはそのまま起動してもlocalhost以外からアクセスできないので、
--addressオプションを指定してやる必要がありました。


dev_appserver.py --address 192.168.0.2 path/to/home


いったん区切りがついたので、
2ヶ月前からせこせこ作っていたGoogle App Engineのアプリケーションを本番環境にアップしてみました。
まったくのモックアップなので友人以外には見せられません。あしからず。
きちんとしたバージョンを何とかして早くアップしてご覧に入れたいものです。

さて、一応無事にリリースの真似事にまでこぎつけることが出来たので、
ソースコードの管理、具体的にはタグとかブランチの管理をしたいなぁ、と思い立ち、
ちょっと調べてみました。

プログラマの思索: Subversionのブランチを有効活用してアジャイルに開発せよ
プログラマの思索: 大規模プロジェクトはバージョン管理が重要になってくる

なるほど、ブランチといっても二種類あるんですね。
リリースブランチ
タスクブランチ
今回はリリースを行ったので、まずは本日の日付とリリースバージョンをタグ名(2008_07_07_ver0.0.1)にして、タグを作成します。タグを作ったら、Trunkから保守用のブランチを切り出すのが通例のようなのですが、わざわざ保守が必要なレベルのものでもないので、今回は切りません。

余談ですけど、保守(Maintenance)のよい短縮語って何なんでしょう?
Abbreviation Index
こ のページを見る限りだと、Maint, Main, Mai, Mntなどが挙げられていますが、MainとかMaiはイマイチ、MntだとMountと勘違いしてしまいそうです(特にLinuxなど・・・)。 Maintかなぁ。でもMaintってダサい・・・Mntがいいなぁ・・・

話を戻しまして、次の改修はモデルをとっかえひっかえ大いじりする大規模な改修になる予定ですので、(2008_07_07_TASK_TotalModelRevamp)←こんな名前をつけてタスクブランチを切ります。
これで遠慮なくソースをぶっ壊せる(Trunkからすぐに元に戻せるから)というわけです。
うーん、バージョン管理って便利ですね。一人開発でもこんなに使えるとは。

でも私が知っている現場ではろくな使われ方されている記憶がないですね。バージョン管理。
(タグ命名規則がないのでタグ一覧が滅茶苦茶だったり、そもそもバージョン管理の何たるかを知っているプログラマのほうが少ないため、バージョンクローズ時にデグレ発生しまくったり)

よいプロジェクトはよいバージョン管理からですね!
私がJavaを嫌いになった理由のひとつに、「ライブラリ管理が大変」であることがあげられます。たとえば、とある簡単なアプリケーションの中でJSONデータを扱いたくなったので、JSON-libをインストールすることにしましょう。
するとこれだけのdepandency(依存ライブラリ)が必要になります。
http://json-lib.sourceforge.net/
http://json-lib.sourceforge.net/dependencies.html
これを全部手で落として来い、と?あなたユーザを舐めてますね?

大規模なプロジェクトであればmaven2というプロジェクト&ライブラリ管理の決定版ツールがあるので、そちらに任せておけば全く問題が無いのですが、10クラス以内で収まるような軽量なプロジェクトのためにmavenの設定をしていたら、pom.xmlを書いている時間のほうが長くなってしまいそうです。要するに、ロクに使えません。

私としては、RubyのGemみたいに、
gem install json-lib 1.5
ってタイプするだけで依存ライブラリ含めてすべてのライブラリがダウンロードできるような仕組みが欲しいんです。ただのそれだけでよいのですが・・・とか思いながらいろいろと調べていた結果、
Raven
こんなものを発見しました!
なんとRuby Gem + RakeでJavaのプロジェクトの管理が出来るんだそうです。まさに欲しかったものはこれ。
早速インストールしてみました。

問題は、私Ruby初めてなんです。putsしかコマンド分かりません。
まぁスクリプト言語なんて何とかなるでしょ!
RubyGems の使い方 - WebOS Goodies

インストールしたら、まずはGemをプロキシの裏から通せるようにします。
プロキシ越しにGEM - 初心者Ruby頑張る。
要するに環境変数http_proxyを作るだけです。環境変数を使わなくちゃいけないのが少々気持ち悪いですが(同様の理由でJAVA_HOMEもあまり好きではありません)我慢。

あとはraven installコマンドを使うだけです。
raven install --proxy http://this.is.proxy.com:1111 commons-lang
これでcommons-langの最新バージョンが落ちてくるはずなのですが・・・なぜかプロキシのURLを認識してくれません。
ravenスクリプトの内部を覗いて調査してみましょう。
gem contents raven
これでインストールされているravenのコンポーネントが全部見れますから、あとはスクリプトの中をテキストエディタで覗くだけです。スクリプト言語の魅力はこのデバッグ性のよさというか、改変し放題なところですね。問題解決が簡単です。

ほどなくしてraven.rbの130行目が怪しいことに気づきました。
def self.parse_proxy(purl)  
  if (purl.length > 0)  
    match = purl.match('http://(.*):(.*)@([^/]*):([0-9]*)')  
    match = match.to_a  
    match.shift  
    puts "Using proxy #{match[2]} and port #{match[3]}"  
    [match[2], match[3].length == 
0 ? 80 : Integer(match[3]), match[0], match[1]]   else     nil   end end
どうやらプロキシを指定するURLが、正規表現にマッチしていなかったみたいです。
raven install --proxy http://u:p@proxy.com:1111 commons-lang
こんどはうまくいきました!無事にcommons-langの2.2がダウンロードされました!
WS000162.JPG

・・・て、あれ?2.2?
今の最新は2.3だろ?
嫌な予感がします。
raven install --proxy http://u:p@proxy.com:1111 commons-lang:2.3
raven: 2.3なんてねーよwwww

raven install --proxy http://u:p@proxy.com:1111 ezmorph
raven: ezmorph?何それ食えるの?

raven install --proxy http://u:p@proxy.com:1111 JSON-lib
raven: JSON-lib?何それ食えるの?
だめだこいつ・・・はやくなんとかしないと・・・
要するに、去年かおととしぐらいからravenのリポジトリ情報が最新化されていないみたいなんです。
おかげさまで新しいライブラリが全く使えません。
しかもこのravenマイナーなプロジェクトですから、ほかにリポジトリ情報がある場所もわからず・・・


と言うわけで結論。Ravenはいいシステムなんですが、メンテされてないです。使えません・・・

今度は
Apache Ivy, the agile dependency manager 
こんなのを試してみようと思います。
相変わらずGoogle App Engineのアプリを作成しています。
何とか来月一日までには本番環境にアップしていたいと考えていたのですが、遅々として進みません。正直アプリ作成をなめすぎていたと痛感しております。
今までやってきた仕事は全部「設計書があったり、すでに既存の動いているものがあるところを改修」でした。今はすべて自分がやらなくてはなりません。ゼロからものを作るのがこれほど大変だとは・・・
さらにだんだんと管理対象が増えてきて、脳みその容量が追いつかなくなってきました。どこから手をつければいいのか・・・いままでの自分の仕事が以下に甘かったかと痛感させられます。

世間の厳しさをようやく知ったところに、ひどい追い打ちが。
今日気づいたのですが、Google App Engineはトランザクション処理が弱いんです。

私の中でのトランザクション処理の常識(Java)は、
try{
int num = pstmt.executeUpdate();
pstmt.commit();
} catch(SQLException e) {
pstmt.rollback();
} finally {
pstmt.close();
connection.close();
}
こんなソースだったので、トランザクション処理なんて楽勝だろうと高をくくっていたのですが、
ふたを開けてみると、まぁまぁ出るわ出るわ、致命的な制限の雨・嵐。
  1. トランザクション内部でQueryは実行不可能、Keyを利用したgetのみ可能
  2. put()ならびにdelete()は1モデルインスタンスにつき1回のみ
  3. トランザクション処理中のモデルは、すべて一つのエンティティグループに属していなければならない。
  4. 現状、parentのいない親エンティティとそれを親にする子エンティティを同一のトランザクションで生成できない
事前にきちんとドキュメントを読み込んでいなかった自分が悪いし、何より分散DB環境なんだからこのぐらいの制約は当たり前だろうとも思いますが、しかしこれではトランザクションが使い物になりません。

上記の制約をまともに受けると、こんなソース(Python)になってしまいます。
try:
old_model1 = copy_model(model1)
model1 = edit_model1(model1, hogehoge)
result1 = db.run_in_transaction(update1, model1)
result2 = db.run_in_transaction(update2, model2)
except:
if result1:
#元の状態に戻す、ここで例外起きたら知らん(もう1つtry節が必要)
db.run_in_transaction(update1, old_model1)
これでは一貫性のあるトランザクションとは言えません。
うーん、困りました。こんなところにApp Engineの弱点があるなんて。
とりあえずはトランザクションのことを考えないで先に進めることにします。
難しい問題だからじっくり考える必要がありそうですね・・・


おまけ
ローカルで上記の制約を確かめようとテストしてみたのですが・・・
67bb062e.jpeg

f3bee166.jpeg

9f39c6aa.jpeg

あれ?ちゃんと登録できちゃうんですけど。
本番環境じゃないと再現できないんでしょうか・・・
Google App Engine用のライブラリってあまり聞かないなぁとふと思い立ちました。
そもそもGoogleの用意しているライブラリが優秀
Djangoも優秀
専用で用意しなくてもPython用のライブラリなら何でも使える
Python自体が最初からかなりの機能を持っている
App Engineの制約が大きいため突飛なことをするライブラリが必要とされない

いろいろ理由はありそうなんですが、
個人的には、db.Modelのプロパティに持たせるバリデータ関数のうち、
よく使いそうなものをライブラリにしたいんですよね。
たとえばこんな感じでValidatorってクラスを作ってみたい。
class FooBar(db.Model):
name = db.StringProperty(validator=Validator.length(3,8))
no = db.IntegerProperty(validator=Validator.value(1,100))
#複数のvalidatorを混ぜてみたりしたい
#lengthが10以下でalphabetかどうかチェックするならこう
test = db.StringProperty(validator=Validator.compose(
(Validator.length(0,10), Validator.alphabet())
)
どうでしょう、結構便利だと思うのですが。
ところでPythonで関数を関数から返却できるんでしょうか?と思い立って調べてみました。
Python 文法
http://morchin.sakura.ne.jp/effective_python/functional.html
おお、lambdaだと複数行が実行できないけど、defの中でdefすればうまくいきそうです!

というわけで今作っているアプリでも必要になりそうなので作ってみようかな。出来たら公開します。
前回までの作業で、自宅サーバでHTTPSが使用できるようになりました。
今度はSubversionとTracをHTTPSに対応させます。

といっても、何も特別な作業は必要ありません。
apache側のバーチャルホストの設定をすべてのページに対して適用しているので、
Subversion, Trac, どちらもすべてのページに対してSSLによる保護が適用されます。

WS000159.JPG

会社から試しにつないでみました。プロキシに阻まれることもなく、バッチリとリポジトリの中身が見えます。暗号化万歳です。

それではここからは今回の本題、SubversionとTracの連携を行ってみます。
Tracのチケット機能は便利なのですが、
  1. Tracでチケットを見る
  2. Eclipseで修正→Subversionでコミット
  3. Tracのチケットにコメントを書いてcloseする
これは煩雑で面倒なプロセスです。
SubversionのコミットコメントがTracのチケットのコメントになったり、
コミットと同時にCloseが行われたら、もっと楽になりますよね。
(むしろチケット=タスク管理とコミット=ソース管理を一体化させることこそがTracのチケットシステムの最大の魅力だと思うわけです)

というわけで設定を施してみました。参考サイトはこちら。
乳牛日記: Subversionのcommitコメントをtracチケットに反映させる
[Subversion][trac]チケットとコミットの連携設定: 30からのBlog
[Think IT] 第4回:チケットとソースコードを連携せよ! (1/3)

書いてあることはみんな一緒です。
「Subversionのpost-commitフックスクリプトから、Tracの専用Pythonスクリプトを呼び出す」
/usr/bin/python /home/web/trac/contrib/trac-post-commit-hook \
-p "$TRAC_ENV" \
-r "$REV"
これだけです!
ちなみに、上記サイトで設定されている-uとか-mオプションはTrac v0.11ではすでにdeprecatedにされており、v0.12で廃止されると明言されておりますので、使用しないようにしました。

さらにさらに、
気の向くままに・・・: trac-post-commit-hookでステータスも変更
こちらのページを参考にして、assigned #1のようにコマンド入力すると、チケットのステータスがnewからassignedになるようにしました。

早速コミットして実験してみましょう。
・・・とおもったのですが、うまくいきません。
デバッグログも表示されないですし、何が起きているのかさっぱりわかりません・・・

ん?まてよ・・・
編集が終わったら、「chmod a+x hooks/post-commit」と入力し、
実行ビットを立てるのを忘れないようにする
あああ!しまったシェルスクリプトなのに+xがついてなかったあああああ!!!

WS000161.JPG

chmodしたら一発で動くようになりました。ああ、酷いミスだ。

さらにもう一箇所問題が。
チケットのステータスをassignedに変更できるようにしたのですが、
trac v0.11から、assignedとは別にacceptedというチケットステータスが増えたみたいなのです。
TracWorkflow – The Trac Project – Trac
assignedとは別に、accept用のスクリプトを用意する必要がありそうです。
コミット時に、チケットのステータスをnewまたはassignedからacceptに変更するようにすればよさそうですね!
http通信ではプロキシの後ろからsubversionにアクセスできないという致命的問題がわかりましたので、https通信機能を自宅のサーバに追加いたしました。

Firefox3ではオレオレ証明書を使おうとすると
「Firefox3のオレオレ警告」@水無月ばけらのえび日記
こんなに厳しいご指摘が飛んでくるようになりまして、
スラッシュドット・ジャパン | オレオレ証明書の警告に「セキュリティ上の問題はございません」と解説する銀行が登場
やる気のないシステムを作った地方銀行もこれからオレオレ証明書サーバを作ろうとする私も非常に肩身が狭いのですが・・・まぁ個人用途ですから大目に見ていただきたいです。


ではさっそくやってみましょう。
HOWTO - Apache2 + Subversion + SSL - Ubuntu Forums
Ubuntuのフォーラムに名前からしてそのまんまの記事がありました。中身も非常にわかりやすいですし、これをそのままなぞらえていけば楽勝だろう・・・と考えていた時期が私にもありました。
sudo apache2-ssl-certificate
bash: そんなコマンドないよ♪

sudo apache2-ssl-certificate
bash: だからそのコマンドねーよwwwww
なん・・・だと・・・?
なんということでしょう。apache2-ssl-certificateがないのです。いつぞやのxorgconfが思い出されます(結局あれはdisplayconfig-gtkコマンドと言う別のコマンドがあるということで解決したのですが)。

しらべてみたら
apache2-ssl-certificate: command not found - Ubuntu Forums
Bug #77675 in apache2 (Ubuntu): “[regression] apache2-ssl-certificate has gone missing since feisty” 結構前からUbuntuのパッケージにapache2-ssl-certificateがないみたいです。こまりました。
でもよく見たら、フォーラムにこんな投稿がありました。
#setup

1. sudo apt-get install apache2
2. sudo apt-get install openssl
3. sudo apt-get install ssl-cert

#create ssl certificate:
sudo make-ssl-cert
/usr/share/ssl-cert/ssleay.cnf /etc/ssl/private/localhost.pem

#switch to apache sites configuration:
cd /etc/apache2/sites-available/

#これはバックアップを取るだけなのでどうでもいい
#bakup the default configuration:
sudo cp default default.backup.date

#これもポート設定だけなのでどうでもいい
#be sure to listen the port 80 for the default:
sudo sed -i '1,2s/\*/*:80/' default

#create the ssl configuration:
sudo cp default ssl

#ここから先は別の記事を参考にすればよいので省略

make-ssl-certコマンドで代用が効くらしいので、これでなんとかなりそうです!
試してみた結果、VirtualHostの設定を間違えてSSLヘッダーエラーが出た以外にさしたる問題も無く、一発でうまくいきました!

あとはVirtualBoxとルータのNAT設定をすれば完了です。
WS000155.JPG
ばっちりです!やったね!
カレンダー
08 2017/09 10
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
ブログ内検索
最新コメント
[11/13 DSLR-A850]
[08/29 逆援助交際]
[08/23 クンニ]
[08/22 熟女]
[08/19 痴漢]
はてなブックマーク
プロフィール
HN:
akisute
性別:
男性
職業:
システムエンジニア
趣味:
ゲーム・東方・ニコ動。あと散歩。
バーコード
推奨環境

横幅900px以上、Firefox 3, Safari 3, Opera 9.5, Chrome 0.2以上。IE7ギリギリ対応。IE6未対応。

忍者ブログ [PR]