2014年12月29日月曜日

Javaからのストアド呼出(TYPE RECORD)方法

ハマりました。
と、言うよりJava(JDK)とOracleを知らなすぎだっただけかも知れません。
JavaからOracleのストアドを呼び出すのは簡単なのですがストアド側の引数でTYPE RECORD型に対して引数として渡せないんです。

ネットの検索の仕方が悪いのか全く情報が見つからない。
同じようなことで苦労している人は居ないのだろうか?それとも常識すぎるのか?
今回自分がJabaからOracleのストアドを呼出するの初めてでOracleの知識も少ないせいかな?

ストアドはこんな感じです。(あくまでも参考ですので…)

/* レコード型定義 */
type TYPE_TEST_RECORD is record(
 numFIELD1 TEST.FIELD1%type
, numFIELD2 TEST.FIELD2%type,
 numFIELD3 TEST.FIELD3%type
);
/* PL/SQL表定義 */
type TYPE_TEST is table of TYPE_TEST_RECORD index by binary_integer;
/* ストアドI/F */
PROCEDURE ProcTEST (
 numRETURN_STS OUT NUMBER, /* リターンステータス */
 numPROCESS_CD IN NUMBER, /* 処理区分 */
 usrTYPE_io IN OUT TYPE_TEST /* データ格納領域 */
);

これをJavaのJDKのthinドライバから呼び出すことが出来ないんです。
TYPE_TESTへ値を渡せない。
Object型等色々試しても一向に拉致が空きませんでした。


そのため、いろいろ調べてみるとJPublisherなるものを使用すれば動作させることが出来るとOracleのページに記載があり調べてみたのだがよくわからん。
JDBCのOCIドライバにすれば出来るんじゃないの?なんて記載も見つけたが…
同じ箇所にストアドの中でTYPE RECORD型に値を設定しなおせば大丈夫との記載も。あまり推奨されていないようだが。

ストアド経由で更新処理だけを行うので簡単に済ませたい。
試しに以下のようにしてストアドの呼出関数を1枚かぶせて見たところ上手く行った。

/* ストアドI/F(Java用) */
PROCEDURE ProcTESTJ (
 numRETURN_STS OUT NUMBER, /* リターンステータス */
 numPROCESS_CD IN NUMBER, /* 処理区分 */
 numFIELD1 IN NUMBER,
 numFIELD2 IN NUMBER,
 numFIELD3 IN NUMBER );
PROCEDURE ProcTESTJ (
 numRETURN_STS OUT NUMBER, /* リターンステータス */
 numPROCESS_CD IN NUMBER, /* 処理区分 */
 numFIELD1 IN NUMBER,
 numFIELD2 IN NUMBER,
 numFIELD3 IN NUMBER
)
 IS
 test_rec TYPE_TEST ;
BEGIN
 test_rec(1).numFIELD1 = numFIELD1 ;
 test_rec(1).numFIELD2 = numFIELD2 ;
 test_rec(1).numFIELD3 = numFIELD3 ;
 ProcTEST (
  numRETURN_STS, /* リターンステータス */
  numPROCESS_CD, /* 処理区分 */
  test_rec /* データ格納領域 */ );
 END ProcTESTJ;

Javaでの呼出はTYPE RECORD型のメンバ数が増えると面倒だがこれで何とか出来る。

Java側はこんな感じです。
第一引数にリターン値が帰ってきます。

String sql="{call ProcTEST(?, ?, ?, ?, ?) }" ;
connection = DriverManager.getConnection(url, userid, password);
OracleCallableStatement callableStatement =    
                       (OracleCallableStatement)connection.prepareCall(sql); callableStatement.registerOutParameter( 1, java.sql.Types.INTEGER) ;
callableStatement.setInt( 2, 1) ;
callableStatement.setInt( 3, field1) ;
callableStatement.setInt( 4, field2) ;
callableStatement.setInt( 5, field3) ;
callableStatement.executeUpdate() ;
returnSts = callableStatement.getInt(1);

