Ads by Google [--/--/-- (--)]
上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

役に立ったらぽちっとよろしく。 人気ブログランキングへ

JSFの現在のバージョン1.2ではファイルのアップロード処理は標準では提供されていないっぽい。で、ネットで検索したらいくつか対策は見つかるけど、ちょっと自分には合わない…残念。…ので、我流の方法を試して見る事に。

ネットで見つかったのはこんなの

  • Apach MyFacesを使えばファイルアップロード用のタグがあるらしいのでそれを使う。
  • ファイルのアップロード部分だけServlet+JSP方式で処理する。

問題と思うのは…。最初の方法の場合、MyFacesはファイルアップロードのためだけのライブラリではないので、ファイルのアップロードのためだけに巨大なライブラリを入れたくない場合に不向き。次の方法の場合、必要なライブラリはApach FileUpload等だけで済むけど、同じページのファイルアップロード以外の部分をServletでガリガリ処理する事になる。

我流の方法ってのはこんなの

  1. Servlet Filterでリクエストを捕まえる。
  2. リクエストを解析し(HTTP&POST&multipart/form-data)以外は普段通りの処理をする。
  3. 目的のリクエストの場合はJSF用のServletが処理出来るよう、HttpServletRequestWrapperで 解析したリクエストをapplication/x-www-form-urlencoded形式に変換。ファイル形式のパラメタは リクエストスコープの属性として格納。その後は普段どおりに処理。

こうすればJSF用のServletがmultipart/form-data形式に対応出来るし、必要なライブラリもApache FileUploadだけで済む。別の方法で、自前でリクエストの解析からJSFのライフサイクル実行まで行うってのも考えられるけど…リクエストをラップするこの方法の方がコードは断然短いはず。

ちなみに…有名なサンプルプログラム PetStore ではファイルのアップロードはAJAXを使ってるっぽい。たぶんAJAXによるファイルのアップロードリクエストをShale RemotingがApache FileUploadで解析する部品に流してる雰囲気。でどうも詳しく見ていくとAJAX経由での処理の流れしか想定してないみたい。てかそもそもPetStoreはJavaScriptをOFFにするとページが表示されなくなったりする。

というかJSF、ファイルアップロード位は標準で備えてて欲しいような…。
けど、ま、いっか!いい方法思いついたし。今さら標準なんて…!!
…うけけ!おいらは自分が良ければそれでいいって性格なのさ!!

役に立ったらぽちっとよろしく。 人気ブログランキングへ

続きを読む »

UIコンポーネント2 [2008/11/21 (金)]

2008/10/20の記事に追記で書いた方法よりもっといい方法を見つけたっぽい気がする…。(前の記事の方法はお蔵入り…うまくいきそうにない…。ちなみに今回の方法はある程度検証済み!!)

その記事でおいらはJSFの複数のコンポーネントの値を連携させようとしていた。で、遅延評価式の確定は大概RenderResponseフェーズだって事に気づいた。そんなら、そこで確定した値を他のコンポーネントに設定するのは同じくRenderResponseフェーズしかないわけで…。だけど、RenderResponseフェーズでetcいじるのはまずいのでは…という事に。

今回の方法のポイントはMapを利用したEL式を作る所。参照する時はこんな感じ…

#{requestScope['myFQCN']['clientId']['key']}

キーの意味はそれぞれ…

myFQCN
専用クラスのFQCN (FQCNでなくても他とかぶらなければ何でもいい)
clienId
子コンポーネントと共有すべき値を持つ親コンポーネントのclientId
key
共有する属性値のキー

で、このマップに対して…

  1. PhaseListenerでRenderResponseフェーズの直前に共有すべき値を持つ コンポーネント(マーカインタフェース等で識別)の全てにアナウンスを流す。
  2. アナウンスを受けたコンポーネントは自身のclientIdと共有属性のキーを指定して先のマップを参照するEL式を作り、それを子コンポーネントのEL式として設定。
  3. コンポーネントはレンダリングと同時に自身のELを評価して、その値を先のマップに設定する。

