とりあえず読む本

今読んでる本

Java 開発の実用問答集 (プログラマーズ叢書)

Java 開発の実用問答集 (プログラマーズ叢書)


衝動買いした本


・・・いや、評価対策に3月中に資格なんか取れって?

アスペクト指向

うーん


確かにコードを分離したりできるのはいいのだけど、結局設定ファイルの記述量が倍になってしまったら意味がないんだよな。


やはりJavaも多重継承ができるようにしてくれんかなぁ。
そうするとやたらめったら多重継承する人もでてくるかもしれんが、「できるけどあまり推奨しないこと」とは別だと思うんだよねー。

AOP導入


前々から興味はあったけれども、なかなか手を付けてこなかった分野かな。


Actionクラスの中で、画面制御をするのにTokenを使うのはよくある手段だと思う。
これまではAbstractActionにメソッドを用意しておいて、実装クラスのexecute()の先頭で毎回読んでいた。
が、どうも人によって書いたり書かなかったりであまりよろしくないのである(もちろん気がついたところは修正しているが、それを頼られても困るわけである)。


そこでAOPの出番となる(はず)。

1.Jointpoint前にTokenをチェックする
1−1.問題なければsaveTokenをする
1−2.不正な場合はExceptionをthrowする
2.execute()の実行


うむ、完璧だ。


さて、肝心のSpringAOPだが、4つのAdviceが用意されている。
今回はBefore Adviceを使うわけである。

public class TokenManagementAdvice extends Action implements MethodBeforeAdvice {

(ログとか略)

  /**
   * Action#execute()の前に実行されるAdvice
   * isTokenValid()とsaveToken()を行う
   */
  public void before(Method m, Object[] args, Object target) throws Throwable {

    HttpServletRequest request = null;

    try{
      request = (HttpServletRequest) args[2];
    }catch(Exception e){
      log.warn("invalid arg" + e);
      return;
    }
    
    if (isTokenValid(request, false) == false) {
      log.warn("InvalidTransaction! : " + target.getClass() + m.getName());
      throw new InvalidTransactionException();
    }
    saveToken(request);
    
    if (log.isDebugEnabled()) {
      log.debug("Token check complete.");
    }
  }


isTokenValid()をするためにはActionクラスをextendsするのがちょっとあれなのだが、気にしない方向で。

struts-configではおなじみのspring連携

    <action path="/hogeInit"
            type="org.springframework.web.struts.DelegatingActionProxy"
            name="dummyForm"
            scope="request"
            validate="false">
        <forward name="success" path="/hoge"/>
    </action>


spring側の設定を次のように

    <bean name="/hogeInit"
      class="org.springframework.aop.framework.ProxyFactoryBean">
            <property name="target">
              <bean class="hoge.hogeInitAction"
                  singleton="false">
              </bean>
            </property>
            <property name="interceptorNames">
                  <value>advice</value>
            </property>
    </bean>
    <bean id="advice" class="hoge.TokenManagementAdvice"/>


あとはAutoProxyとかを使うかどうかかぁ。
ダウンロードするところとかは画面遷移はないのでToken制御はいらないし、ここはちょっと考えどころかな。


【参考】
SpringによるAOPの導入*1
Spring AOPサンプルアプリでAOPを理解する*2

Java・J2EE・オープンソース Spring入門 ~より良いWebアプリケーションの設計と実装

Java・J2EE・オープンソース Spring入門 ~より良いWebアプリケーションの設計と実装

DTOのソート


んな場合かというのは色々だろうけど、実際に使用したのでメモしておこう。


配列のソートというだけならば話は簡単なのだが、DTOのListをソートしたい場合の話。
これはjava.util.Collections*1を使うことで、DTOの任意の値でもってソートできる。


DTOの定義

public class Value {

  Value(String str1,String str2){
    setStr1(str1);
    setStr2(str2);
  } 
  
  String str1;
  String str2;
  
  public String getStr1() {
    return str1;
  }
  public void setStr1(String str1) {
    this.str1 = str1;
  }
  public String getStr2() {
    return str2;
  }
  public void setStr2(String str2) {
    this.str2 = str2;
  }
}

実行クラス

public class test {

    public static void main(String[] args) {
      Value v1 = new Value("AAA", "999");
      Value v2 = new Value("BBB", "000");
      Value v3 = new Value("CCC", "555");
      
      List<Value> values = new ArrayList<Value>();
      values.add(v1);
      values.add(v2);
      values.add(v3);

      //str1でソート
      Collections.sort(values,new Comparator<Value>(){
        public int compare(Value obj1, Value obj2) {
          return (obj1.getStr1()).compareTo(obj2.getStr1());
        }
      });
      
      print(values);
      
      //str1でソート
      Collections.sort(values,new Comparator<Value>(){
        public int compare(Value obj1, Value obj2) {
          return (obj2.getStr1()).compareTo(obj1.getStr1());
        }
      });
      
      print(values);

      //str2でソート
      Collections.sort(values,new Comparator<Value>(){
        public int compare(Value obj1, Value obj2) {
          return (obj1.getStr2()).compareTo(obj2.getStr2());
        }
      });
      
      print(values);
      
      //str2でソート
      Collections.sort(values,new Comparator<Value>(){
        public int compare(Value obj1, Value obj2) {
          return (obj2.getStr2()).compareTo(obj1.getStr2());
        }
      });
      
      print(values);
    }
    
    private static void print(List<Value> values){
      System.out.println("----------------------");
      for(Value v : values){
        System.out.println(v.getStr1()+","+v.getStr2());
      }
      System.out.println("----------------------");
    }

}


実行結果

----------------------
AAA,999
BBB,000
CCC,555
----------------------
----------------------
CCC,555
BBB,000
AAA,999
----------------------
----------------------
BBB,000
CCC,555
AAA,999
----------------------
----------------------
AAA,999
CCC,555
BBB,000
----------------------


とまぁ昇順・降順も任意に制御できるということらしい。
java.util.Collectionsには他にもいろいろと便利な機能がありそうだ*2

privateメソッドをテストする


はてな巡りをしていたら見かけたので*1、JavaWorldの2005年10月号を読み直してみたら確かに書いてあった。


まずはJUnit-addonsをダウンロードする*2


PrivateAccessor*3を使ってテスト作成。






糸冬






こんな便利なものを知らなかったとはorz。


「privateメソッドをテストする必要はない」という話もあるのだけど、使いたいところもたまにあるしということで*4

*1:http://d.hatena.ne.jp/vestige/20050914

*2:http://sourceforge.net/projects/junit-addons/

*3:http://junit-addons.sourceforge.net/junitx/util/PrivateAccessor.html

*4:分岐が多くてpublicメソッドへのテストだけだとちょっと複雑になりそうな場合とか?

改行コード


改行コード*1


多くの開発言語では改行をあらわす記号 '\r' や '\n' などがある。しかし、SQLPL/SQL にはない。
代わりに CHR 関数を使用する。

CHR(13) ... キャリッジリターン( CR )
CHR(10) ... ラインフィード( LF )


改行が CR+LF か LF のみかは OS によって異なるので注意が必要。

Windows 系 : CR + LF
UNIX 系 : LF のみ