潜伏バグからのロングフリーズ

Javaっぽいエンジニアの徒然草

scope属性

jspのscope属性でハマったのでメモ。

 

■参考

http://www.atmarkit.co.jp/ait/articles/0701/20/news017.html

http://struts.wasureppoi.com/jsp/01_scope.html

 

----------------------------------------------------------------------------------------------------

■scope属性

scope属性は、id属性で指定したスクリプティング変数の「スコープ」を指定する。

「変数の有効範囲」を表すもので、下記4種類のスコープが指定できる。

※scope属性を省略した場合は、デフォルトpageとして扱われる。

 

■scopeの種類

 スコープ変数の有効範囲備考
狭い page JSPページ 同一のJSPファイル内で、情報共有する
request HTTPリクエスト 同一クライアント/ブラウザ別に、
1回のリクエスト内で、情報共有する
session HTTPセッション 同一クライアント/ブラウザ別に、
複数のリクエストをまたいで、情報共有する
広い application Webアプリケーション Webアプリケーション全体で、情報共有する

 

■pageスコープ

スクリプティング変数の有効範囲がJSPページ内である」ことを意味する。

Javaのローカル変数と同様の振る舞い。

 

 

■requestスコープ

スクリプティング変数の有効範囲がHTTPリクエスト内である」ことを表す。

つまり、

 1.Webブラウザから届いたHTTPリクエストをWebコンテナが受信する

 2.WebコンテナがJSPサーブレットを呼び出し、HTTPリクエストを処理する

 3.処理結果のHTTPレスポンスをWebブラウザに送信する

この一連の処理が、requestスコープのスクリプティング変数の有効範囲となる。

 

 

■sessionスコープ

スクリプティング変数の有効範囲がHTTPセッション内である」ことを意味する。

 

「HTTPセッション」とは、クライアントごとに用意されるオブジェクトのことを表す。

sessionスコープのスクリプティング変数を利用することで、クライアントごとに異なる状態を保持できる。

 

使用例

・ショッピングカード内容を保存

・各ユーザーのログイン/ログアウト状態を記録

 

 

■applicationスコープ

スクリプティング変数の有効範囲がWebアプリケーション内である」ことを表す。

Webアプリケーション全体で1つの変数を共有する。

 

applicationスコープは、Webアプリケーション全体で共有したいデータ、

例えばマスターデータのキャッシュやアクセスカウント数などを保持する目的で利用する。

applicationスコープに保存された変数の値は、

WebアプリケーションをWebコンテナからアンロード(削除)するまでメモリ上に存在し続ける。

 

まとめは以上。

----------------------------------------------------------------------------------------------------

 

今回ハマった内容。

「scope指定無しで、親でsetしたsessionを見ようとしている」

 

scopeにrequestを指定するだけで解決したものの、中身の動きがいまいちわからない。

 

多分イメージとしてはこんな感じになる(はず)。

f:id:monokurotamago:20140204205559j:plain

 

・scope指定無しの場合はデフォルトpageとなる

・page → request → session → application という順に探す

という点から考えると、

今回の「scope指定無しで、親でsetしたsessionを見ようとしている」動作は不明。

 

後者だけ考えると、

①page見て存在しないと判断

②request見て存在しないと判断

③session見て親でセットした値があったから引っ張ろうとしたが、

 元の画面が違うのでエラーが起きた。

となり納得できる。

 

つまり、

・scope指定無しの場合はデフォルトpageとなる

のはセットする側の話なので読む際は無視。

読む時は、

・page → request → session → application という順に探す

だけ着目していれば良さそう。

 

まとめ。

前画面のsessionを持った状態で別窓にPOP UP出す場合は、

前画面のsession使わないように設定する必要がある。

 

Javaで定数定義したSQLを動的に変更する(=ただの置換) からの final修飾子のおさらい

JavaのStringでSQLを定義。

条件に応じて参照テーブルを変更する。

 ex) xxFlagがONの時はTABLE_1, OFFの時はTABLE_2を参照したい。

   それ以外の結合や絞込み条件などは全く一致する前提。

 

