Hatena::ブログ(Diary)

130単位

2009-03-31

2月分の読書記録

3月末ですが、すっかり忘れていた2月分まとめです。

印象深いのは、なんといっても『大東京トイボックス』。ゲーム制作会社というありそうでなかった設定をベースに、性格豊かなキャラがうまく描かれています。ゲームに造詣が深いほど、より楽しめるのではないかと思います。社内で局部的に回し読みしたりしましたが、みなさん「4巻出るのまだー?」と評価は上々。

マンガ以外では『インターネット的』がよかったです。

2月分読書データ

※3/31にデータ取得したら「3月」とでてしまいましたが、まぁ気にしません。

f:id:deeeki:20090331022148j:image

2月の読書メーター
読んだ本の数:14冊
読んだページ数:1871ページ

大東京トイボックス 3 (3) (バーズコミックス)大東京トイボックス 3 (3) (バーズコミックス)
1冊の中で伏線回収が見事に決まってて、心地よい読後感。
読了日:02月27日 著者:うめ
大東京トイボックス 2 (2) (バーズコミックス)大東京トイボックス 2 (2) (バーズコミックス)
髪が伸びてくのが新しい、と思った
読了日:02月26日 著者:うめ
3年で辞めた若者はどこへ行ったのか―アウトサイダーの時代 (ちくま新書)3年で辞めた若者はどこへ行ったのか―アウトサイダーの時代 (ちくま新書)
座右の銘は"公私混同"。仕事も余暇も人生として楽しむ」
読了日:02月25日 著者:城 繁幸
Adventure Life 〜愛する人と、自由な人生を〜Adventure Life 〜愛する人と、自由な人生を〜
「大人がマジで遊べば、それが仕事になる」
読了日:02月22日 著者:高橋 歩
大東京トイボックス 1 (1) (バーズコミックス)大東京トイボックス 1 (1) (バーズコミックス)
表情豊かなキャラたちが良い。百田モモのおでこと眉毛がすき。
読了日:02月21日 著者:うめ
インターネット的 (PHP新書)インターネット的 (PHP新書)
リンク、シェア、フラット。2001年刊行とは思えないほどの、現在にも通じる的確な内容。
読了日:02月19日 著者:糸井 重里
聖☆おにいさん 1 (1) (モーニングKC)聖☆おにいさん 1 (1) (モーニングKC)
設定勝ち。作者は女性だとは思ったけど、予想外に若い年齢で驚いた。
読了日:02月18日 著者:中村 光
NARUTO 巻ノ45 (45) (ジャンプコミックス)NARUTO 巻ノ45 (45) (ジャンプコミックス)
牛×タコに度肝を抜かれた。
読了日:02月16日 著者:岸本 斉史
会社は2年で辞めていい (幻冬舎新書)会社は2年で辞めていい (幻冬舎新書)
転職者を受け入れる側としても学ぶものがあった
読了日:02月14日 著者:山崎 元
Seasar2入門Seasar2入門
Webでは別にあるSAStrutsS2JDBCの解説が1冊にまとめられてる
読了日:02月13日 著者:ひが やすを
すごいやり方すごいやり方
「いま、うまくいってることはなに?」
読了日:02月05日 著者:大橋 禅太郎,倉園 佳三
「関係の空気」 「場の空気」 (講談社現代新書)「関係の空気」 「場の空気」 (講談社現代新書)
空気の問題は日本語の問題でもあり
読了日:02月05日 著者:冷泉 彰彦
ドラゴンクエスト列伝 ロトの紋章 ~紋章を継ぐ者達へ~ 7 (ヤングガンガンコミックス)ドラゴンクエスト列伝 ロトの紋章 ~紋章を継ぐ者達へ~ 7 (ヤングガンガンコミックス)
ワンピのあとに読んでみたら物足りなさ過ぎた
読了日:02月03日 著者:藤原 カムイ,梅村 崇,堀井 雄二
ONE PIECE 巻52 (52) (ジャンプコミックス)ONE PIECE 巻52 (52) (ジャンプコミックス)
めまぐるしく展開される数々の戦闘。面白すぎる。
読了日:02月01日 著者:尾田 栄一郎

読書メーター


関連記事:

1月分の読書記録 - 130単位

2009-03-30

Red Hatでyum install tomcat5 エラーとその対処

サーバーへJavaのWebアプリ導入の練習 - 130単位

の後日談的な。

導入した先はRed Hat Linux。バージョンは忘れましたがおそらく最新のものかと(【追記】「Red Hat Enterprise Linux Server release 5.3 (Tikanga)」でした)。

んで、Tomcatのバージョン。これが6を想定してたんですが、実際は5でした。超あせりました。

が、サーバー搬入業者さんによる手順書が付属してたので、とりあえずその通りやってみることに。といってもyumなんですが。

yum install tomcat5

インストールコマンド実行。

Loaded plugins: rhnplugin, security
Setting up Install Process
Parsing package install arguments
Resolving Dependencies
--> Running transaction check
---> Package tomcat5.i386 0:5.5.23-0jpp.7.el5_2.1 set to be updated

バージョンは5.5.23のようです。で、35個(計32MB)のパッケージがだーっと出て

Complete!

となりました。で、設定ファイルにjdkのパスを記述して、Tomcat起動。手順書はここまで。

service tomcat5 start
Starting tomcat5: lock file found but no process running for
pid 5853, continuing
/usr/bin/rebuild-jar-repository: error: Could not find xml-commons-apis Java extension for this JVM
/usr/bin/rebuild-jar-repository: error: Some detected jars were not found for this jvm
                                                           [  OK  ]

[ OK ]なんて出てますが、なんかエラーっぽいです。さかのぼってみると、yum installの際にも同様のエラーが出てました。

  Installing     : tomcat5-server-lib                              [34/35]
  Installing     : tomcat5                                         [35/35]
/usr/bin/build-jar-repository: error: Could not find xml-commons-apis Java extension for this JVM
/usr/bin/build-jar-repository: error: Some specified jars were not found for this jvm

こんなときはエラー文言でググってみるのがコツです。

Could not find xml-commons-apis Java - Google ????

が、結果が超少ない(6件)。他の文言でもググってみても、なかなか情報は得られず。どうもTomcattarアーカイブ解凍インストールするのが一般的なようです。

しかし、ダメ元で読んでみた英語のページに解決法が載っていました。

404 Not Found

yum search xml-commons-apisしてみて、見つかればyum installできるよ」とのこと。

yum install xml-commons-apis

で、

Installed: xml-commons-apis.i386 0:1.3.02-0.b2.7jpp.10
Complete!

これで問題なくTomcatが起動するようになり、無事解決となりました。


