2011年10月15日土曜日

CassandraのCQLはスーパーカラム(SuperColumn)の存在無視なのか?

ご存知、Apache Cassandraは0.8からCQLなるものをリリースしました。
こりゃ便利だと、使ってるメモです。

CQLはSQLととても似てて(つか狙って似せてるんだろう)親しみやすいです。
SELECTなんかも以下のような構文でSQL知ってりゃすぐわかる感じです。

SELECT * FROM カラムファミリ WHERE KEY = キー
なので、こんな事もできます。
SELECT * FROM カラムファミリ WHERE COL1 = 条件1 AND COL2 = 条件2
ただし、スーパーカラム(SuperColumn)をいっぱい使用している0.7時代のユーザは
このCQLのちょっと意味不明な仕様にがっかりしたんじゃないのかと思う。

SELECT文にてWHERE句に指定できるカラムは
セカンダリインデックスが付いてないとダメ!!!

ええええ?だってさ、SuperColumnってセカンダリインデックス貼れないじゃん!
これは困りますよね。。。

SuperColumnってCassandraの強みと1つに数えられるくらい大切なものじゃないの?
新しくCQLなるものを出したんならそこに対応していないってのもどうかと思う。

ここで書いてるのはあくまで自分で調べた結果であって、
もし、、いやいやこーやればできんじゃん!ってのがあれば是非ご教授下さい。

@PostConstructと@PreDestroyの悩み

アノテーションの使い方を前回で書いたのはいいんだけども。

ちょっと気になったので試したら悩みができた。。。
@Autowiredとか@Resourceとかで設定した場合でprototype指定されていたら、
ApplicationContextを直接持ってないとこでdestroyって呼べなくね?みたいな。
ApplicationContext持ち回せばいいのかな。。。。

試しに以下のようなコードを書いたが確かにdestroyは呼ばれない。(前回試してるから当たり前なんだが)
クラスを2重にするのがめんどくさかったのでJUnitで。。。。

対象Bean
package com.zomu.t.example;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

@Component("testComponent")
@Scope("prototype")
public class TestComponent {

 @PostConstruct
 public void init() {
  System.out.println("init.");
 }

 public void outputMsg() {
  System.out.println("msg....");
 }

 @PreDestroy
 public void destroy() {
  System.out.println("destroy.");
 }

}


実行クラス
package com.zomu.t.example;

import javax.annotation.Resource;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:ApplicationContext.xml" })
public class TestInitDestroy2 {

 @Resource(name = "testComponent")
 TestComponent tc = null;

 @Test
 public void main() {
  tc.outputMsg();
 }
}


んーどうすりゃいいんだ。
思いつくのはこれしかない。

実行クラス
package com.zomu.t.example;

import javax.annotation.Resource;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:StoreManager-Common-ApplicationContext.xml" })
public class TestInitDestroy2 {

 @Resource(name = "testComponent")
 TestComponent tc = null;

 @Autowired
 ConfigurableApplicationContext appContext = null;

 @Test
 public void main() {
  tc.outputMsg();

  appContext.getBeanFactory().destroyBean("testComponent", tc);
 }
}
やってることは、前回と変わりはない。ApplicationContextと手を握り合って「バルス」って唱えただけ。

これだと当たり前にdestroyも呼ばれるんだが。
他にいい方法ってないの?

@PostConstructと@PreDestroy

Springの@PreDestroyと@PostConstructについて。
これはBean定義時代の「init-method」と「destroy-method」のアノテーション。

Scopeをprototypeで作成したBeanについて@PreDestroyはいつ呼ばれんだ?
って気になったので、サンプルを作成して確かめたんでメモる。

まずは、prototypeで作成しない場合の例

対象のComponent
package com.zomu.t.example;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

import org.springframework.stereotype.Component;

@Component("testComponent")
public class TestComponent {

 @PostConstruct
 public void init() {
  System.out.println("init.");
 }

 public void outputMsg() {
  System.out.println("msg....");
 }

 @PreDestroy
 public void destroy() {
  System.out.println("destroy.");
 }

}


実行クラス
package com.zomu.t.example;

import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestInitDestroy {

 public static void main(String[] args) {

  ConfigurableApplicationContext appContext = new ClassPathXmlApplicationContext(
    new String[] { "ApplicationContext.xml" });

  TestComponent tc = (TestComponent) appContext.getBean("testComponent");

  tc.outputMsg();

  appContext.close();

 }
}


結果
init.
msg....
destroy.

おお。ちゃんと呼ばれてますね。
では、prototypeで作成した場合。

対象のComponent
package com.zomu.t.example;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

