BlogJavaを中心にした技術ネタなど。S2AOPのアスペクトの自動ウィービングでの注意点S2AOPでコンポーネントにアスペクト使用する場合、ポイントカットを明示的にしていないと以下のルールでウィービングされる。「pointcut属性」参照)a.コンポーネントがインターフェースを実装していない場合は、Objectクラスで定義されているメソッドを除く、全ての非finalなpublicメソッド。b.コンポーネントがインターフェースを実装している場合は、インターフェースで定義されている全てのメソッド。意外と落とし穴で、インターフェースを実装すると、インターフェースで定義されていないメソッドにはアスペクトがウィービングされなくなる。}}対処として考えられるのは以下の3パターン。通り、インターフェースを実装しなければS2AOPがよろしくやってくれるので、S2コンテナでコンポーネント管理するクラスには、一切インターフェースを実装しないルールにする。通り、インターフェースを実装するとインターフェースで定義されているメソッドだけがウィービング対象になるので、S2コンテナでコンポーネント管理するクラスの公開メソッドは全てインターフェースで定義する。アスペクトをウィービングできる。「Xxxxxxのメソッド(xxxx)にはアスペクトを適用できない修飾子が指定されています」のようなWARNログが出てしまう。オーバーライドし、独自のPointcutを返すようにする。メソッドかどうかを判断(Method#getModifiers())してfinalであればウィービングしないようにする。理想的な対応と思うが、S2標準のdiconの書き方ができなくなる。S2の思想や、実装量を極力減らして生産性を上げることを考えると、パターン1.が一番良いと言うことになるかな。複数のクラスで共通の公開メソッドを規定したい場合にインターフェースが使えないのは結構痛い。インターフェースではなく継承でと言う方法もあるが、Javaは多重継承できないし、あまり継承で面倒なことにはなりたくない。共通の公開メソッドを規定したいと言うケースはあまりないだろう、と言うことで。コメント:1S2Flex2でIllegalAccessRuntimeExceptionS2Flex2で、以下のようなエラーが発生。不正なアクセスがありました。org.seasar.framework.util.MethodUtil.invoke(MethodUtil.java:73)Webで調べても明確な原因・対処法が見つからなかったのですが、デバッガでトレースしつつ、S2Flexのソースを見ていくと、原因はDTOにありました。全て直列化しようとするようなのです。この時、DTOに直列化不能(=リフレクションでアクセス不能)なオブジェクト(具体的には、java.lang.Classオブジェクトなど)を返すような#getXxx()が定義されていると、このエラーが発生するようです。対応としては、DTO(とDTOに含まれるオブジェクト)には、S2Flexが直列化できないオブジェクトを返す#getXxx()を定義しないように注意する、しかないと思われます。コメント:0S2Flex2のサンプルが動かない(XIncludeに注意)S2Flex2の技術調査で、配布されているサンプルを動作させようとしたのですが、なかなか動作せず、ハマりました。level=error,code=NetConnection.Call.Failed」と言うエラーが表示され、動作しない。org.seasar.flex2.rpc.remoting.message.io.reader.impl.AmfMessageReaderImpl.clean(AmfMessageReaderImpl.java:102)と出力されている。直接の原因は、サーバログにワーニングとして表示されているように、コンポーネントの自動バインディングが正しく行われていないことです。自動バインディングが行われていないか?は、diconのインクルード方法が関係していました。XIncludeをサポートしていないようなのです。SeasarファウンデーションのXIncludeに関するドキュメント)このため、diconファイルが正しくインクルードされず、インクルード先のdiconに定義されているコンポーネントが認識されていないのでした。5.0.xにバンドルされているXMLパーサを使用しないようにすれば良いです。xmlParserAPIs.jarを削除すれば、JREにバンドルされているXMLパーサが使用されるようになります。5.xのXMLパーサは、XIncludeをサポートしているようなので、問題は解決しました。1.4.xのXMLパーサはXInclude未サポートなので、この対応をしてもダメ。5.5.xだと問題が発生しないかもしれないですね。細かいことで何箇所かつまずきました。ルートパッケージ名を、実際のパッケージ名にあわせて修正していませんでした。その為、PageやActionがDIコンテナに自動登録されていませんでした。当初、「そういえば、diconにコンポーネント登録してないなぁ」と思ったのですが、サンプルを見てもPageやActionをコンポーネント登録している気配がない。Creatorが働いていて、パッケージ構成とクラスの命名規則を守っていれば、自動的にコンポーネント登録されるのでした。2.アクションメソッドが呼び出されないSUBMITボタンを作って、Pageクラスのアクションメソッドを呼び出すようにしたのですが、どういうわけか呼び出されない。Pageクラスのプロパティに値は設定されているので、HTMLとPageクラスの関連付けは正しく行なわれているようですが。原因は、HTMLのformのidの命名ミスでした。Extensionを使う場合、HTMLの各要素に色々と規約があるのですが、この規定に従ったidを付与していませんでした。以前に、S2StrutsやS2Daoを使った際も、ちょっとした命名ミスで結構ハマったことがあり、これはCoCでの注意点だと思います。動いているように見えたりして調査が難しいことが多いです。Seasarのソースを読まないと、原因特定できないことも少なくありません。気づくのに時間がかかることもしばしば。実プロジェクトで使う時は、アーキテクトが命名規則一覧のようなものを作成・配布したほうが良さそうな気がします。3.ActionからServiceやLogicを呼び出すと、NoSuchMethodErrorActionにインジェクトしたServiceやLogicを呼び出そうとすると、NoSuchMethodErrorが発生しました。呼び出そうとしているメソッドは存在するように見えます。原因は...これまたServiceとLogicのクラス名の命名ミスでした。Deployの規約(?)とあっていませんでした。・インターフェース・・・HogeHoge・実装クラス・・・HogeHogeImplです。org.seasar.teeda.extension.interceptor.ActionSupportInterceptor.invoke(ActionSupportInterceptor.java:73)<以下略>が発生しました。原因は、Actionクラスに、PageインスタンスのGetterメソッドがないことでした。Actionクラスには、画面の入力値を保持したPageインスタンスがインジェクトされますが、インジェクトしてもらうだけなので、Setterだけで良いか、と思ってGetterを作成していませんでした。S2AOPで拡張されたActionクラスが、オリジナルのActionクラスのフィールドにアクセスする際、Getterメソッド経由でアクセスするっぽいです。(S2AOPが、サブクラス化によってアスペクトをウィービングしているから...かな)5.PageとActionのアクションメソッドの呼び出し優先順Teedaでは、アクションメソッドをPageクラスとActionクラスどちらにでも定義できるようですが、その呼び出される優先順は、(1)Pageクラス(2)Actionクラスのようです。・アクションメソッドをPageだけ定義し、Acitonには定義しない→Pageのアクションメソッドが呼び出される・アクションメソッドをActionだけ定義し、Pageには定義しない→Actionのアクションメソッドが呼び出される・アクションメソッドをPageとAciton両方に定義する→Pageのアクションメソッドが呼び出される(Actionに定義したアクションメソッドは意味がない)と言う事になります。今日1日でいろいろ勉強になりました。ほとんどが命名規約違反によるもので、それはSeasarサイトのドキュメントをしっかり読めば回避できるものがほとんどです。実際のプロジェクトでは、実装者全員がこのような問題に対処できるわけではないので、やはりSeasarプロダクトを理解したアーキテクトなりがサポートする必要があるように思います。自分がアーキテクトをできる場合は、積極的に採用(してもらえるように提案)したいと思います。org.seasar.struts.servlet.S2ActionServlet.init(S2ActionServlet.java:61)のようなエラーが発生しました。このエラーからはわかりにくいのですが、原因はstruts-config.xmlの記述にありました。className="org.apache.struts.validator.ValidatorPlugIn">:</plug-in>----------------------------------------------------のように記述していたのですが、StrutsのValidatorプラグインより先にAutoStrutsConfigRegisterプラグインを定義していたため、AutoStrutsConfigRegisterプラグインからValidatorを参照しようとした際に、NullPointerExceptionが発生していたようです。className="org.seasar.struts.plugin.AutoStrutsConfigRegisterPlugIn">:</plug-in>----------------------------------------------------のように、Validatorプラグインを先に書くだけです。してもNullPointerExceptionが出ると原因特定に骨が折れます。コメント:0次のページプロフィールAuthor:crossroad関西在住。フリーランスのソフトウェアエンジニア。エレキベース(Rock&Roll)とお酒が好物でございます。