技術メモ用のエントリ

技術者の宝石箱の続きエントリ

インデックス

一覧

DOM で複数選択可能なリストボックスを作成する(IE)

Internet Explorer(IE)で DOM を使って複数選択可能なリストボックスを作成する方法です。

var select = null;
if (navigator.appName.match(/Internet Explorer/)) {
    select = document.createElement("<select multiple>");
} else {
    select = document.createElement("select");
    select.multiple = true;
}

要求と要件の違い

要求
お客さんのこんなことをしたい、こんなことができるといいなという望み
要件
要求をシステム化「する」と決めたもの

お客さんは、自分がどんなことをしたいのかとか、どんなものが欲しいのかということをうまく説明できないことが多い。だから、要求は「開発する」(掘り起こす)もの。

うまく要求が掘り起こせたら、今度はシステム開発者がじゃあどういう仕様でどういうシステムを作ろうかと考える。だから、要件は「定義する」もの。

Maven2のpom.xmlのXMLスキーマ

Maven2 の pom.xml の XMLスキーマおぼえがき

<?xml version="1.0" encoding="UTF-8"?> 
<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"> 
</project>

Excelでファイルの最終更新日を取得する

Excel でファイルの最終更新日を自動で再計算する方法。

参考

インストラクターのネタ帳:ファイルの最終更新日時を取得したい−ユーザー定義関数

Ruby on Rails2.0で、NoMethodError in AdminController#index

書籍『RailsによるアジャイルWebアプリケーション開発』を Rails2.0 で作業していくと、scaffold :product のところで次のようなエラーが発生する。

NoMethodError in AdminController#index
undefined method `scaffold' for AdminController:Class

これは、Rails2.0 からは各種ライブラリ類がプラグインとして切り出されたためだそうだ。ということで、必要なプラグインを入れるとよい。

まずは、scaffolding プラグインから。

\workspace\depot>ruby script/plugin install scaffolding
+ ./MIT-LICENSE
+ ./README
+ ./Rakefile
+ ./init.rb
+ ./lib/scaffolding.rb
+ ./lib/templates/edit.erb
+ ./lib/templates/layout.erb
+ ./lib/templates/list.erb
+ ./lib/templates/new.erb
+ ./lib/templates/show.erb
+ ./test/scaffolding_test.rb

つぎに、paginate というプラグインを入れなければならない。scaffold だけ入れた状態だと次のようなエラーが発生する。

NoMethodError (undefined method `paginate' for #<0x4829610>):

ということで、paginate プラグインをインストールする。

\workspace\depot>ruby script/plugin install http://tools.assembla.com/svn/breakout/breakout/vendor/plugins/classic_pagination/
+ ./CHANGELOG
+ ./README
+ ./Rakefile
+ ./init.rb
+ ./install.rb
+ ./lib/pagination.rb
+ ./lib/pagination_helper.rb
+ ./test/fixtures/companies.yml
+ ./test/fixtures/company.rb
+ ./test/fixtures/developer.rb
+ ./test/fixtures/developers.yml
+ ./test/fixtures/developers_projects.yml
+ ./test/fixtures/project.rb
+ ./test/fixtures/projects.yml
+ ./test/fixtures/replies.yml
+ ./test/fixtures/reply.rb
+ ./test/fixtures/schema.sql
+ ./test/fixtures/topic.rb
+ ./test/fixtures/topics.yml
+ ./test/helper.rb
+ ./test/pagination_helper_test.rb
+ ./test/pagination_test.rb
 
 
Pagination
==========
 
To install:
 
  script/plugin install svn://errtheblog.com/svn/plugins/classic_pagination
 
This code was extracted from Rails trunk after the release 1.2.3.
WARNING: this code is dead. It is unmaintained, untested and full of cruft.
 
There is a much better pagination plugin called will_paginate.
Install it like this and glance through the README:
 
  script/plugin install svn://errtheblog.com/svn/plugins/will_paginate
 
It doesn’t have the same API, but is in fact much nicer. You can
have both plugins installed until you change your controller/view code that
handles pagination. Then, simply uninstall classic_pagination.