※ちなみにCentOS5.2では、「yum install tomcat5」のみでOKでした。

2009-03-25

サーバーへJavaのWebアプリ導入の練習

近々、RedHat Linuxへの導入作業を控えています。ほとんど経験がないので、VM仮想マシン(CentOS 5.2)を新たにこしらえて、ひととおりの手順を実行してみました。そのメモを残してみたいと思います。ざっくりとしたものなので、コマンドなどの詳細はリンクされているページを参照ください。間違った記述がありましたらすいません。

リモート接続設定

  • 固有IPを設定
    • system-config-network-tui
  • 許可するポートの設定 (http、ssh)
    • system-config-securitylevel-tui

関連記事:
Linux 固定IPの設定とポートの開放手順 - 130単位

JDKインストール

Javaアプリケーションサーバー構築(Tomcat6) - CentOS自宅サーバー構築
http://centossrv.com/tomcat6.shtml

上記ページを参考に。

chmod +x jdk-6u12-linux-i586-rpm.bin

Tomcatインストール

JDKの参考ページを引き続き参考に。

wget http://ftp.riken.jp/net/apache/tomcat/tomcat-6/v6.0.18/bin/apache-tomcat-6.0.18.tar.gz
tar -xzf apache-tomcat-6.0.18.zip 
mv -f apache-tomcat-6.0.18 /opt/tomcat

Apacheインストール

Webサーバー構築(Apache) - CentOS自宅サーバー構築
http://centossrv.com/apache.shtml

上記ページを参考に。

yum -y install httpd
  • confファイルを編集
    • 「ServerName」は、ドメインを取得していないと意味がないっぽい

Tomcat自動起動設定

Javaアプリケーションサーバー構築(Tomcat6) - CentOS自宅サーバー構築
http://centossrv.com/tomcat6.shtml

まずはこちらの方法で試す。

  • 自動起動により、Tomcatのサンプルページを見るまではいけた
  • けど、追加したWebアプリのページがうまく表示されず
  • tomcat/bin/startup.shを手動で実行したらいけた
Tomcat自動起動設定準備

やはり自動起動させたいので、

“安全”のためにTomcatを理解し、構築し、動作させる (1/3) - @IT
http://www.atmarkit.co.jp/fjava/rensai4/safetomcat_01/safetomcat_01_1.html

こちらの方法に切り替え。

  • jsvc.tar.gzを/tmpへ移動
  • tarコマンドで解凍
  • autoconfを実行するも、autoconfがないといわれる
-bash: autoconf: command not found
wget http://ftp.gnu.org/gnu/autoconf/autoconf-2.61.tar.gz
./configure --prefix=/usr
make
  • autoconf再実行→configure
  • 今度はsh configureでエラー