--------------------------------------------------------------------------------------

 

SQLを2つ書く方法】

何の捻りもなく、そのまんま。

 

private static final String SQL_SEARCH_1 =

"SELECT "

    + TABLE_1 + "." + field1 + ", "

    + TABLE_1 + "." + field2 + ", "

    + ・

    + ・

    + ・

+ " FROM "

    + TABLE_1

+ " WHERE "

    + 略

;

 

private static final String SQL_SEARCH_2 =

"SELECT "

    + TABLE_2 + "." + field1 + ", "

    + TABLE_2 + "." + field2 + ", "

    + ・

    + ・

    + ・

+ " FROM "

    + TABLE_2

+ " WHERE "

    + 略

 

;

 

メリット

・参照テーブル毎に(結合、絞込みなどの)条件を変えたい、といった変更に強い。

 

デメリット

・2重メンテが発生

・コードが冗長

 

--------------------------------------------------------------------------------------

 

【置換する方法】

 

// 置換用文字列

private static final String TABLE_X = "@TABLE_X@";

 

private static final String SQL_SEARCH =

"SELECT "

    + TABLE_X + "." + field1 + ", "

    + TABLE_X + "." + field2 + ", "

    + ・

    + ・

    + ・

+ " FROM "

    + TABLE_X

+ " WHERE "

    + 略

 

;

 

--------------------------

 

String sql = xxFlag ? SQL_SEARCH.replaceAll(TABLE_X , TABLE_1)

                                 : SQL_SEARCH.replaceAll(TABLE_X , TABLE_2);

 

Point

・置換用文字列は@で囲む等、普通は使用しない形で記載する(誤置換防止)。

 →例えば置換用文字列を「S」と定義すると、SELECTの「S」が置換されてしまう。

 

メリット

・コードが簡潔に書ける

 

デメリット

・参照テーブル毎に(結合、絞込みなどの)条件を変えたい、といった変更に弱い。

 

 

ちなみに、

 SQL_SEARCH はstatic finalだけど、replaceAllで変更できるの?

 ▶︎ 変更ではなく、新規Stringインスタンスが返るので問題なし!

 

 

一応JavaDocも確認。

 JavaDocのStringクラス

 ※1.5版から引用。古いけど多分変わってないはず。

java.lang.String

 public final class String

 extends Object

 implements Serializable, Comparable<String>, CharSequence

 

文字列は定数です。この値を作成したあとに変更はできません。

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

 

特に意識していなかったけれど、Stringクラスはfinalだったらしい。

 

■final修飾子メモ

 final クラス: サブクラスの作成ができなくなる

 final メソッド: オーバーライドができなくなる

 final 基本型変数: 変数の値の変更ができなくなる

 final 参照型変数: 変数の参照の変更ができなくなる

   ※setter/getterなどで、インスタンスの値変更はできる点に注意

   下記ケースはエラーにならずに正常に書き換えられる。

 

 

 

 

public class XxxBean {

 

    private String str;

    privateintnum;

 

    // constructor

    public XxxBean(String str, int num) {

        this.str = str;

        this.num = num;

    }

 

    // getter and setter

    public String getStr() {

        returnstr;

    }

    public void setStr(String str) {

        this.str = str;

    }

    public int getNum() {

        returnnum;

    }

    public void setNum(int num) {

        this.num = num;

    }

 

}

 

 

 

publicclass Test {

 

    public static void main(String [] args) {

        final XxxBean bean = new XxxBean("aaa", 1);

        bean.setStr("bbb");

        bean.setNum(2);

 

        System.out.println(bean.getStr());

        System.out.println(bean.getNum());

    }

 

}

 

 

仮に、

 bean = null;

と書いた場合はコンパイルエラーになる。 

 

 

homebrew -> rbenv で Rubyの準備

homebrewが入っている前提です。

 

■事前準備

1. homebrewを最新に。

$ brew update

 

2. 現状把握のため、homebrew経由でインストールした一覧を表示。