もっと良い方法もあると思いますが、JavaからストアドのTYPE RECORD型へ値を渡す際の参考になればと思います。
特にリプレース案件などでストアド使っているシステムをJavaに置き換えるなんて時に同じ現象にぶち当たる人いそうなんだけけどね。

2014年10月12日日曜日

HTML:画像の上にポップアップ表示させたい場合


今月末納品するリプレース案件のシステム。

一部コンテンツを一般公開するわけなんだけどHTMLに不備が見つかってしまう。

地図画面の上にこんな感じでポップアップ表示をさせていたんだけどIE8,IE9では表示されるのだがFireFox,Chrome,IE10,IE11では表示されない…。
赤丸部分にカーソル合わせてください。これが出なかったんですよIE11だけは




HTMLはこんな感じ
<IMG src="test.png" useMap="#POPUP">
<MAP name="POPUP" alt="test">
<!-- ポップアップタグ -->
<AREA href="sample.html" shape=circ alt="ここは〇〇&#13現在:××&#13;1時間後:▲▼" coords=234,156,20></AREA>
</MAP>


調べた結果IE11以外は<AREA alt="~" の部分を<AREA title="~" に変更することで無事解決

IE11だけはどうしても表示されない。
<AREA タグ内でonMouseOver,onMouseOutでDIVの表示に切り替えないと駄目かな?なんて考え始めたのだが確かJavaScriptは極力使わない方針だったので躊躇してしまう。

しかしなんでIE11だけ駄目なんじゃ!?

表示出来ないt多分納品出来ないのでJavaScriptで表示するのも視野に入れて作成しているとあれ!?なんか出るようになったぞ!

そういえば今IMGタグの終了タグ入れたよな!?

まっまっまさか!
</IMG>

この終了タグが抜けていたせい!?

なんでIE11だけ駄目なんだよ。全部駄目だったらもっと早く気がついたのに…
このコンテンツって何も変えていなくてIE11 での表示確認だけだったのに酷い。。。

かなり無駄な時間を使ってしまったではないか…

終了タグはちゃんと入れましょうね。

終了タグは全く関係ありませんでした。
無くても問題なく表示されました。

表示がポップアップの表示が遅いだけだったかも知れません。。。





2014年7月16日水曜日

リモートデスクトップでコンソールセッションに接続


Windows2003Serverへリモートデスクトップでアクセスし起動中のアプリを停止させようとしたら動いているはずのアプリがいない!
タスクマネージャのプロセスではちゃんと動いているのに~なんて事無いですか?


これはリモートデスクトップで接続した時に違うセッションに接続しているためだそうです。
その場合、コマンドプロンプトから以下のコマンドで接続するとコンソール・セッションに接続できます。

c:\>mstsc.exe /console /V:xxx.xxx.xxx.xxx


/Vは接続先のIPアドレスを入れます。
IPアドレスをしてしないとリモートデスクトップ接続画面で接続先を指定する事になります。

接続するときは毎回コンソールセッションに繋ぎたい場合などは上記の一行をメモ帳などに書き込んでmstsc-aaa.batなんてバッチファイルにしておけば便利ですね。



Windows7にてhostsファイルを編集するには


hostsファイルってご存じですか?

ネットワークのIPアドレスとホスト名(マシン名)を紐付けてくれるファイルです。
最近は使うことがあまりないと思うのですが古いシステムなどでは使用していたりするんです。

昔のシステムってアプリケーションとかに直接IPアドレスとか持っていたりするのでこれをホスト名にしておけばhostsファイルの修正だけで済むわけです。

が、今となってはこのファイルを簡単に変更できてしまうと悪意のあるサイトに簡単に誘導できてしまうためセキュリティが強化され編集出来ないんですよね。

ちょっと古いシステムを動かしたいのでhostsファイルを編集したいんですが…