インストールすると、will_paginate を使ったほうが良いという警告がでる。なので、will_paginate も一緒にいれる。

\workspace\depot>ruby script/plugin install http://tools.assembla.com/svn/breakout/breakout/vendor/plugins/will_paginate/
+ ./README
+ ./Rakefile
+ ./init.rb
+ ./lib/will_paginate/collection.rb
+ ./lib/will_paginate/finder.rb
+ ./lib/will_paginate/view_helpers.rb
+ ./test/boot.rb
+ ./test/console
+ ./test/finder_test.rb
+ ./test/fixtures/admin.rb
+ ./test/fixtures/companies.yml
+ ./test/fixtures/company.rb
+ ./test/fixtures/developer.rb
+ ./test/fixtures/developers_projects.yml
+ ./test/fixtures/project.rb
+ ./test/fixtures/projects.yml
+ ./test/fixtures/replies.yml
+ ./test/fixtures/reply.rb
+ ./test/fixtures/schema.sql
+ ./test/fixtures/topic.rb
+ ./test/fixtures/topics.yml
+ ./test/fixtures/user.rb
+ ./test/fixtures/users.yml
+ ./test/helper.rb
+ ./test/lib/activerecord_test_connector.rb
+ ./test/lib/load_fixtures.rb
+ ./test/pagination_test.rb

これで、正常に動くようになる。

WebLogicでAPP-INFを使って共通Jarを配置するときは、ClassLoaderに注意する

WebLogic8.1 から EAR 直下の APP-INF/lib、APP-INF/classes に各モジュール(WAR)から利用される共通ライブラリ(JAR)やクラスを配置できます。これは WebLogic の独自仕様のようですが。

このとき、APP-INF 以下に置いたライブラリやクラスは各モジュール(WAR)とは別のクラスローダでロードされます。

参考

IBM: クラスローダーとJ2EEパッケージング戦略を理解する

EAR ルート
├ APP-INF    ← EAR クラスローダ(親)
│  ├ classes
│ └ lib
├ WAR1      ← WAR1 クラスローダ(子)
│ └ WEB-INF
└ WAR2      ← WAR2 クラスローダ(子)
└ WEB-INF

親のクラスローダで読み込んだクラスは子のクラスローダからは見つけることができますが、子で読み込んだクラスは親のクラスローダからは見つけることができません。

EAR クラスローダで読み込まれたクラスは各モジュールで共有されるため、static 領域のインスタンスや値も共有されます。

また、親と子のどちらで見つけたクラスを先に読み込むかによってシングルトンクラスの動作に影響が出たりすることがあります。

参考

IBM: クラスローダーを理解する - シングルトンがシングルトンでなくなる日

WebLogicが発行するSession Cookieのパスはデフォルトで / (スラッシュ)

WebLogic のデフォルト設定でのセッション Cookieのルールは以下の通り。

要素名 デフォルト値 説明
cookie-name JSESSIONID セッションIDの長さは52文字
cookie-path null デフォルトは / (スラッシュ)※1。デフォルト値では、ブラウザは、WebLogic Server で指定されているすべての URL にクッキーを送信する
cookie-domain null デフォルトは、クッキーを発行したサーバのドメイン※2
cookie-secure false Cookie を https 接続のときのみブラウザから送り出すか。
cookie-max-age-secs -1 無期限。ブラウザを閉じると削除される。
timeout-secs 3600 セッションタイムアウト時間。デフォルトで3600秒。

同一ホスト名でいくつものアプリケーションを管理している場合、WebLogic はデフォルトで、cookie-path を / にしてしまうため、セッションCookieの上書き(セッションIDの上書き)がされることがあります。きちんと path 属性をコンテキストパス、domain 属性を ホスト名に設定しましょう。はまりそうなので注意!

参考

BEA:weblogic.xml デプロイメント記述子の要素

※1 Cookieパスは /(スラッシュ):Cookie の仕様では、Cookie を送出するリクエストヘッダに含まれている要求したドキュメントのパスと同じになります。 ※2 サーバのドメイン:ホスト名ではないことに注意。Cookie の仕様では、domain を指定しない場合はサーバのホスト名になります。