$ brew list

git

※この段階ではgitしか入っていない。

※rbenvの導入にgitが必要というわけではなく、別件でgitを導入したためこの状態。

 

readlineインストール

$ brew install readline

 

$ brew list

git readline

※導入成功を確認

 

■rbenvインストール

$ brew install rbenv

 

$ brew list

git rbenv readline

※導入成功を確認

 

ruby-buildインストール

$ brew install ruby-build

 

$ brew list

autoconf openssl rbenv ruby-build

git pkg-config readline

ruby-buildに必要と思われる、autoconf, openssl, pkg-configが勝手に入った模様。

※上記3つを自動で入れてくれたため、少し時間がかかった(数分程度)。

 

■rbenvで導入可能なRubyの一覧を表示

$ rbenv install -l  ◀︎最後の文字は「エル」

Available versions:

  1.8.6-p383

  1.8.6-p420

  1.8.7-p249

  1.8.7-p302

  1.8.7-p334

  1.8.7-p352

  1.8.7-p357

  1.8.7-p358

  1.8.7-p370

  1.8.7-p371

  1.8.7-p374

  1.8.7-p375

  1.9.1-p378

  1.9.1-p430

  1.9.2-p0

  1.9.2-p180

  1.9.2-p290

  1.9.2-p318

  1.9.2-p320

  1.9.2-p326

  1.9.3-dev

  1.9.3-p0

  1.9.3-p125

  1.9.3-p194

  1.9.3-p286

  1.9.3-p327

  1.9.3-p362

  1.9.3-p374

  1.9.3-p385

  1.9.3-p392

  1.9.3-p429

  1.9.3-p448

  1.9.3-p484

  1.9.3-preview1

  1.9.3-rc1

  2.0.0-dev

  2.0.0-p0

  2.0.0-p195

  2.0.0-p247

  2.0.0-p353

  2.0.0-preview1

  2.0.0-preview2

  2.0.0-rc1

  2.0.0-rc2

  2.1.0

  2.1.0-dev

  2.1.0-preview1

  2.1.0-preview2

  2.1.0-rc1

  2.2.0-dev

  jruby-1.5.6

  jruby-1.6.3

  jruby-1.6.4

  jruby-1.6.5

  jruby-1.6.5.1

  jruby-1.6.6

  jruby-1.6.7

  jruby-1.6.7.2

  jruby-1.6.8

  jruby-1.7.0

  jruby-1.7.0-preview1

  jruby-1.7.0-preview2

  jruby-1.7.0-rc1

  jruby-1.7.0-rc2

  jruby-1.7.1

  jruby-1.7.10

  jruby-1.7.2

  jruby-1.7.3

  jruby-1.7.4

  jruby-1.7.5

  jruby-1.7.6

  jruby-1.7.7

  jruby-1.7.8

  jruby-1.7.9

  maglev-1.0.0

  maglev-1.1.0-dev

  maglev-2.0.0-dev

  mruby-dev

  rbx-1.2.4

  rbx-2.0.0

  rbx-2.0.0-dev

  rbx-2.0.0-rc1

  rbx-2.1.0

  rbx-2.1.1

  rbx-2.2.0

  rbx-2.2.1

  rbx-2.2.2

  rbx-2.2.3

  ree-1.8.6-2009.06

  ree-1.8.7-2009.09

  ree-1.8.7-2009.10

  ree-1.8.7-2010.01

  ree-1.8.7-2010.02

  ree-1.8.7-2011.03

  ree-1.8.7-2011.12

  ree-1.8.7-2012.01

  ree-1.8.7-2012.02

  topaz-dev

 

Rubyっていっぱいあるのねー。

 

 

 

■2.2.0-devを入れてみる

$ rbenv install 2.2.0-dev

Cloning https://github.com/ruby/ruby.git...

Installing ruby-2.2.0-dev...

Installed ruby-2.2.0-dev to /Users/xxxxxx/.rbenv/versions/2.2.0-dev

 

■インストールしたバージョン一覧を表示

$ rbenv versions