*** C-Language compilation tools ***
checking for gcc... no
checking for cc... no
checking for cl.exe... no
configure: error: no acceptable C compiler found in $PATH
See `config.log' for more details.
yum groupinstall "Development Tools"
autoconf
sh configure
make
  • jsvcファイルができる
  • jsvcの所有者を専用ユーザーに変更
  • jsvcをtomcat/bin/以下へ移動
  • 不要なファイル等を削除
Tomcat自動起動設定作成
  • 起動スクリプトを作成
    • 上記参考ページのものから、以下の部分のみ変更
JAVA_HOME=/usr/java/default
CATALINA_HOME=/opt/tomcat
  • 実行権限付与
  • chkconfigへ追加
chkconfig jsvc on
  • 起動
/etc/rc.d/init.d/jsvc start

ApacheTomcatの連携

  • Apacheのproxy_ajp.confを編集
vi /etc/httpd/conf.d/proxy_ajp.conf
  • 記述を追加
ProxyPass /app/ ajp://localhost:8009/app/
/etc/rc.d/init.d/httpd reload
  • これで「:8080」なしでアクセス可能
    • 8080ポートも閉じてok

Webアプリ用の設定

chown -R tomcat. /opt/app/
  • これで表示ok

いやはや、自動起動に苦労しました。

2009-03-23

IE8(Sleipnir)とSafariとChromeでAcid3 Test

IE8(Sleipnir)とSafariとChromeでAcid2 Test - 130単位

の続きです。

今回はAcid3 Testを試してみます。Safari4とChrome2.0の両ベータ版も検証に加えてみました。

The Acid3 Test
http://acid3.acidtests.org/

Acid3 Test 描画結果

Sleipnir2.8.4+IE6

f:id:deeeki:20090323015145j:image

Sleipnir2.8.4+IE8

f:id:deeeki:20090323015020j:image

IE8

f:id:deeeki:20090323014943j:image

Safari3

f:id:deeeki:20090323014829j:image

Safari4β*1

f:id:deeeki:20090323022221j:image

Chrome1.0

f:id:deeeki:20090323014853j:image

Chrome2.0β*2

f:id:deeeki:20090323022248j:image

雑感

合格したのはSafari4βのみとなりました。Chrome2.0βはスコアは100ですが、「LINKTEST FAILED」と表示されています。それにしても、スコアだけで比較するとIE8はかなりダメっぽく思えてしまいますね。

Sleipnir+IE8は、Acid2のときと同様にIE7の描画結果と同一かと思われます。

Wikipediaによれば、合格したブラウザは今のところ2つのようです。

IE8(Sleipnir)とSafariとChromeでAcid2 Test

IE8(Sleipnir)とSafariとChromeでベンチマーク - 130単位

の続きです。

せっかくなので、Acid2 Testも各ブラウザでやってみました。

The Second Acid Test
http://www.webstandards.org/files/acid2/test.html

Acid2 Test 描画結果

Sleipnir2.8.4+IE6

f:id:deeeki:20090323023044j:image

Sleipnir2.8.4+IE8

f:id:deeeki:20090323014707j:image

IE8

f:id:deeeki:20090323014513j:image

Safari3

f:id:deeeki:20090323014550j:image

Chrome1.0

f:id:deeeki:20090323014618j:image

雑感

IE8+Sleipnirが予想に反してうまくいっていません。SleipnirレンダリングエンジンはIEと同一という認識でいましたが、どうも間違っていたようです。Sleipnir側のバージョンアップで対応されるものなのであれば、それに期待したいと思います。ちなみにWikipediaをみてみると、IE7の描画結果に酷似しているのが確認できます。

蛇足ですが、合格した場合に鼻のあたりにマウスオーバーすると青くなります(その状態でキャプチャしてます)。

引き続き、Acid3 Testをやってみます。

*1:4 Public Beta 528.16

*2:2.0.169.1

2009-03-22

IE8(Sleipnir)とSafariとChromeでベンチマーク

SleipnirでIE8のjscript.dllを試す - 130単位

の続きです。

前回はdllのみでしたが、正規にIE8本体をインストールしました。

f:id:deeeki:20090326013128j:image

というわけで再度ベンチマーク実験。前回同様にSunSpiderです。

SunSpider JavaScript Benchmark
http://www2.webkit.org/perf/sunspider-0.9/sunspider.html

ベンチマーク結果

dllのみのSleipnirIE8×Sleipnirは、ほぼ差はない感じです。素のIE8だともう少し速いです。カスタマイズして拡張機能がもろもろ入ったSleipnirなので、それが影響しているのかもしれません。

インストール済みの他のブラウザもついでに計測してみました。SafariIE8の3分の2くらい。そしてGoogle Chromeはぶっちぎりの数値をたたき出してました。

 Sleipnir
+IE8jscript.dll
Sleipinir
+IE8
IE8SafariChrome
total 17185.0ms16895.8ms14846.2ms9536.2ms2763.0ms
3d: 1953.2ms1946.4ms1953.4ms1188.8ms405.2ms
 cube:637.6ms646.6ms634.4ms360.0ms64.4ms
 morph:593.6ms574.8ms603.4ms418.6ms251.4ms
 raytrace:722.0ms725.0ms715.6ms410.2ms89.4ms
access2590.8ms2609.4ms2625.0ms1409.8ms154.4ms
 binary-trees:559.2ms565.8ms559.6ms187.0ms11.2ms
 fannkuch:968.8ms978.2ms1000.0ms677.8ms44.0ms
 nbody:650.0ms643.4ms656.2ms384.8ms61.8ms
 nsieve:412.8ms422.0ms409.2ms160.2ms37.4ms
bitops: 2019.2ms2060.0ms2028.4ms941.4ms121.6ms
 3bit-bits-in-byte:315.6ms309.6ms312.6ms164.0ms10.6ms
 bits-in-byte:337.6ms344.0ms340.4ms235.6ms20.6ms
 bitwise-and:834.4ms859.4ms837.8ms302.4ms37.0ms
 nsieve-bits:531.6ms547.0ms537.6ms239.4ms53.4ms
controlflow: 365.6ms365.8ms362.8ms216.2ms6.4ms
 recursive:365.6ms365.8ms362.8ms216.2ms6.4ms
crypto: 1034.4ms1035.2ms1038.4ms695.2ms134.6ms
 aes:471.8ms466.0ms469.0ms229.8ms45.6ms
 md5:281.2ms287.6ms287.8ms221.6ms52.8ms
 sha1:281.4ms281.6ms281.6ms243.8ms36.2ms
date: 1409.4ms1422.4ms1412.4ms993.4ms300.6ms
 format-tofte:718.6ms725.2ms724.8ms413.6ms148.8ms
 format-xparb:690.8ms697.2ms687.6ms579.8ms151.8ms
math: 1662.8ms1628.0ms1687.6ms1310.6ms230.6ms
 cordic:640.4ms634.2ms662.6ms531.2ms109.8ms
 partial-sums:481.6ms453.0ms484.6ms518.0ms89.6ms
 spectral-norm:540.8ms540.8ms540.4ms261.4ms31.2ms
regexp556.0ms543.8ms537.8ms557.4ms622.8ms
 dna:556.0ms543.8ms537.8ms557.4ms622.8ms
string: 5593.6ms5284.8ms3200.4ms2223.4ms786.8ms
 base64:2865.8ms2725.2ms597.0ms345.8ms64.6ms
 fasta:793.6ms750.2ms762.8ms553.8ms117.6ms
 tagcloud:653.0ms634.4ms637.2ms393.8ms198.6ms
 unpack-code:612.4ms553.2ms559.4ms418.2ms273.6ms
 validate-input:668.8ms621.8ms644.0ms511.8ms132.4ms

追記:

Safari4βとChrome2.0も検証してみました。totalの値のみ載せます。

 Safari3Safari4βChrome1.0Chrome2.0β
total 9536.2ms2968.4ms2763.0ms1994.6ms

Safariが大幅に速度向上してChromeに肉薄しています。が、Chromeも3分の2程になっています。

検証環境

OS
Windows XP SP3 32bit
CPU
Pentium4 2.53GHz
メモリ
1.00GB RAM
IE8
バージョン 8.0.6001.18702
Sleipnir
バージョン 2.8.4
Google Chrome
バージョン 1.0.154.48
Safari
バージョン 3.2.2 (525.28.1)

関連リンク

IE8 / Firefox3 / Google Crome ベンチマーク対決 :: Drk7jp
http://www.drk7.jp/MT/archives/001484.html

こちらでFirefoxとの比較が載っています。

2009-03-21

SleipnirでIE8のjscript.dllを試す

Internet Explorer 8 : かつてない新機能
http://www.microsoft.com/japan/windows/products/winfamily/ie/function/default.mspx

IE8の正式版がリリースされました。Sleipnir使い*1の自分としては大きなニュース。

で、いきなりアウトローな感じではありますが、以前から気になっていた以下のTipsを試してみることにしました。

Sleipnir(Trident)でJavascriptの実行速度を高速化できる裏技 Sleipnirist
http://sleipnirist.blog26.fc2.com/blog-entry-250.html

手順

  1. IE8インストーラダウンロードします
  2. 32bitWinXPの場合、ファイル名はIE8-WindowsXP-x86-JPN.exeです
  3. 解凍ソフト(Lhazなど)でインストーラの中身を見ます
  4. jscript.dllを取り出します
    f:id:deeeki:20090321073724j:image
  5. Windowsをセーフモードで再起動します(通常では上書きできないため)
  6. windows\system32\jscript.dllバックアップしておきます
  7. windows\system32\jscript.dllを上書きします
    f:id:deeeki:20090321073720j:image
  8. 再起動します

ベンチマーク結果

SunSpider JavaScript Benchmark
http://www2.webkit.org/perf/sunspider-0.9/sunspider.html

こちらのサイトで検証してみました。

OS
Windows XP 32bit
CPU
Pentium4 2.53GHz
メモリ
1.00GB RAM

上記環境でのベンチマーク結果です。

TESTSleipnir 2.8.4
+ IE6
Sleipnir 2.8.4
+ IE8jscript.dll
COMPARISON
TOTAL: 144250.8ms 17185.0ms 8.39x as fast
3d: 3778.4ms 1953.2ms 1.93x as fast
  cube: 965.6ms 637.6ms 1.51x as fast
  morph: 1175.4ms 593.6ms 1.98x as fast
  raytrace: 1637.4ms 722.0ms 2.27x as fast
access: 5015.8ms 2590.8ms 1.94x as fast
  binary-trees: 1703.2ms 559.2ms 3.05x as fast
  fannkuch: 1556.4ms 968.8ms 1.61x as fast
  nbody: 931.2ms 650.0ms 1.43x as fast
  nsieve: 825.0ms 412.8ms 2.00x as fast
bitops: 4013.0ms 2019.2ms 1.99x as fast
  3bit-bits-in-byte: 1090.8ms 315.6ms 3.46x as fast
  bits-in-byte: 1078.2ms 337.6ms 3.19x as fast
  bitwise-and: 944.0ms 834.4ms 1.13x as fast
  nsieve-bits: 900.0ms 531.6ms 1.69x as fast
controlflow: 1343.8ms 365.6ms 3.68x as fast
  recursive: 1343.8ms 365.6ms 3.68x as fast
crypto: 2644.0ms 1034.4ms 2.56x as fast
  aes: 934.6ms 471.8ms 1.98x as fast
  md5: 869.0ms 281.2ms 3.09x as fast
  sha1: 840.4ms 281.4ms 2.99x as fast
date: 2362.6ms 1409.4ms 1.68x as fast
  format-tofte: 1125.0ms 718.6ms 1.57x as fast
  format-xparb: 1237.6ms 690.8ms 1.79x as fast
math: 3021.8ms 1662.8ms 1.82x as fast
  cordic: 1149.8ms 640.4ms 1.80x as fast
  partial-sums: 750.0ms 481.6ms 1.56x as fast
  spectral-norm: 1122.0ms 540.8ms 2.07x as fast
regexp: 722.0ms 556.0ms 1.30x as fast
  dna: 722.0ms 556.0ms 1.30x as fast
string: 121349.4ms 5593.6ms 21.7x as fast
  base64: 81749.8ms 2865.8ms 28.5x as fast
  fasta: 1337.6ms 793.6ms 1.69x as fast
  tagcloud: 9699.8ms 653.0ms 14.9x as fast
  unpack-code: 1449.8ms 612.4ms 2.37x as fast
  validate-input: 27112.4ms 668.8ms 40.5x as fast

およそ8倍程度速くなったようです。iGoogleの表示など、体感的にも速くなったと思います。

ただ、これはあくまでJavaScriptの話。レンダリングに関してはIE6のエンジンのままなので、ACID2テストは散々です。

f:id:deeeki:20090321084300p:image

さて、このたび正式リリースされたわけで、IE6のままでいる理由も特にありません。ので、普通にIE8インストールしようと思います。

*1:自宅では

2009-03-19

jQuery 指定した文字列をハイライトするプラグイン

やりたいこと:
検索結果から、検索した文字列をハイライトしたい

jQueryプラグインとかないか探してみたら、ありました。

highlight: JavaScript text higlighting jQuery plugin
http://johannburkard.de/blog/programming/javascript/highlight-javascript-text-higlighting-jquery-plugin.html

MITライセンスとなっています。あまりメジャーではないのか情報が少なめだったので、本家サイトを参考に導入手順を残しておいてみます。

使い方

1. jQuery本体とプラグインの読み込み

<script>タグでjQuery本体、jquery.highlight-3.jsの順に読み込み

<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="jquery.highlight-3.js"></script>
2. スタイルシートハイライト用のクラスを記述

クラス名は「highlight」固定、背景色などは自由に記述

.highlight { background-color: yellow }
3. ハイライトを適用する

検索対象となる要素集合(任意)のjQueryオブジェクトに対して、ハイライトしたい語句を引数にしてhighlight()メソッドを呼ぶ

$(".target").highlight("さがす語句");
4. ハイライトを取り除く

取り除きたい要素集合(任意)のjQueryオブジェクトに対して、removeHighlight()メソッドを呼ぶ

$(".target").removeHighlight();

留意点

空文字(「""」)を渡すと、ブラウザが固まってしまいます。実際にやらかしまして、見たこともないChromeダイアログが現れたりしました。ので、記念にキャプチャ。

f:id:deeeki:20090319022303j:image

空文字の場合は処理しないようにすべきでしょう。

コードサンプル

以下、画面遷移した直後にハイライトを適用するコード例です。検索フォームと結果が同一画面で、#keywordとid指定したテキストボックスに入力内容を保持しているとします。

<script type="text/javascript">
$(function(){
    var keyword = $("#keyword").val();
    if (keyword != "") {
        $(".target").highlight(keyword);
    }
});
</script>

【追記】

新たに記事とサンプルを作成しました。

2009-03-18

Social IMEを2週間ほど使用してみた

Social IME 〜みんなで育てる日本語入力〜
http://www.social-ime.com/ 

ユーザーが登録した単語を共有できる、フリーの日本語入力ソフトウェアです。先月のプレスリリース以来、1500を超えるブックマークを集めて非常に注目されています。

仕事でも顔文字を入力したいという適当な理由から、インストールして2週間ほど使ってみました(※バージョンはベータ版17)。

良い点

  • フリー
  • 相当な種類の顔文字デフォルトで入っている
  • MS IMEに存在しない単語が入っている
    • 「さいばん=採番」が入っていたりした(MS IME2003には無かった)

残念な点

  • 初回入力時に数秒フリーズする
    • どうもアプリ毎に発生するっぽい?
  • たまに大量の文字化けが起こる
    f:id:deeeki:20090318010328j:image
  • アルファベット入力から戻せなくなる
    • [無変換]キーでいけると思うのだけど…(自分が無知なだけかも)
  • 【追記】アルファベット入力について
    • 全角モードで[Shift]+[CapsLock]で大文字入力にすると、同時にアルファベット入力になる
    • もう一度[Shift]+[CapsLock]で元に戻る
    • [無変換]キーは効かない様子

今後の使用

で、残念な点に耐えかねて使用をやめようかと思って感想を記事にしようとした矢先。配布サイトを確認してみたらアップデートの情報が。

(2009/03/17) ベータ版20を公開しました。ソフトウェアキーボードに対応し、初回の変換が遅い問題を修正しました。

(2009/03/10) ベータ版19を公開しました。かな入力英語キーボードへの対応を強化しました。

(2009/03/08) ベータ版18を公開しました。文字化けバグのフィックスを行いました。

いやはや、となると上記の問題はだいたい解消されていそうです。

そんなわけで、最新版をインストールし直して、もうしばらく使ってみることにします。

2009-03-17

SAStruts 例外発生でエラーページに遷移

  • SAStrutsで、例外発生時にエラーページに遷移させたい。

これが今回やりたいこと。どうやらStrutsの機能でできるようです。以下はリファレンスの引用です。

struts-config.xml

<global-exceptions>
    <exception path="/error/norole.jsp" key="errors.norole"
        type="org.seasar.struts.exception.NoRoleRuntimeException"/>
</global>
Super Agile Struts - Feature Reference

これを参考に、struts-config.xmlに以下のように記述。実行時例外が対象です。

<global-exceptions>
    <exception path="/error.jsp" key="errors.system"
        type="java.lang.RuntimeException"/>
</global>

で、適当なアクションの実行メソッドにて、0で割る処理を入れて試してみました。すると、404となってしまいました。

HTTPステータス 404 - /app/error.jsp

なので、パスの書き方を「/WEB-INF/」からに変更してみました。

<global-exceptions>
    <exception path="/WEB-INF/view/error.jsp" key="errors.system"
        type="java.lang.RuntimeException"/>
</global>

これでうまくいきました。

2009-03-16

はじめてWEB+DB PRESSを読んでみた

WEB+DB PRESS Vol.49

『WEB+DB PRESS Vol.49』

ふと、立ち読みしてみました。表紙を飾っている特集記事の語句それぞれが、かなり自分の興味をそそるものだったので。

パラパラとめくっていき、目にとまったのが『良いコードへの道』というコーナー。比較的易しそうで、ちょうど学習中のJavaで書かれていたのが、まるまる読むきっかけとなりました。

内容は、配列(コレクション)を利用したコードを、うまく抽象化していく一連の過程の解説。自分にとってためになるようなTipsがいくつもでてきました。

  • YAGNI(You Aren't Going to Need It)
    • どうせいらない→だからまず必要なことだけシンプルに書く
  • メソッドに切り出して、コードの意図を含んだメソッド名を意識する
  • 「ペアで管理すべき変数」は「1つのオブジェクト」へ
  • 抽象化の貢献度合いを後で振り返り、判断能力や先読み能力を養う

また、JSPのサンプルコードに、今まで考えたこともなかったような書き方が載っていました。わずか数行でしたが、ものすごく衝撃を受けました。

というわけで、そのまま購入したのでした。まだ読んでいませんが他の記事も楽しみです。

書店に立ち寄るのは二・三ヶ月ぶりだったのですが、思わぬ良質な発見が得られたりすることを再確認。定期的に足を運びたいものです。

2009-03-15

マリエールで菓子まき体験

友人の結婚式に出席してきました。ご祝儀を出す立場としては人生初です。

これ以上ない幸せな空間を共有させていただいて、心から感動しました。

f:id:deeeki:20090314230037j:image

披露宴のラストに「お見送りのあと、新郎新婦からもうひとつのプレゼントがございます」なんてアナウンスされまして。吹き抜けのロビーに移動後、スタッフの方から出席者へ渡されたのはビニール袋。どうやら菓子まきが行われることが判明。幼少の頃に体験した以来です。

懐かしさを感じつつ、素直に楽しんでみました。アグレッシブなおじさんがいたりして苦戦しましたが、それなりにゲットできたんではないかと思います。

f:id:deeeki:20090314230034j:image

二次会ではビンゴゲームで景品をいただきました。当たったのは女性用美顔器*1。…うれしくなくはないです。

*1:お値段的には相当なもの

2009-03-14

プログラマ度診断をやってみた

プログラマ度診断
http://www7.plala.or.jp/keny01/consult/exam.html

via :  プログラマ度診断結果 - Yamkazu's Blog

ちょっと気になったのでやってみました。15個の質問に答えると結果が出ます。

f:id:deeeki:20090314050346j:image

プログラマ
80%
プログラマ適正
A

でした。

性格診断まとめ

  • 考えて行動、チャンス逃しがち
  • 人に対してクール
  • 計画性と対応力
  • 感情よりも理屈
  • 好奇心と追求心と飽きっぽさ

…チャンスをものにできるようになりたいです。

続きを読む

2009-03-13

jQuery getJSON()でセレクトボックスの項目を動的生成

SAStruts アクションにJSONを返すメソッドを作成してみる - 130単位

前回の続きです。やりたいことは以下。

部署: 従業員:

  • 2つのセレクトボックス
  • 片方の選択により、Ajaxでもう片方の項目を動的生成

前回はSAStrutsサーバー側のJSONを返す処理を作成しました。今回はクライアント側のJavaScriptです。jQueryを使います。getでJSONを取得するメソッドのリファレンスを確認します。

jQuery.getJson( url, data, callback )

HTTP(GET)通信でJSON形式のデータを読み込む。

no title

引数は順に、リクエストURLパラメータ、コールバック関数、です。

これを、部署のセレクトボックスのonChangeイベントに設定します。

$("#departmentId")
    .change(function(){
        $("#employeeId").empty();

        var departmentId = $(this).val();
        if (departmentId == "") {
            return;
        }
        
        $.getJSON(
            "ajaxEmployeeList",
            {"departmentId" : departmentId},
            function(employeeList){
                var optionItems = new Array();
                optionItems.push(new Option("", ""));
                for (key in employeeList) {
                    optionItems.push(new Option(employeeList[key], key));
                }
                $("#employeeId").append(optionItems);
            });
    });

簡単に解説してみます。

  1. 従業員のセレクトボックスを空にする
  2. 選択中の部署idを取得 → 空白なら何もせず
  3. getJSON()でAjaxリクエスト
    1. リクエストURLを指定
    2. 部署idをパラメータに指定
    3. 返されたJSON(従業員のid-nameのリスト)をセレクトボックスに設定

ちなみに上記コードのリクエストURLの指定は、SAStrutsでは同アクション内にメソッドを定義した場合です。URLの最後に"/"は入れても入れなくてもいいみたいです。

ただし、これだとFirefox等では動きますがIE6では動きません。

IEjQueryでselectのoptionを追加できない - toyosystem
http://www.jamboree.jp/cms/archives/90

どうもIE6バグでappend()がうまくいかないようです。というわけで、上記記事を参考にIE6に対応するようにしてみます。

IE6対応版

select要素のDOMを利用して、options[]プロパティに1つずつ追加していきます。

$.getJSON(
    "ajaxEmployeeList",
    {"departmentId" : departmentId}
    function(employeeList){
        var select = document.getElementById("employeeId");
        var i = 0;
        select.options[i++] = new Option("", "");
        for (key in employeeList) {
            select.options[i++] = new Option(employeeList[key], key);
        }
    });

IE6対応版その2

社内にあったとあるソースコードではこんなやり方をしていました。html文字列を配列に格納しておいて、最後に連結して追加しています。この場合だとjQueryのappend()が効くようです。

$.getJSON(
    "ajaxEmployeeList",
    {"departmentId" : departmentId},
    function(employeeList){
        var optionItems = new Array();
        optionItems.push('<option value=""></option>');
        for (key in employeeList) {
            optionItems.push('<option value="' + key + '">' + employeeList[key] + '</option>');
        }
        $("#employeeId").append(optionItems.join());
    });

4873114683
jQueryクックブック

4844329618
jQuery逆引きマニュアル Webデザインの現場で役立つ基本と実践

2009-03-11

SAStruts アクションにJSONを返すメソッドを作成してみる

部署: 従業員:

このような2つのセレクトボックスがあって、部署の選択に応じて、従業員のセレクトボックスを動的に生成したいとします。

これを、Ajaxを使ってSAStrutsで実現しようとしてました。

StringBufferの例

アクションにAjaxリクエスト用のメソッドを作成します。

パラメータの部署idはアクションフォームで定義されているとします。

@Execute(validator = false)
public String ajaxEmployeeList() {
    List<Employee> employeeList = employeeService.findByDeptId(form.depertmentId);
    
    StringBuilder buf = new StringBuilder(100);
    buf.append("{");
    for (Employee emp: employeeList) {
        buf.append("\"");
        buf.append(emp.id);
        buf.append("\":\"");
        buf.append(emp.name);
        buf.append("\",");
    }
    buf.setLength(buf.length() - 1);
    buf.append("}");
    
    ResponseUtil.write(buf.toString(), "text/javascript");
    return null;
}

idとnameさえ得られれば良いので、単純にStringBufferで書いてみました。最後にユーティリティクラスのResponseUtilを使ってJSONを出力しています。ちなみに、最初はgetEmployeeList()という名前にしようとしたのですが、Getterと解釈されるっぽいので違う名前にしました。

ただ、やはりどうもコードにすっきり感がありません。

で、なんとなく「json」と書いてコード補完をしてみたら、「JSONSerializer」なるクラスを発見。serialize()というメソッドがあり、どうやらこれで出来そうです。

JSONSerializerの例

追記:修正した記事↓を書きました。なお、JSONSerializerは非奨励とされています。
SAStruts JSONを返すアクションメソッド 修正編 - 130単位

※ org.seasar.framework.util.JSONSerializerをインポートします。

@Execute(validator = false)
public String ajaxEmployeeList() {
    List<Employee> employeeList = employeeService.findByDeptId(form.depertmentId);
    
    HashMap<String, String> map = new HashMap<String, String>();
    for (Employee emp: employeeList) {
        map.put(emp.id, emp.name);
    }
    
    ResponseUtil.write(JSONSerializer.serialize(map), "text/javascript");
    return null;
}

コードを短くするなら、エンティティのListをそのままJSONに変換してもいいと思います。その際エンティティに導出プロパティがあった場合、正しく定義していないと例外が発生してしまうので注意が必要です。

Content-Type

ResponseUtil#write()の第二引数にContent-Typeを指定していますが、JSONは"application/json"とするのが本来は正しいようです。

JSONのContent-Typeは application/json(管理人日記) - むぅもぉ.jp
http://muumoo.jp/news/2006/09/26/0applicationjson.html

ちなみに第二引数なしだと"text/plain"になります。"application/json"と"text/javascript"と"text/plain"、それぞれのContent-Typeを各ブラウザで試してみましたが、IE6/Firefox3/Safari/Chromeどれでも問題ありませんでした。

ところが

記事を書くにあたってリンクを張ろうとしてみたら、以下のような記述が。

推奨されていません。 このクラスの代わりにJSONIC等を使用してください

JSONSerializer (Seasar2 Framework 2.4.48 API)

JSONからの変換の際に、うまくいかないケースがあるようです。

[#CONTAINER-339] [S2Container] JSONSerializer を deprecated にしました.代わりに JSONIC 等を使用してください. - The Seasar Foundation Issues
https://www.seasar.org/issues/browse/CONTAINER-339

参考リンク

というわけで、JSONICを使うように修正したいと思います。以下参考記事。

suz-lab - blog: S2JDBC - SAStruts - JSON - jQuery
http://suz-lab.blogspot.com/2008/09/s2jdbc-sastruts-json-jquery.html

SAStruts + JSONIC でバリデーションエラーをJSONで返す : json, sastruts, seasar | メモリークラフト
http://www.memorycraft.jp/2008/11/sastruts-jsonic-json.html

2009-03-10

S2JDBC テーブルを利用した独自仕様のid採番メソッド

AS400DB2では、通常ではトランザクションが扱えないようです。ただし、ジャーナル処理を設定すれば扱えるようになるみたいです。*1

で、今回の案件

  • ジャーナルは作成しない
  • IDはテーブルを使って採番

という方針があり、それと関連してFOR UPDATEについてあれこれ調べたりしてました。

DB2で「SELECT ... FOR UPDATE」のロックを検証 - 130単位
S2JDBC DB2DialectでのforUpdate()を調べてみた - 130単位

さて、Javaには「synchronized」という修飾子があるそうです。これをメソッドの宣言に記述すれば、排他処理が行えるとのこと。

Java スレッド排他制御 synchronizedメソッド‐ニコニコ動画(ββ)
http://www.nicovideo.jp/watch/sm2346912

というわけで、S2JDBCのサービスにid採番用のメソッドを書いてみます。

  • 採番用テーブルのカラムはkeyとvalueのみ
  • エンティティを作成してSQL自動生成で記述
  • 各サービスから扱えるようにAbstractServiceに定義
  • 最初の採番時、対象キーのレコードが無くても動作可
  • valueカラムの現在値=次に採番される値

こんな感じの仕様です。

public abstract class AbstractService<ENTITY> extends S2AbstractService<ENTITY> {

    public synchronized int generateId(String key) {
        int id;

        IdGenerator idGen = jdbcManager
            .from(IdGenerator.class)
            .where("key = ?", key)
            .getSingleResult();

        if (idGen == null) {
            id = 1;

            idGen = new IdGenerator();
            idGen.key = key;
            idGen.value = 2;
            jdbcManager.insert(idGen).execute();
        }
        else {
            id = idGen.value;

            idGen.value = id + 1;
            jdbcManager.update(idGen).execute();
        }
        return id;
    }
}

で、synchronizedが実際に効くのかどうか試してみましたが、いまいちわかりませんでした。

  1. トランザクションは無しに設定
  2. メソッドの採番中にユーザーAのみ分岐されるThread#sleep()を仕込む
  3. ユーザーAにて採番実行
  4. ユーザーBにて採番実行

こんな手順でやってみたのですが、synchronizedがない状態でも3の時点で止まってくれました。おそらく検証方法がまずいのか、理解が足りないかのどちらかかと思われますが…。考えてもわからないので、ひとまず一区切りとしたいと思います。

*1:間接的に触れているだけなので、曖昧な書き方ですみません

2009-03-08

S2JDBC DB2DialectでのforUpdate()を調べてみた

FOR UPDATEの自動生成

DB2Dialectを指定してS2JDBCSQL自動生成でforUpdate()を使うと、「 for update with rs」が付加されたSQLが発行されます。

select T1_.KEY as C1_, T1_.VALUE as C2_ from ID_GENERATOR T1_ where T1_.KEY = 'EMPLOYEE_ID' for update with rs

Db2Dialectのソースをのぞいてみると、そのような記述があるのが確認できます。ちなみにDb2DialectはS2Tigerの中に存在します。

利用できないメソッド

  • forUpdateNowait()
  • forUpdateNowait(CharSequence... propertyNames)
  • forUpdateWait(int seconds)
  • forUpdateWait(int seconds, CharSequence... propertyNames)

これらのメソッドはDB2では利用できません。UnsupportedOperationExceptionとともに、「DBMS(db2)ではサポートされていません。」というメッセージが表示されます。

  • forUpdate(CharSequence... propertyNames)

カラムを指定したforUpdateメソッドも利用できません。ただ、「FOR UPDATE OF ...」という構文がDB2にはあります。もしかしたら実際はできるのでは。そんなわけで、他のDialectを参考にしたりして少しいじってみることに。

脱線の結果

で、なんとなくわかったこと。どうやらテーブル名のエイリアスが指定されているとダメなようです。「FOR UPDATE OF」以降をカラム名のみで組み立てるようにしたら、とりあえず通るようにはなりました。

ただ、テーブル結合を伴う場合についても考慮する必要がありますし、そもそもDB2と他のDBMSとでは異なる挙動になっているのかもしれません。自動生成に関しては、素直にカラム指定なしのforUpdate()を使っておくのがいいと思います。

いちおういじってみたコードを載せておきます。

public class MyDb2Dialect extends Db2Dialect {
    @Override
    public boolean supportsForUpdate(final SelectForUpdateType type,
            boolean withTarget) {
        return type == SelectForUpdateType.NORMAL;
    }

    @Override
    public String getForUpdateString(final SelectForUpdateType type,
            final int waitSeconds, final Pair<String, String>... aliases) {
        final StringBuilder buf = new StringBuilder(100).append(" for update");
        if (aliases.length > 0) {
            buf.append(" of ");
            for (final Pair<String, String> alias : aliases) {
                buf.append(alias.getSecond()).append(", ");
            }
            buf.setLength(buf.length() - 2);
        }
        buf.append(" with rs");
        return new String(buf);
    }
}

関連記事:

DB2で「SELECT ... FOR UPDATE」のロックを検証 - 130単位

2009-03-07

DB2で「SELECT ... FOR UPDATE」のロックを検証

採番用テーブルによってidの採番を行う場合、「SELECT ... FOR UPDATE」を使えばよい、というのがここ1年で覚えた知識のひとつ。ただ、あまり深くは理解していませんでした。

一番の疑問点は、「FOR UPDATE」という文字列の指す意味。ふつうに訳すと「更新のための」となり、照会は問題なく行えそうな気がしてきます。仮に照会が行えるとしたら、極めて近いタイミングのアクセスがが発生した場合、重複したidができる可能性があることになってしまいます。

また、ロックの種類はおおまかに共有ロック(照会可能、更新不可)と排他ロック(照会・更新とも不可)があるようです。FOR UPDATEで実際に排他ロックが獲得できているのか、そのあたりも気になります。

というわけで、現案件Java×DB2で調べてみることにしました。原始的な方法しか思い浮かばない自分にとっては、デバッグモードのあるEclipseは都合がよかったです。

検証

手順は以下です。

  1. トランザクションを有効にする
  2. 採番用テーブルからレコードを取得
  3. その直後にEclipseブレークポイントを設定
  4. アプリケーションの停止中に、CSESQL実行して検証
--SQL例
select VALUE from ID_GENERATOR where KEY = 'EMPLOYEE_ID' for update with rs

SELECTによる照会は、FOR UPDATEの有無で2通り検証しています。更新に関しては、ふつうにUPDATEでidの値を更新できるかどうかです。

DB2は「分離レベル」というものでロックの強度を指定できるようなので、その違いで検証しています。

分離レベル「UR
単純な照会
FOR UPDATEつき照会
更新
分離レベル「CS

※初期設定では、WITH句がない場合と同じ

単純な照会
FOR UPDATEつき照会
更新
分離レベル「RS」
単純な照会
FOR UPDATEつき照会×
更新×
分離レベル「RR
単純な照会
FOR UPDATEつき照会×
更新×
FOR UPDATE OF ...

「FOR UPDATE OF (カラム名)」という指定方法もあるようです。WITH句と共存できるかどうかは試してないのですが、とりあえず以下のSQLではどちらもロックがかかりませんでした。

select VALUE from ID_GENERATOR where KEY = 'EMPLOYEE_ID' for update of VALUE
select VALUE from ID_GENERATOR where KEY = 'EMPLOYEE_ID' for update of KEY
単純な照会
FOR UPDATEつき照会
更新

まとめ

DB2でテーブルによる採番を行う場合、以下のようにすればidの重複は起こらないといえます。

  • FOR UPDATE句を指定する
  • WITH句で分離レベルを「RS」か「RR」にする

※少しでも同時実行性を高めるために、「RR」よりも「RS」を指定するのがいいと思われます。

また言葉の意味についてですが、「FOR UPDATE」が修飾しているのはロックではなく、照会なのだと思います。「(後に)更新するための照会」であるがゆえに、ロックが必要、というわけですね。おそらく。

参考リンク

@IT:RDBMSアーキテクチャの深層(4)  OracleDB2、ロッキング・メカニズムはこれだけ違う
http://www.atmarkit.co.jp/fdb/rensai/rdbmsarc04/rdbmsarc04_1.html

DB2 Universal Database  分離レベル
http://publib.boulder.ibm.com/infocenter/db2luw/v8/index.jsp?topic=/com.ibm.db2.udb.doc/admin/c0004121.htm

DB2 UDB V8.1 デザイン・ガイド:ロック -基礎編- 
http://www-06.ibm.com/jp/domino01/mkt/dminfo.nsf/doc/000D73E3

浮浪プログラマ始末書:[DB] 排他制御
http://blog.livedoor.jp/froo/archives/50661135.html

2009-03-05

ニコニコ生放送を見た

堀江貴文×ひろゆき」緊急生対談‐ニコニコニュース
http://blog.nicovideo.jp/niconews/2009/03/002528.html

一般会員なのでつながるか不安でしたが、見ることができました*1

f:id:deeeki:20090305223358j:image

記念にキャプチャしてみました。

異色の二人の対談、しかもネットを通じての生放送。

なんというか不思議な満足感を持ちつつ視聴させてもらいました。

f:id:deeeki:20090305223359j:image

アンケートもあったりしました。

なかなか面白かったので、もう一度やって欲しいです。

*1:途中で一回プレミアム会員さんにおゆずりさせられましたが

2009-03-03

SAStruts リンク記述におけるs:linkとhtml:linkの比較

http://localhost:8080/app/subapp/action/method/1

ホスト名以降、「メインアプリ/サブアプリ/アクション/メソッド/パラメータ」とします。

SAStrutsでこのURLにアクセスした場合の、<s:link>と<html:link>の挙動を比較してみます。

s:link

以下、公式リファレンスの引用です。

SAStrutsには、Strutshtml:link継承したs:linkが用意されています。 href属性を設定するときに、コンテキストルートを自動的に補完させる場合に使います。パスを/ではじめた場合は、コンテキストルートからみたパスになります。パスが/ではじまっていない場合は、JSPからみたパスになります。

Super Agile Struts - Feature Reference
JSP
<s:link href="">A</s:link>
<s:link href="link">B</s:link>
<s:link href="./">C</s:link>
<s:link href="./link">D</s:link>
<s:link href="../">E</s:link>
<s:link href="../../">F</s:link>
<s:link href="/">G</s:link>
<s:link href="/link">H</s:link>
出力html

想定される遷移先をコメントで示しています。

<a href="/app/subapp/action/">A</a>         <!-- 同じアクションのindexメソッド -->
<a href="/app/subapp/action/link">B</a>     <!-- 同じアクションのlinkメソッド -->
<a href="/app/subapp/action/./">C</a>       <!-- 同じアクションのindexメソッド -->
<a href="/app/subapp/action/./link">D</a>   <!-- 同じアクションのlinkメソッド -->
<a href="/app/subapp/action/../">E</a>      <!-- サブアプリのIndexアクション -->
<a href="/app/subapp/action/../../">F</a>   <!-- メインアプリのIndexアクション -->
<a href="/app/">G</a>                       <!-- メインアプリのIndexアクション -->
<a href="/app/link">H</a>                   <!-- メインアプリのLinkアクション -->
遷移先URL
A http://localhost:8080/app/subapp/action/
B http://localhost:8080/app/subapp/action/link
C http://localhost:8080/app/subapp/action/
D http://localhost:8080/app/subapp/action/link
E http://localhost:8080/app/subapp/
F http://localhost:8080/app/
G http://localhost:8080/app/
H http://localhost:8080/app/link

html:link

JSP
<html:link href="">A</html:link>
<html:link href="link">B</html:link>
<html:link href="./">C</html:link>
<html:link href="./link">D</html:link>
<html:link href="../">E</html:link>
<html:link href="../../">F</html:link>
<html:link href="/">G</html:link>
<html:link href="/link">H</html:link>
出力html
<a href="">A</a>        <!-- 同じアクションの同じメソッド、同じパラメータ -->
<a href="link">B</a>    <!-- 同じアクションの同じメソッド、linkパラメータ -->
<a href="./">C</a>      <!-- 同じアクションの同じメソッド、パラメータなし -->
<a href="./link">D</a>  <!-- 同じアクションの同じメソッド、linkパラメータ -->
<a href="../">E</a>     <!-- 同じアクションのindexメソッド -->
<a href="../../">F</a>  <!-- サブアプリのIndexアクション -->
<a href="/">G</a>       <!-- ドキュメントルート -->
<a href="/link">H</a>   <!-- 別のWebアプリ -->
遷移先URL
A http://localhost:8080/app/subapp/action/method/1
B http://localhost:8080/app/subapp/action/method/link
C http://localhost:8080/app/subapp/action/method/
D http://localhost:8080/app/subapp/action/method/link
E http://localhost:8080/app/subapp/action/
F http://localhost:8080/app/subapp/
G http://localhost:8080/
H http://localhost:8080/link

まとめ

基本的には、<s:link>を使うのが良いと思います。<html:link>だと、以下の場合に遷移先URLが異なってしまいます。

html:link 「/」で終わるURLの場合
http://localhost:8080/app/subapp/action/method/1/
A http://localhost:8080/app/subapp/action/method/1/
B http://localhost:8080/app/subapp/action/method/1/link
C http://localhost:8080/app/subapp/action/method/1/
D http://localhost:8080/app/subapp/action/method/1/link
E http://localhost:8080/app/subapp/action/method/
F http://localhost:8080/app/subapp/action/

<s:link>であれば、「/」で終わっていても同じURLになります。自動補完により、必ず絶対パスで出力されるためです。

2009-03-02

エクセル 集計時の小技3つ

タスクにてちょっとした集計をしようとした際に、自動化したいと思って調べたメモです。

別のシートを参照

'シート名'!セル
e.g.

現在のシートと「200901」というシートで、同じセルの差を計算

=B2-'200901'!B2

数値の正負を記号付きで表示

セルの書式設定([Ctrl]+[1])を開く → 表示形式タブの分類で「ユーザー定義」を選択

正の数のフォーマット;負の数のフォーマット;0のフォーマット
e.g.

全角で+か−か±を表示、さらに括弧でくくる (数字は2桁までを想定)

("+"#0);("−"#0);("±"0)

※ ダブルクォーテーションで囲わないと、半角とみなされてしまうので注意

セルの値に応じてマークを表示

IF関数を利用

=IF(条件式,真のときの値,偽のときの値)

※ 入れ子にすることで複数の条件分岐が可能

e.g.

2以下は▲、5以上は◎

=IF(B2<=2,"▲",IF(B2>=5,"◎",""))

※ 値に応じてセルの色を変えたい場合は、条件付き書式(メニューの書式→条件付き書式)を利用する


関連記事:

エクセル/複数のハイパーリンクをまとめて削除 - 130単位

2009-03-01

2年ぶり雪山

ホワイトピアたかす - 岐阜県高鷲のスキー場
http://www.whitepia.jp/

whitepia_01

上達は感じられなかったものの、ふつうにターンできるくらいの昔の感覚は取り戻せたんじゃないかと思います。

転んだりしてあちこち痛いですが、良い気分転換になりました。

ゲレンデ感想

コースマップ|ホワイトピアたかすスキー場
http://www.whitepia.jp/course/index.html
  • 中央のコース、センターウェイは幅が広くて滑りやすい
    • 雪も固くはない
    • 最後のほうにいくつかキッカー(ジャンプ台)がある
      • それに挑戦してみるのも楽しかったりする
  • 右側初級コース、パノラマウェイは幅が狭く平らな箇所もある
    • 初心者にはちょっと厳しい
  • 初心〜初級者は左側クワッドリフトからセンターウェイのループがおすすめかと

whitepia_03