秀丸エディタで開くとアクセス制限がかかっていて開くことは出来ても保存が出来ません。
プロパティとか見ても権限変更出来ないし…
まだ、Windows7を使い始めて半月なので正直どうすりゃいいんじゃ?って感じ



ネットでいろいろ調べて見ると管理者権限で実行すればよいなんて見つかる。
ふむふむ、秀丸エディタのアイコンを右クリックして「管理者として実行」すると編集することが出来ました!こんなメニューがあるなんて知らなかったよ。
※メモ帳でも同じように管理者で実行すれば問題なく編集できるはずです。


注意!
hostsファイルをドラッグ&ドロップで秀丸、メモ帳に渡しても表示すらしないです。
エディタのメニューでファイルを開くから開かないと編集出来ません。
(一体どんな理由なんだろうか?)


今回はhostsファイルを例にしましたが「ファイルが編集できない~!」なんて時はメモ帳やエディタを「管理者として実行」してみましょう!


2014年3月22日土曜日

Windows2008ServerでVC++6.0で作成したプログラムを動かす


Windows2003ServerからWindows2008R2へのサーバリプレース作業がありました。
DBもSQLServer2000からSQLServer2008へアップグレード。

このWindows2003サーバ本来持っている機能は作成しなおしここまでは問題なく作業終了。

ところが現地で問題が発覚
本来、別サーバで動いているべきアプリがいつの間にかリプレース対象のサーバで動いていたことが発覚!
当然、仕様落ちだし作業範囲外。とは、言ってもその動いていたアプリをWindows2008で動かさねば。


このアプリVC6.0++ で作成されていてすんなり動くことはなく多々、問題がありそう。

機能
コンソールアプリで通信を行い受信したデータを別サーバのDBへ書き込む。
書き込む先はWindows2000サーバでDB接続はODBC。
実行ファイルの他にdllが2つある。


問題となりそうなところ

1.64bitOSで32bitで作成されたアプリが動くのか?
  
2.DLLが動作するのか?

3.ODBC接続でうまく接続できるのか?


早々に対応しないといけないのでVMにWindows2008R2の試用版を入れて動作確認。

まず、アプリをそのままコピーして起動してみる。
起動した時点で、DLLが見つかりませんとメッセージが表示される。
そのためDLLを”Windows\System32”へコピーしてみるが状況は変わらず。
次に別に作成した”c:\work”へコピーし環境変数のPATHにこのフォルダを追加して実行すると起動は出来る。

PATHを追加しなくても動作出来ないのか調べたところ、WOW64で32Bit 版のアプリを検出すると、CPUを32bitプログラムが動く「Compatibility Mode」に変更するそうで、その際参照するシステムフォルダは”Windows\SysWOW64”になるとのこと。
それならと、DLLをコピーしてみる。(当然System32、PATHは元に戻して)
実行すると何とか起動が出来るようになった。

さすがにマイクロソフトも考えてくれて傷んだね。

これで1,2の問題は解決出来そう。

次が3.のODBC接続。
現地と同じようにODBC接続を設定する。
ODBC設定の動作確認で接続完了まで行っているので設定自体は問題無いと思うが残念ながらアプリはエラーメッセージを吐き出し接続できない。
こちらも調べてみると32Bit版のODBC接続を設定すれば良いそうです。
32bit版のODBC設定画面は”Windows\SysWOW64\odbcad32.exe”を起動して同じ設定にすれば良いらしい。
設定後再起動すると確かにDBへ接続できている様子。
通信用のデータを流してDBへ書き込むところまでひと通り確認できた。
※但しこの時点で接続しているDBはWindowsXP+SQLServer2005で現地とは異なる


ODBCドライバの説明で下位のSQLServerへの互換性は保証しているなんて記載を見つける。
裏切られることの多いマイクロソフトを信じて現地のサーバへセットアップに。

嬉しいことに一発でうまく行きました。


まとめ、Windows7、Windows2008R2など64bitOSで32bit版を動作させるにはSysWOW64を使用すればうまく行きます。