FFFTPでシンボリックリンクを削除する方法

FFFTP でシンボリックリンクを削除する方法。

[コマンド(C)] -> [任意のコマンド(C)...]

を選択して、

DELE ファイル名

でOK。シンボリックリンクをプログラムから作っちゃったけど、削除できない〜ってなったのでメモ。サーバアカウントが発行されていて、コンソールにつなげる場合は、コマンドラインから削除すればOK。ロリポップは、FTP しかあいてなかったのであせった。

Railsをやってて気になったこと

Rest ちっくな URL で更新画面みたいなのの定義の仕方

/comment/new/preview 見たいな感じで定義する。

routes.rb map.resources :comment, :new => {:preview => :post}

Rest ちっくなアプリで Ajax によるサーバサイドバリデーションするURL

/comment/new/validate 見たいな感じでいいのかな。

routes.rb map.resources :comment, :new => {:validate => :post}

確認画面を挟む登録で、ファイルアップロードがある場合

attachement_fu を使ってうまくやる方法がわからなかったので、仕方ないから自分で一時ファイルの仕組みを作った。

※ そのうち追加するかも

Commons HttpClient のマルチパートで日本語ファイル名が文字化けする

Commons HttpClient を使って、日本語ファイル名のファイルをマルチパートでアップロードすると、ファイル名が文字化けします。 これ、ソースを追っていくと驚愕の事実が・・・。

org.apache.commons.httpclient.methods.multipart.FilePart#sendDispositionHeader

/**
 * Write the disposition header to the output stream
 * @param out The output stream
 * @throws IOException If an IO problem occurs
 * @see Part#sendDispositionHeader(OutputStream)
 */
protected void sendDispositionHeader(OutputStream out) 
    throws IOException {
  LOG.trace("enter sendDispositionHeader(OutputStream out)");
  super.sendDispositionHeader(out);
  String filename = this.source.getFileName();
  if (filename != null) {
    out.write(FILE_NAME_BYTES);
    out.write(QUOTE_BYTES);
    out.write(EncodingUtil.getAsciiBytes(filename));
    out.write(QUOTE_BYTES);
  }
}

ファイル名のエンコーディングを ASCII でやってる・・・。 Orz…

日本語ファイル名の文字化けを回避する方法ですが、私は FilePart を継承して sendDispositionHeader をオーバーライドして、Encoding を自分で指定できるようにしました。他にも、URLEncoding して、サーバ側で Decode するという方法もあります。

参考

HttpClientでの日本語ファイルのアップロード

JBoss Seamでログイン後にセッションIDを変更する

JBoss でSession#invalidate() した後に、HttpServletRequest#getSession(true) しても、セッションIDが新しくならい問題の解決方法。

JBoss サーバの $JBOSS_SERVER/deploy/jboss-web.deployer/server.xml の emptySessionPath 箇所を false に変更する。

<Connector port="8080" address="${jboss.bind.address}"    
         maxThreads="250" maxHttpHeaderSize="8192"
         emptySessionPath="false" protocol="HTTP/1.1"
         enableLookups="false" redirectPort="8443" acceptCount="100"
         connectionTimeout="20000" disableUploadTimeout="true" />

emptySessionPath は、セッションCookie のパスを &/& にする設定のようで、ポータルなどの別コンテキスト間でセッションを継続したい場合などに使う設定のようです。これが false でないと、JBoss で Session#invalidate しても、セッションIDが新しくならないっぽいです。

この値を設定したところ、JBoss Seam で Seam#invalidateSession を呼び出した後、新しくセッションIDが発行されるようになりました。

ということで、JBoss Seamのログイン後処理(PostLoginEvent)で一度セッションを新しくすると良いかもです。ただし、セッションを新しくした後、ログイン状態を保持する方法がわかりません。。。中身入れ替えるとかすればいいのかもですが、Seam#invalidateSession は、Seam の処理を抜けるときにセッションを破棄するので、その場では新しいセッションIDがとれません><; やり方、確認中です。誰かわかる人教えてください。。