こうすれば、遅延評価式の評価はレンダリング時に行われ、なおかつ連携するコンポーネントは予め設定された場所を参照するだけなので、レンダリング時にコンポーネントの値を再設定する必要が無い。

ちなみに、本当はMapを使わなくても、EL式から参照できてコンポーネントの外で値を共有出来れば何でもいい。ただEL式には予めマップを処理する機能があるのでありがたく拝借する。

UMLシーケンス図

役に立ったらぽちっとよろしく。 人気ブログランキングへ

First contact… [2008/11/04 (火)]

こないだの記事の内容、色々調べたけども、結局分からなかった…。なので、どっかの掲示板に投稿しようと思った。だけど日本語のサイトでぴったしの掲示板が見当たらない…。しかたないので、海外のサイトに投稿する事に…もちろん英語で…。

結論だけ言うと、どうやらJSFの仕様的バグかも…ということらしい。つまり、めずらしい事に、おいらの疑問は正しかったみたい。………なんだけど、問題はその結論に辿り着くまでのやりとり。ぶっちゃけ、おいらの英語は中学で習ったレベルで、コンピュータ関連の英語だけ必要に迫られてReadOnlyって程度。それでも英語、日本語、コンピュータ全て出来る外国の人が昔は側にいてくれてたので、それをいい事にサボり続け今に至る…。なので、一人であちゃらのサイトに投稿する等出来るはずもないのだけども、もうそれしか手は無い…。それに…エンジニア同士だしソースコードのみでも伝わるだろう…と思ってた。けどいざ書いて見るとものの見事に伝わらない!もう誤解の連続…。

以下が、そのスレッド…。なんかもう誤解を生みまくりでニュアンスもきっと全部凄い失礼な感じになってる可能性大!!そんなで分けも分からずとにかく誤りまくっている自分…笑。そして、どんなに変な英語でも、ちゃんとレスを返してくれるあちゃらの方々!

Sun's JSF Forum
http://forums.sun.com/thread.jspa?threadID=5343413&tstart=0

あちゃらの方々皆がそうではないんだろうけども…、これだけ根気強く対応をされると、おいらは使えなくて残念なんだけど、、、うんやっぱり世界の共通語はこの人らの言葉がいい!…と思ったのでした。

…ん?てか「おいらは使えなくて残念なんだけど」と書くと、まるで英語・日本語以外でなんか他の言葉を喋れそうなニュアンスになる気もする。…違う…、日本語だけ…いや…つまり日本語もまともに使えてない可能性大………。

役に立ったらぽちっとよろしく。 人気ブログランキングへ

怪奇現象… [2008/10/28 (火)]

昔のホラー映画でなんかテレビに悪霊がいてって話があったけど、うちのPCも最近やたらと怪奇現象が多い。どうもこれにも悪霊が取り憑いたっぽい…。そう、うちのPCでは悪魔の言葉とおぼしき意味不明の文章がログにたまるは、血で綴られたような赤いエラーメッセージが出るは、独りでにプログラムが停止するは…。そのうち本人もバグの階段を…
┌(。ρ。┌ )┐三三三   …て感じで降りていくに違いない。(ネタ古過ぎ…)

さてさて、映画ではエクソシストが悪霊を退治してくれるらしいけども、現実エクソシストと思って頼ったフレームワーク(JSF)が悪霊以上に凶悪な気がするこの頃。…いや、でも実はそれは、おいらが既にアンチパターンに取り憑かれていて…だからエクソシストが憎いのか(恐)!…そんな感じの今日のネタ…。(つまり、簡単すぎてJSFが間違ってるとも思えない…何かおいらに見落としがあるに違いないって事(爆!!))

まず、コンバータを設定したValueExpressionを参照する入力コンポーネントを用意。それに空の文字列を入力、そして他のコンポーネントにValidationフェーズで検証エラーの起きる値を入力してサブミット。すると空の文字列を入力したはずなのに…ValueExpressionの値が優先されて元に戻っちゃう…。