@Component("testComponent")
@Scope("prototype")
public class TestComponent {

 @PostConstruct
 public void init() {
  System.out.println("init.");
 }

 public void outputMsg() {
  System.out.println("msg....");
 }

 @PreDestroy
 public void destroy() {
  System.out.println("destroy.");
 }

}

さっきと違うのは、@Scopeでprototype指定しているだけ。
実行すると、、、

結果
init.
msg....

あれ、destroyが呼ばれない。
なんじゃこりゃ。
プロトタイプだから、もうBeanFactoryの知ったこっちゃねぇって事?
じゃー実行クラスで実験してみる。

package com.zomu.t.example;

import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestInitDestroy {

 public static void main(String[] args) {

  ConfigurableApplicationContext appContext = new ClassPathXmlApplicationContext(
    new String[] { "ApplicationContext.xml" });

  TestComponent tc = (TestComponent) appContext.getBean("testComponent");

  tc.outputMsg();

  appContext.getBeanFactory().destroyBean("testComponent", tc);

  appContext.close();

 }
}


結果
init.
msg....
destroy.

なるほど。
ちゃんとインスタンスと登録名さえ渡してくれりゃケツ拭きまっせ。ってことっぽい。
めんどいから拭いてくれよー。って思いました。

2011年10月5日水曜日

Castorの使い方「Unmarshal」

Castorを使い始めて間もないが、基本的にネット上に転がっている情報ではUnmarshalについて詳しく載っていなくて
英語もあまり得意でない僕にとっては、苦戦を強いられた。。。

まずUnmarshalは、XML→Objectのこと。
おいおいそこからかよ。。。っていう気持ちを抑えて無駄にメモることにする。

使い道はいろいろあるだろうけど、
自分の場合はWebAPIの返却をオブジェクトとして扱いたかったから。
(XSDとか提供されていない場合に)

Unmarshalを行うコードは以下のようになる。
public class CastorTest {

 private static Mapping mapping;
 private static Unmarshaller unmar;
 private static CategoryList categoryList;

 public CastorTest() {

 }

 private void initialize() {
  mapping = new Mapping();
  try {
   mapping.loadMapping("xml/categoryList_mapping.xml");
   System.out.println("categoryList_mapping succeeded.");
  } catch (Exception e) {

  }
 }

 private void HandleCategoryList() {
  try {
   unmar = new Unmarshaller(mapping);
   categoryList = (CategoryList) unmar.unmarshal(new InputSource(
     new FileReader("xml/categoryList.xml")));
   Category[] categories = new Category[categoryList.getCategories().getCategories().size()];
   categories = (Category[]) categoryList.getCategories().getCategories().toArray();

   for (int i = 0; i < categories.length; i++) {
    Category category = categories[i];
    System.out.print(category.getName());
   }

  } catch (Exception e) {
   e.printStackTrace();
  }
 }

 public static void main(String[] args) {
  CastorTest test = new CastorTest();
  test.initialize();
  try {
   test.HandleCategoryList();
  } catch (Exception e) {
   System.out.println(e);
  }

 }
}
僕がつまづいたのは、Mapping定義を示すXMLファイルの書き方。。。 Unmarchalを行うXMLとそのMapping定義のXMLを続けて以下に示す。 ▼変換したいXML


 
  
   002
   名前1
   キー1
   親1
  
  
   001
   名前2
   キー2
   親2
  
 

▼Mapping定義


 
  
  
   
  
 
 
  
   
  
 
 
  
   
  
  
   
  
  
   
  
  
   
  
 


はまったところだけを書いておくと、、、、

->変換するXMLはエンコーディング指定をSJISにしないとだめ!
->ArrayListへ詰めるには上記のようにしなきゃだめ!
->基本的にclassタグにはtypeを書いておけ!
->たぶんclassは入れ子になっちゃダメ?

こんくらいかな。
誰かが救われれば本望です。

2011年10月1日土曜日

JSFの限界点 - イントロ -

JSF(JavaServerFaces)はSunが作ったフレームワーク。
MVC2を採用していてるJEEに準拠したもの。

導入はとても簡単でっていっても書かないけど、
GlassFishと併せて使ってみて相性がとてもいいんではないかと感じた。


基本的に製造順序としては以下のようになるのでは?と考えている。

1.画面(XHTML)の作成(ただし、ManagedBeanがなくてもいいようなプロト状態)
2.ManagedBeanの作成
  〜ビジネスロジック等も製造するけどまー省略〜
3.画面のManagedBeanへの適用


何回かに分けてこれから書こうかと思うが、
実際に使うことを検討したが、辞めた理由についてメモしていく。