* system (set by /Users/xxxxxx/.rbenv/version)

  2.2.0-dev

 

■使用バージョンを変更してみる

$ rbenv global 2.2.0-dev

$ rbenv versions

  system

* 2.2.0-dev (set by /Users/xxxxxx/.rbenv/version)

 

■使用バージョンをシステムデフォルトに戻す

$ rbenv global system

$ rbenv versions

* system (set by /Users/xxxxxx/.rbenv/version)

  2.2.0-dev

 

思ってたよりも簡単に、複数のRubyバージョンの共存ができました。

 

詐欺メールにご注意ください

以前携帯キャリアメールに大量の迷惑メールが来た時期がありました。
回避策として、長い+難しいアドレスに変更したのが数年前。
それ以来、迷惑メールとは無縁だったキャリアメールですが、
本日数年ぶりに受信したのでネタにしてみます。
 
-----ここから-------------------------------------------------------------------------------------
 
差出人: 三菱東京UFJ銀行 <maimai******@yahoo.co.jp>
日時: 2014年1月14日 12:53:43 JST
宛先: <************@hotmail.co.jp>
件名: 三菱東京UFJ銀行】本人認証サービス
 
***********************************************************************
   三菱東京UFJ銀行Eメール配信サービス

************************************************************************

2014年「三菱東京UFJ銀行」のシステムセキュリティのアップグレードのため、貴様のアカウントの利用中止を避けるために、検証する必要があります。
以下のページより登録を続けてください。

https://******************************login?*****ID=*********

――Copyright(C)2014 The Bank of Tokyo-Mitsubishi UFJ,Ltd.All rights reserved――

 
-----ここまで-------------------------------------------------------------------------------------

 

送信アドレス

 ▶︎一部伏せてます。色々とヒドいアドレスです。騙す気が感じられません。

  カタツムリ臭がぷんぷんします。

 

宛先アドレス

 ▶︎一部伏せてますが、自分のアドレスとは全く関係ないものが表示されていました。

  携帯キャリアメールで受信しているのに、hotmailとは如何なものでしょう。

  BCCによる大量一括送信臭がぷんぷんします。

 

文中アドレス

 ▶︎間違って押さないように伏せてます。

  リンク先にて暗証番号などを入力させるフィッシングサイトなのか、

  はたまたウイルスが仕込まれているのか不明ですが、

  なんらかの仕掛けがあるのは間違いないので押さないに越したことはありません。

 

言うまでもありませんが

 ▶︎銀行からこういうメールが送られてくることは 有 り 得 ま せ ん 。

  騙されないようにお気をつけください。

 

なお

 ▶︎三菱東京UFJ銀行(本物)から忠告も出ているようです。

  http://www.bk.mufg.jp/info/mail_chuui/

  銀行さんも大変ですね。

 

以上。

かの有名なORA-00600に遭遇した話

以前(2013/10/19)業務中に起こったお話。

 

業務アプリからOracleにアクセスしようとしたら、ORA-00600が発生した。

調べてみると、有名なエラーコードらしい。

 

オラクルの内部エラー。

解決方法は次の2つしかない。

①サポート契約を結んでオラクルに問い合わせる

②原因と思われるものをあきらめる

 

①について

サポート契約を結んでいなければ不可。

また、契約を結んでおり、問い合わせた結果解決方法を得た場合でも、

守秘義務があるため他の人が同じ状態になっていたとしても教える事は出来ない。

これにより、第三者から情報を得て問題を解決することはできないため、

サポート契約を結んでいない場合は②の手段を取らざるを得ない。

 

②について

今回の件で言うと、原因と考えられるのはメモリ割当の変更だった。

エラーが発生した当日早朝に、とある2つのインスタンスに対して、SGAのメモリ割当を512MB→2GBに変更していた。

そのうち片方のインスタンスで、照会を行うとJDBCドライバ内部でぬるぽが発生するようになった。

ちなみに挿入は普通に出来た。

同条件のもう片方のインスタンスではエラーは発生していない。