<h:form>
    <-- 検証エラーをおこすために何も入力しない -->
    <h:inputText id="required" required="#{true}"/>
    <h:message for="required"/>
    <-- 空文字を入力しても元の値に戻る -->
    <h:inputText id="hasInitial" value="#{testBean.value}">
        <f:convertNumber integerOnly="true"/>
    </h:inputText>
    <h:message for="hasInitial"/>
    <h:commandButton/>
</h:form>

どうもコンバータがnullを返して、それがlocalValueとして設定されて、最後のgetValue()がJavaDocによると、localValueがnullならValueExpressionを使うって書いてあるので、たぶんこれだ…。うーん、isLocalValueSetとかで切り分けてくれると思ってたんだけど…違うみたい。

上記の現象の画像による説明

うーん、、、単純なんだけど汎用的な解決策が見つからない…。JSFの欠陥?なわけないよな…こんな単純な所で…。とするとおいらの理解が足りてないって事か…うーん。

役に立ったらぽちっとよろしく。 人気ブログランキングへ

前回に続きJSFと格闘中。ASP.Netで出来た事がJSFでクールに出来ない…。やるせないのでメモ。

おいらはASP.Netを使っていた時はUIコンポーネント(.Netでは確かコントロールとか言ってた)同士を連携させるまとめ役のUIコンポーネントを作って楽する手がお気に入りだった。で、ただコンポーネント同士をまとめるのでなく、あるコンポーネントに設定された値に基づき他のコンポーネントの値を調整するといった、やや混みいった事をしてた。

例えば、エンドユーザにラジオボタン等で幾つか代表的な候補を示し、それ以外の値を入力したい場合のみ最後のラジオボタンを選びその隣の入力コンポーネントにカスタム値を入力してもらう。カスタム値を入力するコンポーネントは子コンポーネントとして記述できるようにし、内容に応じて種類を変えられるようにする。そしてプログラムから入力された値を取り出す時はただの単一値入力コンポーネントと同様に扱えるようにしておく。名づけて"UISelectOrCustom"!うん、我ながらいいネーミング!

このUISelectOrCustomを実装する場合、モデル側からカスタム入力でしかあり得ない値を取得したらば、それを子コンポーネントにも設定しないといけない。すると問題になるのはJSFのUnifiedELの遅延評価式の存在とその評価タイミング。標準のUIコンポーネントの実装方法に倣うなら遅延評価のタイミングはRender Responseフェーズにおける描画時になる。となるとそこで取得した値を子コンポーネントに伝えるタイミングもRender Responseフェーズの描画時になる。

ここが問題になる。てのは、まずRender Responseフェーズでコンポーネントの木構造を書き換えるとクライアントIDの関係が崩れる。そのためJSFではこれは反則になっている。だから設定を受けてコンポーネントの木構造が書き換わるようなコンポーネントは取り扱えなくなる。また、保存する状態の取得は描画前にやっておくので、描画時に子コンポーネントの値を再設定されるとValueChangeEvent等がおかしな事になるし、保存前の状態を前提とするコンポーネント(標準のコンポーネントではないけど)も取り扱えなくなる。つまり、そんなこんなでRender Responseフェーズでコンポーネントに手を加えるのは禁止されていたり危険だったりでチキン野郎のおいらには到底出来ない…。

で、ASP.Netでこれが出来たような気がする理由はそもそも遅延評価ってのが無かったような覚えがある。データバインドにしろ何にしろどっかのタイミングではいドーン!って感じで設定される。だからレンダリング前に値は確定させれるし、それがASP.Netは普通なわけで…。おかげでまぁユーザコントロールやカスタムコントロールは気軽にほいほい作れる。

う〜ん、、、せめてJSFが描画前に全ての値を確定するフェーズをデフォルトで用意して、値の確定はそこでやるのを標準にしてくれてればいいのだけど、そんなのは無い…。ま、JSFでも解決策は無くはないような気もするんだけど→追記を参照、なんかトリッキーな手のような気がして自分に自身が持てない。なので遅延評価はいいんだけど…この件についてはASP.Netに一票…。

役に立ったらぽちっとよろしく。 人気ブログランキングへ

続きを読む »

Copyright © ふらふら技術者の日記 All Rights Reserved.
Powered by FC2 Blog FC2ブログ