Oracleサーバマシン自体のメモリも、充分に余裕がある状態。

原因不明。

謎。

なぞなぞ。

結局2GBまで増やす事を諦め、SGAの割当を1.5GBまで減らしてみたところ、内部エラーが発生しなくなった模様。

 

管理者に話を聞いてみると、朝の自動DB再起動時に、MOUNTで止まってOPENできていなかったらしい。

手動でオープンしたら動いたので気にしていなかったとのこと。

 

MOUNTで止まるということは、OPENの際に読み込むデータが壊れている可能性が高い。

つまり、データファイル or REDOログ あたりが壊れたのかな?

Oracle Master Bronze取得のために勉強したことが、管理者との会話にて少しだけ生きた。

感動。

 

一応、似たようなケースで参考になりそうなサイトがあったのでメモ。

<http://kawabata-eye.jp/modules/d3blog/details.php?bid=75>

 

今回はメモリを下げることで対処してしまったため、上記サイトの内容は未検証。

いつか役に立てばいいな。

マルチテーブル・インサートにてORA-24335エラーが発生

【マルチテーブル・インサート構文】

insert all

  into XXX_TBL (id, name, value) values ('001', 'AAAAA', 1)

  into YYY_TBL (id, name, value) values ('002', 'BBBBB', 2)

select * from dual;

 

基本的には普通のinsert文と同じ書き方。

異なる点は下記3つ。

・insertとintoの間にallが入る

・intoが複数並ぶ

・最後にselect * from dualが入る

 

マルチテーブル・インサートにて、

大量にINSERTを実施しようとしたところ、[ORA-24335]エラーが発生。

ORA-24335: 1000列以上はサポートされていません。

 

VALUES(?)のバインド変数が1000個を越えたのが原因のよう。

IN句で指定可能な数の限界が1000個であるのと同様っぽい。

DevLOVE甲子園2013

2013/11/9に行われたDevLOVE甲子園2013の参加レポートです。

 

f:id:monokurotamago:20140112203354j:plain

※画像はイベントのサイトDoorkeeperから拝借しました。

http://devlove.doorkeeper.jp/events/5464

 

10時過ぎに会場最寄りとなる鮫洲駅に到着し、駅側のマックで朝食をとりました。

余談ですが、朝マックはどうにも好きになれません。

朝時間にも通常メニューを出してほしいです(熱望)。

 

食後にコンビニ@ミニストップに。

戦の準備として、ペットボトルのお茶1本、おにぎり2つ、そしてEdyへの入金を行います。

どうやら会場が一度入ったら出られない(再入場不可という意味で)らしいのです。

フルで参加すると、11:00-20:00までの長丁場。

会場内に食べ物が売ってない&飲み物はEdyでしか買えない環境に軟禁…ゴクリ。

 

中略。

なんだかんだで会場に到着。

途中別のビル(しかも思いっきり裏口)に入って、

警備員とご対面したことなんてここに書く必要はありません。

 

会場にINして即ビックリ。

流石楽天ビル!

田中マー君のポスターがあちこちに。

 

今回の方式は、一つの会場を4ブロックに分けて、それぞれの場所で20分間隔で同時開催というものでした。

一度だけ「創」トラックに行きましたが、基本的には「団」トラックに居座っていました。

そして前半戦が終わったタイミング(16時ちょっと)で切り上げました。

長丁場は身が持ちません。

 

 

以下聞いた内容をざっくりと。

【発表タイトル】【発表者】で記載しています。

発表者は敬称略です。

 

 

【凡庸なSEが、大規模SIerの集団でできること】【よこみちみのる】

発表者は認定スクラムマスター!

皆で前進する現場に居たい

→場所を変えるのではなく、先ずは今居る場所を理想にしようと努力する

やったこと3つ。

①学ぶことを当然とする風潮を作る

 ・若手勉強会

 ・マネージャ向けアジャイル開発勉強会

 ・PRJ内の読書会(朝会後15分だけ。1時間とかだとだれる。敷居を低く)

②チーム意識を高める

 ・詳細聞き逃しました…

③若者の主役感を育てる

 ・褒めて伸ばせ

動くには社内に仲間を見つける事が重要。

一人でやるのはシンドイ。

 

 

【いまの自分にできること。】【脇野寛洋】

発表者は団トラック発表者の中で唯一、営業職とのこと。

営業→エンジニアの力を借りてお客の問題を解決する

客から来るアバウトな要求を、ユーザ要件を図にして分かり易くエンジニアに伝える→いまの自分にできること

営業は団体戦で言うと先鋒であり、勢いづけをする必要がある。

 

 

JavaScript development by Agile and Scrum】【@shinjukujohnny】

Daily Scrumを毎朝15分実施。

最初から完成度高いものを目指してモジュール作りこむ→結合時にgdgdに。

とりあえず最小限で動くものを作って客に見せる→フィードバック貰える→改善できる

 

自動化(保存すると自動でUnitTestが走る)すると良い。

リファクタリングにリスクがないからガンガン出来る

→コードの見通しが良くなり事故が減る。

 

 

【成功と失敗の狭間に横たわる2つのマネジメント】【中村洋(@yohhatu)】

期待マネジメント→関係者が互いに持っている期待を明確にする

モチベーションマネジメント→モチベーションを上げるスイッチは、人によって違う

優秀な人ほど、自分でモチベーションをコントロール出来る傾向にある。

指示待ちは良くない。

 

 

【世界をかえる前に現場をかえよう】【すなだ】

アジャイルサムライ(コミュニティ)

KPT(アジャイルの用語)

・社内勉強会→何か作ろうぜ→作ったもの発表しようぜ→イベント出品で盛り上がった

・月一のゆるい定例勉強会(帰社日和@ネーミングセンス良すぎ!)

 

 

【Can We Change The World?~ TISMatsuri という名の社内カンファレンスを始めた理由 ~】【白石康司(@shiraco)】

社員数6000人の会社(TIS)で、勉強会開催について呼びかけたら7人集まった。

運営資金は副社長に寄付(ポケットマネーで5万程)出してもらった。

 

 

【テストを書く文化をゼロから育てる戦略と戦術】【和田卓人(t_wada)】

聴衆の数が非常に多かったです。

 

・テストを書く時間が無いのではなく、テストを書かないから時間がない。

・「動くコードに触れるな」という文化があるが、触れなければいずれそのコードは死ぬ。

・良いテストとは?

 ・繰り返し使えること(一度使ったらファイルを消して~とか、DBをクリアして~とかは駄目)

 ・ネットワークに繋がってないと使えない、と言った制約があっても駄目

・オススメ本「レガシーコード改善ガイド」

 

 

【DevLOVE始めました 仙台で 0中間管理職が始めた社外の団】【早坂則泰】

発表者はDev仙台の代表!

中間管理職をして長らく直接開発してなかったが、何気なくDevLOVEに参加して開発の楽しさを再認識。

手を動かす勉強会は仙台にはない!

ハンガーフライト!

ということでDev仙台を立ち上げた。

 

 

【バラバラの同僚を社内勉強会でつなげよう】【すぎいまさかつ】

当日知ったのですが、居酒屋で勉強会@北海道の記事を書いた方でした。

※ブログ「HOW TO GO」

 

居酒屋で勉強会のエントリを書いてくださったことに対して、一言お礼を言いたかったのですが、常に人に囲まれてて声をかけることが出来ませんでした。残念。

 

 

前半が終わったところで会場から退散しました。

帰り際に一枚。

f:id:monokurotamago:20131109161924j:plain

 

ほんとは室内も撮りたかったのですが、自重しました。

 

 

感想とか

・イイ話が色々聞けた(KONAMI感)

 → 社内勉強会やってる人は、皆アレコレ苦労しているっぽい。

   そして苦労する点は大体似ているっぽい。

・後日別途レポートを書きますが、アジャイルサムライと出会えた点は大きな収穫。

・最後に、運営/企画スタッフに感謝です。

 

以上。