メイン

その他技術 アーカイブ

2007年01月19日

ORDB閉鎖

いつのまにかORDB(http://www.ordb.org/)が閉鎖されている。知らなかったです。
ORDBとは、不正中継を行う設定になっているメールサーバーをデータベース化し、無償で公開していた組織です。このデータベースはスパムメールのフィルタリングに有効活用されてきました。

ORDBが無くなった理由は、最近のスパムメールが送られる方法が変わってきたことが一番のようです。
メールサーバーの不正中継で送られるのではなく、クライアントPCに対してボットを送り、クライアントPCから送信されることの方が多くなってきたために、メールサーバーごと拒否ということがなかなか難しくなってきているのですね。これも時代の流れということでしょうか。 

恥をさらすようですが、私も自宅でサーバーを立てていたときに、ORDBに登録されてしまったことがあります。すぐに設定を直して申請しましたが、今となっては懐かしい思い出です。

2007年01月25日

Prototype.js 1.5リリース

http://journal.mycom.co.jp/news/2007/01/22/343.html

APIドキュメントも公開されました
http://prototypejs.org/api

2007年03月09日

Spring勉強会

Spring FrameworkというDIコンテナがありますが、その日本ユーザー会が設立されています。
Japan Springframework User Group(JSUG)
ここ主催で第1回の勉強会がまさに今この時間に開催されています。
たまたま私の会社で行われていたので少しだけ覗いてきましたが、第1回の参加者は70名という大盛況のようです。
参加された方の中には、実際にSpringを利用されている方もたくさんいらっしゃるようです。
Springもエンジニアリング技術のひとつとして現場に浸透してきたということではないでしょうか。
皆さんもご興味があればユーザー会に参加されてみてはいかがでしょう。

2007年03月16日

第2回 日本Springユーザー会

日本Springユーザー会の第2回が開催されます。
http://springframework.jp/?%CA%D9%B6%AF%B2%F1#f2d183a0

日時
 4/13(金) 19:00~21:00 , 21:00から自由参加の呑み会
内容
 19:00~20:00 SpringとORM
 20:00~20:10 ライトニングトークス
 トーカー募集中! オレのアツイ思いを聞いてくれな方、長い時間はアレだけど、トークスなら事例発表でもという方など募集中です。トーカー希望、もしくは誰もいないなら話してくれるという方は申し込み時にコメントでお申し込み下さい
 20:10~21:00 Spring+JPA, SpringJDBC
費用/場所
 参加費用:無料
 呑み会に参加される方は、およそ3000円程度
 場 所: 東京都新宿区西新宿2-1-1 新宿三井ビル34階 豆蔵 トレーニングルーム

2007年03月19日

SpringのHibernateTemplateに定義されていない処理を実装する方法

SpringのHibernateTemplateに定義されているメソッドは、Hibernateで実現可能なことの一部しか存在しません。HibernateTemplateに無い処理を実装したいときには、HibernateCallbackを使います。(getHibernateTemplate().getSessionFactory()することも出来ますが、それじゃあ。。。ね)
例えばAccountというエンティティがあり、それに対してユーザー認証(nameとpasswordが一致しているかどうか)を行う場合の記述は以下のような感じです。

package net.grandnature.example.invoice.dao.hibernate;

import java.sql.SQLException;
import net.grandnature.example.invoice.dao.AccountDao;
import net.grandnature.example.invoice.entity.Account;
import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.criterion.Expression;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

public class AccountDaoImpl extends HibernateDaoSupport implements AccountDao {
 public Account findAccount(final String name, final String password) {
  HibernateCallback callback = new HibernateCallback() {
   public Object doInHibernate(Session session)
   throws HibernateException, SQLException {
    Criteria criteria = session.createCriteria(Account.class);
    criteria.add(Expression.eq("name", name));
    criteria.add(Expression.eq("password", password));
    return criteria.uniqueResult();
   }
  };
  return (Account) getHibernateTemplate().execute(callback);
 }
}

HibernateCallbackのメソッドdoInHibernateがコールバックされます。この例ではHibernateTemplateをそのまま使っても実現できますが、Listで返って来てしまうのでちょっと気持ち悪いですよね。

2007年03月21日

FetchType.EAGER時に複数のbagを記述できない件

Hibernate Annotationsで、FetchType.EAGERを複数指定すると実行時に例外が発生します。
具体的には


org.hibernate.HibernateException: cannot simultaneously fetch multiple bags

というエラーです。ひとつのSQLクエリーの中でbagを2つ以上定義できないと言う意味です。

Hibernate Annotations FAQ(http://hibernate.bluemars.net/329.html)によると、解決策は以下の3つです。


  • bag形式で記述しない。@IndexColumnを付けてSetかListで利用する。

  • @CollectionIdを使う。

  • @Fetch(FetchMode.SELECT)か@Fetch(FetchMode.SUBSELECT)を指定する


LAZYじゃない形で一番簡単なのはFetchMode.SUBSELECTでしょうか。SUBSELECTを指定するとSQLを別々に発行します。

2007年03月23日

Hibernate Shards登場

Hibernateの新しいプロダクトです。(Contributed by Google)
http://www.hibernate.org/414.html
複数のRDBにデータを分割してI/Oする仕組みをHibernateで実現するもののようです。
主要な機能としては


  • Hibernate標準APIに沿ったモデル:Hibernateの標準APIを利用できるため、新たな使い方を覚える必要が無い

  • 柔軟な分割ロジック:データを分割する方法を柔軟に選択できる。自分で作ることも出来る。

  • virtual shardsのサポート:分割ロジックを変更した際の再分割が容易に行える

  • フリー・オープンソース:LGPL


なかんじみたいです。試してみよう。

2007年04月06日

Hibernate Shardsをちょっと触る

Hibernate Shardsは、複数のRDBにデータを分割してI/Oする仕組みをHibernateで実現するものです。
ほんの少しだけ触ってみました。変わったことは何もしていません。Hello Worldレベル。

  1. 必要なライブラリ
  2. Hibernate Shardsを用いるにはHibernate Coreが必要なので、
    • Core本体
    • Coreが依存するlib
    • Shardsのlib
    を入れる。試すJDBCドライバーも含める。

    +lib
     antlr.jar
     cglib.jar
     asm.jar
     asm-attrs.jars
     commons-collections.jar
     commons-logging.jar
     hibernate3.jar
     hibernate-shards.jar
     jta.jar
     dom4j.jar
     log4j.jar
     JDBCドライバーのjar

  3. RDBMSの設定

  4. Hibernate Shardsは複数のRDBMSに対してデータを分散して登録する。そのためにhibernateの設定ファイルをRDBMS分用意する。

    db1.hibernate.cfg.xml

    <hibernate-configuration>
     <session-factory name="sf0">
      <property name="dialect">org.hibernate.dialect.HSQLDialect</property>
      <property name="connection.driver_class">org.hsqldb.jdbcDriver</property>
      <property name="connection.username">sa</property>
      <property name="connection.password"></property>
      <property name="connection.url">jdbc:hsqldb:hsql://localhost:9001</property>
      <property name="hibernate.connection.shard_id">0</property>
      <property name="hibernate.shard.enable_cross_shard_relationship_checks">true</property>
      <property name="hbm2ddl.auto">create</property>
    ・・・
     </session-factory>
    </hibernate-configuration>

    db2.hibernate.cfg.xml

    <hibernate-configuration>
     <session-factory name="sf1">
      <property name="dialect">org.hibernate.dialect.HSQLDialect</property>
      <property name="connection.driver_class">org.hsqldb.jdbcDriver</property>
      <property name="connection.username">sa</property>
      <property name="connection.password"></property>
      <property name="connection.url">jdbc:hsqldb:hsql://localhost:9002</property>
      <property name="hibernate.connection.shard_id">1</property>
      <property name="hibernate.shard.enable_cross_shard_relationship_checks">true</property>
     <property name="hbm2ddl.auto">create</property>
    ・・・
     </session-factory>
    </hibernate-configuration>

    hibernate.connection.shard_idは、複数のRDBを識別する識別子となるので、かぶらないように別々の番号を振る。session-factorynameもかぶらないようにつけておく必要があるっぽい。


  5. エンティティとマッピングファイル
  6. エンティティを用意する。簡単に試したいのでidとvalueのみの単純なエンティティを使う。

    package net.grandnature.example.invoice.entity;

    public class Example {
     private Long id;
     private String value;
     public Long getId() {
      return id;
     }
     public void setId(Long id) {
      this.id = id;
     }
     public String getValue() {
      return value;
     }
     public void setValue(String value) {
      this.value = value;
     }
    }

    マッピングファイルはこんな感じ。

    example.hbm.xml

    <hibernate-mapping package="net.grandnature.example.invoice.entity">
     <class name="Example">
      <id name="id" type="long">
       <generator class="org.hibernate.shards.id.ShardedTableHiLoGenerator"/>
      </id>
      <property name="value"/>
     </class>
    </hibernate-mapping>

    ShardedTableHiLoGeneratorを用いると複数のRDBMSでHiloの値が重複しないようになる。identityなどで行いたい場合は、ひとつめのDBは0からはじまるように、ふたつめのDBでは1000からはじまるように、など、データ量に応じてIDが重複しないように自分でうまく調節する必要がある模様。

    ShardedTableHiLoGeneratorをHibernate Annotationでgeneratorとして指定するにはどうすればいいのかなあ。

  7. データを登録してみる
  8. public class ShardsExample {
     public static void main(String[] args) {
      new ShardsExample().insert();
     }

     void insert() {
      Session session = createSessionFactory().openSession();
      Transaction tx = session.beginTransaction();
      for (int i = 0; i < 10; i++) {
       Example example1 = new Example();
       example1.setValue(i + "番目");
       session.save(example1);
      }
      tx.commit();
      session.close();
     }

     SessionFactory createSessionFactory() {
      Configuration prototype = new Configuration().configure("db1.hibernate.cfg.xml");
      prototype.addResource("example.hbm.xml");
      List shard = new ArrayList();
      shard.add(new Configuration().configure("db1.hibernate.cfg.xml"));
      shard.add(new Configuration().configure("db2.hibernate.cfg.xml"));
      ShardStrategyFactory shardStrategyFactory = buildShardStrategyFactory();
      ShardedConfiguration shardedConfig = new ShardedConfiguration(
        prototype, shard, shardStrategyFactory);
      return shardedConfig.buildShardedSessionFactory();
     }

     ShardStrategyFactory buildShardStrategyFactory() {
      ShardStrategyFactory shardStrategyFactory = new ShardStrategyFactory() {
       public ShardStrategy newShardStrategy(List shardIds) {
        RoundRobinShardLoadBalancer loadBalancer = new RoundRobinShardLoadBalancer(
          shardIds);
        ShardSelectionStrategy pss = new RoundRobinShardSelectionStrategy(
          loadBalancer);
        ShardResolutionStrategy prs = new AllShardsShardResolutionStrategy(
          shardIds);
        ShardAccessStrategy pas = new SequentialShardAccessStrategy();
        return new ShardStrategyImpl(pss, prs, pas);
       }
      };
      return shardStrategyFactory;
     }
    }

    これを実行すると、db1.hibernate.cfg.xmlにて定義したRDBに

    ID:1, VALUE:0番目
    ID:2, VALUE:2番目
    ID:3, VALUE:4番目
    ID:4, VALUE:6番目
    ID:5, VALUE:8番目

    が入り、db2.hibernate.cfg.xmlにて定義したRDBに

    ID:32768, VALUE:1番目
    ID:32769, VALUE:3番目
    ID:32770, VALUE:5番目
    ID:32771, VALUE:7番目
    ID:32772, VALUE:9番目


    が入る。(例えばの話)

  9. データを取得してみる
  10.  void select() {
      SessionFactory sessionfactory = createSessionFactory();
      Session session = sessionfactory.openSession();
      List list = session.createQuery(" FROM Example ").list();
      for (Example example : (List) list) {
       System.out.println("ID:" + example.getId() + ", VALUE:" + example.getValue());
      }
     }

    単一のRDBを操作する場合と変わらない。複数のRDBであることを意識することなく取得できる。

  11. ShardAccessStrategyを別のものに換えてみる
  12. ShardAccessStrategyとは、データベースへのオペレーションを複数のRDBに対してどのように適用するかを定めたもの。現在の例はSequentialShardAccessStrategyを使っている。SequentialShardAccessStrategyは、複数のRDBに対してひとつずつ順番に処理を実行していく。これをParallelShardAccessStrategyに変更してみる。ParallelShardAccessStrategyはスレッドを生成し、複数のRDBに対して並列に処理を行う。

    変更したbuildShardStrategyFactory

    ShardStrategyFactory buildShardStrategyFactory() {
     ShardStrategyFactory shardStrategyFactory = new ShardStrategyFactory() {
      public ShardStrategy newShardStrategy(List shardIds) {
       RoundRobinShardLoadBalancer loadBalancer = new RoundRobinShardLoadBalancer(shardIds);
       ShardSelectionStrategy pss = new RoundRobinShardSelectionStrategy(loadBalancer);
       ShardResolutionStrategy prs = new AllShardsShardResolutionStrategy(shardIds);
       ThreadFactory factory = new ThreadFactory() {
        public Thread newThread(Runnable r) {
         Thread t = Executors.defaultThreadFactory().newThread(r);
         t.setDaemon(true);
         return t;
        }
       };
       ThreadPoolExecutor exec = new ThreadPoolExecutor(10, 50, 60,TimeUnit.MICROSECONDS,
         new SynchronousQueue(), factory);
       ShardAccessStrategy pas = new ParallelShardAccessStrategy(exec);
       return new ShardStrategyImpl(pss, prs, pas);
      }
     };
     return shardStrategyFactory;
    }

2007年04月10日

Hibernate Validatorを使う

Hibernate Validatorとは、ドメインモデルに対する制約条件をエンティティクラスにアノテーションで記述することが出来るようにしたHibernateのプロダクトです。エンティティクラスに書くのでバリデーションのコードが重複しにくいことや、アノテーションで手軽にかけるということくらいがウリでしょうか。

Beanのバリデーションを行う仕様は、JSR303 Bean Validationで進められているようです。

  1. 必要なライブラリ
  2. Hibernate Validatorを用いるにはHibernate Core本体、およびCoreが依存するjarに加え、Hibernate Annotationが必要です。
    Core以外には以下のjarがあればよいと思います。

    • ejb3-persistence.jar
    • hibernate-annotations.jar
    • hibernate-commons-annotations.jar
    • hibernate-validator.jar

    最近色々なHibernateのプロダクトがTOPレベルに昇格してきましたが、各プロダクトのバージョンをそろえないとうまく動かなかったりするので注意する必要があります。特にAnnotationは、バージョンが違っていても例外やエラーとなるのではなくアノテーションが適用されずに正常終了というケースもあるので不具合の判別が難しいことがあります。以下はhibernate.orgのCompatibility Matrixの抜粋です。

    Package Version Core Annotations EntityManager Validator Search Shards Tools
    Hibernate Core 3.2.2 GA - 3.2.x, 3.3.x 3.2.x, 3.3.x 3.0.x 3.0.x 3.0.x 3.2.0 Beta9

  3. エンティティクラス
  4. AnnotationとValidatorを使ったエンティティです。すごく簡単です。

    @Entity
    public class Customer implements Serializable {
     @Id
     @GeneratedValue(strategy = GenerationType.IDENTITY)
     public int id;
     @NotNull
     @Length(max = 10)
     public String name;
     @Range(min = 0, max = 100)
     public int age;
     @Email
     public String email;
     @Past
     public Date birthday;
    }

    アノテーションによって上記のエンティティに設定した制約を纏めると以下のような感じです。


    • nameはNULLであってはいけない

    • nameは10文字以内でなければならない

    • ageは0から100の範囲内にある数値でなければならない

    • emailはEメールアドレスの仕様に沿った記述でなければならない

    • birthdayは過去日付でなければならない


    これがアノテーションで書けるのは簡単でいいですね。ビルトインで用意されている制約は他にも@CreditCardNumberとか@Size(コレクションなどのサイズ)などがあります。

  5. 定義ファイル
  6. hibernate.cfg.xmlはこんな感じです。Hibernate Annotation用のmapping定義を追加している程度です。

    <hibernate-configuration>
     <session-factory>
      <property name="dialect">org.hibernate.dialect.HSQLDialect</property>
      <property name="connection.driver_class">org.hsqldb.jdbcDriver</property>
      <property name="connection.username">sa</property>
      <property name="connection.password"></property>
      <property name="connection.url">jdbc:hsqldb:hsql://localhost:9001</property>
      <property name="show_sql">true</property>
      <property name="format_sql">true</property>
      <property name="hbm2ddl.auto">create</property>
      <mapping package="net.grandnature.example.entity"/>
      <mapping class="net.grandnature.example.invoice.entity.Customer"/>
     </session-factory>
    </hibernate-configuration>

  7. 動かす
  8. ・・・と言っても普通に動かすだけなのですが

    SessionFactory sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory();
    Session session = sessionFactory.openSession();
    Transaction tx = session.beginTransaction();
    Customer customer = new Customer();
    customer.name = "KIDA Taro";
    customer.age = 76;
    customer.email = "kida@example.com";
    DateFormat parser = DateFormat.getDateInstance();
    ex.birthday = parser.parse("1930/12/06");
    session.save(ex);
    tx.commit();
    session.close();

    このまま動かすと普通に登録されます。もし、例えばbirthdayが未来日付だったりEメールアドレスに不正なものが設定されていたりと、エンティティの状態が制約に違反していると、save時にorg.hibernate.validator.InvalidStateExceptionが投げられます。制約に違反している内容の詳細はInvalidStateExceptionのgetInvalidValuesメソッドで返されるorg.hibernate.validator.InvalidValueの配列に格納されています。

    ただし、@NotNullの制約に引っかかったときはorg.hibernate.PropertyValueExceptionが投げられます。

2007年04月11日

Hibernate Searchを触る

Hibernate Searchは、アノテーションによってドメインモデルの索引を生成し、テキストのクエリーからドメインモデルのエンティティを取得することができるようにしたプロダクトです。Hibernate Searchは、検索エンジンにApache Luceneを使っています。Hibernate Searchもこのたび晴れてHibernateのTOPプロジェクトに昇格したプロダクトです。(まだベータ版ですが)

ということでHibernate Validatorを触ったりHibernate Shardsを触ったりしたついでに少しだけ触ってみます。Hello Worldレベルです。

  1. 必要なライブラリ
  2. 面倒なので、前回のHibernate Validatorを使ったときのものを流用することにします。これに加えて必要なものは

    • lucene-core-2.1.0.jar
    • hibernate-search.jar

    です。どちらもHibernate Searchのアーカイブの中に含まれています。JMSを使うのであればjms.jarも要りますが今回は使いません。なおLuceneが2.1.0よりも古いと動かなくなったみたいなので注意です。

  3. エンティティクラス
  4. 前回のHibernate Validatorを使ったときのエンティティを少しだけ改造します。

    @Entity
    @Indexed
    public class Customer implements Serializable {
     @Id
     @GeneratedValue(strategy = GenerationType.IDENTITY)
     @DocumentId
     public int id;
     @NotNull
     @Length(max = 10)
     @Field(index = Index.TOKENIZED, store = Store.YES)
     public String name;
     @Range(min = 0, max = 100)
     public int age;
     @Email
     public String email;
     @Past
     public Date birthday;
    }

    赤字のところしか変えていません。

  5. 定義ファイル
  6. hibernate.cfg.xmlはこんな感じです。Hibernate Search用に変えている部分は省略しています。

    <hibernate-configuration>
     <session-factory>
      ・・・
      <property name="hibernate.search.default.directory_provider">
       org.hibernate.search.store.FSDirectoryProvider
      </property>
      <property name="hibernate.search.default.indexBase">C:\Indexes</property>
      <mapping package="net.grandnature.example.entity"/>
      <mapping class="net.grandnature.example.invoice.entity.Customer"/>
      <event type="post-update">
       <listener class="org.hibernate.search.event.FullTextIndexEventListener"/>
      </event>
      <event type="post-insert">
        <listener class="org.hibernate.search.event.FullTextIndexEventListener"/>
      </event>
      <event type="post-delete">
        <listener class="org.hibernate.search.event.FullTextIndexEventListener"/>
      </event>
     </session-factory>
    </hibernate-configuration>

    Luceneによって生成されるインデックスのファイル達がC:\Indexesに保存される設定です。

  7. エンティティを登録してみる
  8. Sessionをそのまま使うのではなくFullTextSessionを取得してそれを使うようにします。それ以外は普通です。


    SessionFactory sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory();
    Session session = sessionFactory.openSession();
    FullTextSession fullTextSession = Search.createFullTextSession(session);
    Transaction tx = fullTextSession.beginTransaction();
    Customer customer = new Customer();
    customer.name = "KIDA Taro";
    customer.age = 76;
    customer.email = "kida@example.com";
    DateFormat parser = DateFormat.getDateInstance();
    ex.birthday = parser.parse("1930/12/06");
    fullTextSession.save(ex);
    tx.commit();
    fullTextSession.close();

    これを実行してエンティティがRDBに永続化されると、Luceneのインデックスも同時に生成されています。C:\Indexesの中にそれらしいファイルが出来ていると思いますが、それらがLuceneのインデックスファイルです。

  9. 検索してみる
  10. SessionFactory sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory();
    Session session = sessionFactory.openSession();
    FullTextSession fullTextSession = Search.createFullTextSession(session);
    BooleanQuery booleanQuery = new BooleanQuery();
    booleanQuery.add(new PrefixQuery(new Term("name", "Kida")),BooleanClause.Occur.SHOULD);
    Query fullTextQuery = fullTextSession.createFullTextQuery(booleanQuery);
    Iterator result = fullTextQuery.iterate();
    while (result.hasNext()) {
     Customer customer = (Customer) result.next();
     System.out.printf("%d - %s%n", customer.id, customer.name);
    }
    ・・・

    BooleanQuery、PrefixQuery、BooleanClause、TermはLuceneのクラスです。QueryはHibernateのQueryです。こんな感じでクエリーから該当するHibernateのエンティティのインスタンスを取得できます。

2007年07月14日

Silverlightを触る

Silverlightとは、Micsoroftの.Net3.0技術のうちのひとつです。「WPF(Windows Presentation Foundation)」という画面描画のための新しい技術を、ブラウザに組み込んでどこでも使えるようにしたものというような解釈を(私は)しています。
利用者側はFlashのようにプラグインを入れて動作させます。逆に言うと、プラグインさえ入れれば利用できます。利用者は.Net3.0のランタイムなどを入れる必要はありません。通常のWPFアプリのように、.Netのdllなどをクライアント側に配置して動かすこともできるようですが、JavaScriptのみで動かすのが本流ではないかと思います。

Silverlight本体は、「Silverlight.js」というJavaScriptのファイルで提供されているようです。
WPFなので、「XAML(eXtensible Application Markup Language)」というXMLで画面を記述します。XAMLは「ザムル」と呼ぶようです。
基本的には、


  • html

  • 画面を定義したxaml

  • Silverlight.js(Silverlight本体)

  • Silverlightを呼んだり、イベント処理を行うJavaScript


があれば動きます。
ためしに簡単なサンプルを作ってみました。

サンプルはこちらです。
サンプルのファイルをダウンロードできるようにまとめたものはこちらです。

なお、サンプルに初めてアクセスするときに、Silverlightのプラグインを入れるかどうか聞いてきます。サンプルをみるためにはプラグインのインストールを許可する必要があります。

このサンプルで作ったのは、以下のXAML程度です。簡単なものです。

<Canvas
 xmlns="http://schemas.microsoft.com/client/2007"
 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 Width="500" Height="450"
 >
 <Canvas.Triggers>
   <EventTrigger RoutedEvent="Canvas.Loaded">
    <EventTrigger.Actions>
     <BeginStoryboard>
      <Storyboard>
    <DoubleAnimation Storyboard.TargetName="angle"
        Storyboard.TargetProperty="Angle"
        From="0" To="360" Duration="0:0:10" RepeatBehavior="Forever" />
      </Storyboard>
     </BeginStoryboard>
    </EventTrigger.Actions>
   </EventTrigger>
  </Canvas.Triggers>
 <TextBlock Opacity="1" RenderTransformOrigin="1.022,0.458" Width="188" Height="46" FontSize="30" TextWrapping="Wrap" Canvas.Left="8" Canvas.Top="215.001" x:Name="title" FontWeight="Normal">
  <TextBlock.RenderTransform>
   <TransformGroup>
    <RotateTransform x:Name="angle" Angle="0"/>
   </TransformGroup>
  </TextBlock.RenderTransform>
  <TextBlock.Foreground>
   <LinearGradientBrush EndPoint="1,0.5" StartPoint="0,0.5">
    <GradientStop Color="#FF000000" Offset="0"/>
    <GradientStop Color="#FFFFFFFF" Offset="0.967"/>
    <GradientStop Color="#FF77777D" Offset="0.354"/>
    <GradientStop Color="#FFDBDBDD" Offset="0.967"/>
    <GradientStop Color="#FFA6A6AE" Offset="0.938"/>
   </LinearGradientBrush>
  </TextBlock.Foreground>
  GrandNature
 </TextBlock>
</Canvas>

XAMLの定義は、手作業でやるのは相当しんどいのでExpression Blendというツールを使うのがよいみたいです。7/13に、他のツールと併せてExpression Studioとして発売されたようです。
今回はそちらの試用版を使ってみました。タダにしてくれないかなあ。
Silverlight、流行りますかね。

2007年07月19日

Adobe Integrated Runtime (AIR)を触る

Adobe Integrated Runtime (AIR)は、Adobeが提供しているプロダクトです。AIRは、Webアプリの開発技術をベースにデスクトップアプリを作ることが目的のようです。HTML、やJavaScriptのみならず、FlashやPDFといった既存の様々な技術要素を組み合わせることができるから「Integrated Runtime」なのでしょう。ちなみにAIRは「Apollo」というコードネームです。

  1. AIRの実行環境
  2. 以下から落とせます
    http://labs.adobe.com/downloads/air.html
    利用者はこれが入っていないとAIRのアプリケーションを実行できません。利用者が明示的に実行環境をインストールしなければなりません。

  3. SDK
  4. Flex3のSDKの中に含まれているようなのでこちらを使ってみました。(AIR単体のSDKもあります。)
    http://labs.adobe.com/technologies/flex/sdk/flex3sdk.html
    もうFlex3なんですね、全然ついていけません。AIRは、Flexの技術要素を使わずにJavaScriptやHTMLとAIRのAPIだけで作ることもできますが、Flexと連携するのが本流のようです。

  5. IDE
  6. 一般的なIDEはFlex Builder 3のようですが、私はAptana IDEを使いました(ステップ実行はできませんが)。Aptana起動画面のpluginsタブに「Download and install the Aptana plugin for Adobe AIR Support」というリンクがあります。そこからAIRの開発環境をインストールすることができます。

  7. サンプル
  8. 自分で作る気力がなかったのでサンプルを見る程度でお茶を濁すことにしました。
    以下にあるサンプルの
    http://labs.adobe.com/wiki/index.php/Apollo:Applications:Samples
    Freshというものを見ました。このサンプルはFlexを使っていないようです。htmlとJavaScriptだけでできています。画面デザインはhtml(fresh.html)です。このHTMLがデスクトップアプリになるとは。すごいなあ。
    画面からのイベントや画面の部品とJavaScriptを紐付けて、そこからAIRのAPIを呼ぶような感じです。
    ちなみに、RSSのfeedなどの情報は、Local Storeに保存されています。Local Storeの場所は

    C:\Documents and Settings\[user]\Application Data\com.adobe.apollo.samples.fresh\Local Store

    のあたりです。

  9. 配布
  10. AIRのアプリケーションの配布は簡単です。Aptanaであれば、プロジェクトを右クリックし、「エクスポート」->「Adobe Air Package」を選択することで、AIRのパッケージファイルを作成できます。このファイルはインストーラーになっています。

2007年07月30日

LOGO

LOGOという言語について書かせて頂きました。もしよろしければご覧下さい。

前編
http://gihyo.jp/dev/serial/01/enjoy-pg/0003
後編
http://gihyo.jp/dev/serial/01/enjoy-pg/0004

2007年08月29日

ワークフローエンジンのプロセスを変更するときって

ワークフローエンジンを使うとプロセスと処理が分離できるので、プロセスの変更があった際に、処理のコードを変更する手間が減るという常套句はわかるのですが、プロセスを変更するときって、古いプロセスで動いてたインスタンスたち(個々の申請とか)は、どう扱うのがセオリーなんでしょう??

JBossのjBPMでは、プロセスに履歴の概念があり、変更されたプロセスがデプロイメントされても、それまでに動いているインスタンスは古いプロセスに紐づいたまま動くようです。あと人から聞いただけですがWebLogicのワークフローのやつでは、そもそも生きているインスタンスが残っている間はプロセスの変更が出来ないっぽい、らしい。

何でそうなのかわかる気もします(プロセスのどの部分が変えられているのかわからないし、プロセスの追記だけであればいいけど元のプロセスから何かが削られると宙ぶらりんなインスタンスが出来るし)が、これってプロセスの変更に柔軟って言えるのかなーって思ってしまいます。

生きているインスタンスが残っているときにプロセスを変える場合、データの整合性を保つのは運用でカバーするんだよなきっと。これってすごく大変じゃないかな?となると現実的にはインスタンスが生きているときのプロセスの変更は無しなんでしょうね、でも、さらに現実的には生きているインスタンスが無いタイミングなんてのはなかなか無いだろうから、そうなると、ワークフローエンジンを使う限りプロセスは変更しちゃならんってことになるか?

もちろん、年度とかでプロセスの区切りが明確にわかることもあるだろうから、そういうときには一時的に古いプロセスで動いてくれてもいいんだよなきっと。

2007年09月05日

dRubyの正面

dRuby本を読んだ感想を書くページを作りました。

dRubyの正面

2007年11月05日

豆ナイト「体験入学!!豆ナイト学園2年3組 - 今さら聞けないAjax」

豆蔵で豆ナイトという夜間勉強会をやっています。
今回はAjaxがテーマです。
まだ申し込み可能なので参加してみよう!

http://www.mamezou.net/modules/mamenight1/

開催日時
2007年11月12日(月) 19:00~21:00
場所
新宿三井ビル34階 株式会社豆蔵 トレーニングルーム
タイトル
体験入学!!豆ナイト学園2年3組 - 今さら聞けないAjax


2008年04月28日

HQLからSQL

例えばこんな感じ。

Job job = (Job) jobDao.getHibernateTemplate().load(Job.class, 1L);
QueryTranslator t = new QueryTranslatorImpl("select man from Man as man where job=:job", "select man from Man as man where job=:job" ,null, (SessionFactoryImplementor)jobDao.getHibernateTemplate().getSessionFactory());
t.compile(null, false);
List list = jobDao.getHibernateTemplate().getSessionFactory().getCurrentSession().createSQLQuery("select count(*) from ( " + t.getSQLString() +")").setEntity(0, job).list();

2008年05月27日

件数の指定

hibernateではsetFirstResult、setMaxResultsなどで取得時の件数を指定できます。
SQLにlimitやoffsetが付いた形で発行されるので、結果セットが膨らまず、有効です。
しかし、コレクションに対してfetch joinしている場合には件数が狂います。
対策としてはlazyにするか、結果セットのリストを自分でsubListする、などになります。

DetachedCriteriaとCriteria

通常、CriteriaはSessionオブジェクトから生成します。DetachedCriteriaは、HibernateのSessionオブジェクトのインスタンスを参照することが出来ない状況下でCriteriaを構築するために用意されています。
ただしバージョンによってはCriteriaで出来ることがDetachedCriteriaで出来ないことがあります。たとえばDetachedCriteriaではcreateCriteria, createAlias時に結合方法の指定が出来ない、などです。Hibernateのバージョン3.2.6以降では対応されていますので、3.2.6以降を利用するとよいと思います。バージョン3.2.6では、DetachedCriteriaとCriteriaとのインタフェースの差異がなくなっているようです。

Add outer join support for aliases on DetachedCriteria

なお、setFetchModeでの指定は可能ですので、こちらで何とかするという方法もあります。

2008年06月02日

自インスタンスのメソッド呼び出し時にAOPがかからない

Spring FrameworkでのAOPの話です。Springに限らずそうですが、AdviceがPointCutにマッチしたとしても、自インスタンスからの呼び出し時には適用されません。(Proxy越しにならないからですね。)
他のインスタンスからの呼び出しに変えるのが最もわかりやすい方法ですが、そのように出来ない場合には、自インスタンスのメソッド呼び出し前にProxyを作ってAdviseを適用しなおすような方法になると思います。
例えば以下のような感じです。

ProxyFactory proxyFactory = new ProxyFactory(this);
Map advisors = ((ListableBeanFactory) BeanFactoryの取得).getBeansOfType(Advisor.class);
Iterator iterator = advisors.keySet().iterator();

while (iterator.hasNext()) {
 Advisor advisor = (Advisor) advisors.get(iterator.next());
 proxyFactory.addAdvisor(advisor);
}

こうすると、proxyFactory.getProxyでインスタンスが取れます。こいつ越しに呼べば、ちゃんとAOPがかかります。(ださいですが。。)


2008年08月20日

Validatorを自作

Hibernate Validatorで調べると、日本語ではなぜかこのサイトが一番上に出てきます。不思議ですが、せっかくなので自前のValidatorを作る方法を載せておきます。とても簡単です。

 ちなみにHibernate Validatorを使ったバリデーションは、org.hibernate.validator.ClassValidatorなどを使って明示的に実行すれば、エンティティに限らずどんなJavaBeanでも使えます。対象のクラスのことをHibernateが知っている必要はありません。

まずアノテーションから

@Documented
@ValidatorClass(StringDateValidator.class)
@Target({METHOD, FIELD})
@Retention(RUNTIME)
public @interface StringDate {
  String message() default "{errors.date}";
  String pattern() default "yyyyMMdd";
}

実装クラスはこんな感じです。

public class StringDateValidator implements Validator, Serializable {
  private static final long serialVersionUID = -7262522203009002581L;
  private String pattern;
  public void initialize(StringDate parameters) {
    pattern = parameters.pattern();
  }
  public boolean isValid(Object value) {
   if ( value == null ) return true;
   if (!(value instanceof String)) return false;
   String str = (String) value;
   if(str.length()==0) return true;
   SimpleDateFormat sdf = new SimpleDateFormat(pattern);
   sdf.setLenient(false);
   try {
    sdf.parse(str);
   } catch (ParseException e) {
    return false;
   }
   return true;
  }
}

こんな感じでアノテーションと実装のセットを作るだけで使えます。楽チンですね。

2008年09月03日

Google Chrome

WebKitは開発ツールもMacがメインのターゲットと言う感じで、Windowsだと色々と結構めんどくさそうですが、Chromeが賑やかになると、Winユーザーも色々と楽しいことがありそうですね。
そして、ChromeはWebKitを使っているということで、Androidとのコラボが非常に楽しみになります。色々と可能性が開きそうです。

gmailがかなり快適に使えますね。私は、仕事用も個人用もどちらもgmailなので、アクセスが速くなるのはかなり嬉しいです。
全体的にSafariより高速な気がするのはなぜでしょう。私のMacがただ遅いだけかもしれませんが。

2008年09月16日

Hibernate - 固定長文字列(CHARなど)のカラムに対して半角スペースでpaddingしたい

自分ではカラムの型に固定長文字列を使った事がなかったので、このような問題に遭遇したことがありませんでした。解決方法の例としては、アプリケーションのコードで毎回やる方法もありますが、ユーザー型(UserType)を使う方法とかもあります。ユーザー型の場合は、以下のような感じのクラスを作ります。

package example.usertype;

public class RightPadUserType implements UserType, ParameterizedType {
  public int[] sqlTypes() {
    return new int[] { Types.VARCHAR };
  }
  public Class returnedClass() {
    return String.class;
  }
  public boolean equals(Object x, Object y) throws HibernateException {
    return EqualsHelper.equals(x, y);
  }
  public int hashCode(Object x) throws HibernateException {
    return x.hashCode();
  }
  public Object assemble(Serializable cached, Object owner)
      throws HibernateException {
    return cached;
  }
  ・・・(省略)
  public Object nullSafeGet(ResultSet rs, String[] names, Object owner)
      throws HibernateException, SQLException {
    String value = rs.getString(names[0]);
    if(value==null)
      return "";
    return value;
  }
  
  public void nullSafeSet(PreparedStatement st, Object value, int index)
      throws HibernateException, SQLException {
    if (value == null) {
      st.setNull(index, Types.NULL);
    } else {
      st.setString(index, StringUtils.rightPad((String)value, length));
    }
  }
  // カラム長
  private int length = 0;
  public void setParameterValues(Properties properties) {
    if(properties.get("length") != null)
      length = Integer.parseInt((String)properties.get("length"));
  }
}

trimしてもいいのですが、trimだと検索時にindexが効かず遅くなりそうなので、padする方がよいような気がします。ただ、そうすると、カラム長を教えてあげる必要があります(※1)。以下はhbmで書いた場合の例です。

<hibernate-mapping>
 <class name="example.Job" table="Jobs">
・・・
    <property name="name">
      <type name="example.usertype.RightPadUserType">
       <param name="length">10</param> ※1
      </type>
    </property>
・・・
  </class>
</hibernate-mapping>

自動生成する方法を作って工夫しないと面倒そうです。あまりいい方法ではないかもしれません。


2008年11月20日

NetBeans IDE 6.5リリース

NetBeansの6.5がリリースされました。
PHP、Groovy、Grailsをサポートしたようです。
また、FireFoxとIEでのJavaScriptデバッグの機能も追加されているようです。

http://www.netbeans.org/

2009年04月18日

Google App Engine for Javaのむずかしかったところメモ

メモです。

1. Google App Engine for Javaのサインアップ
Google App Engine for Javaを使うには、App Engineのサイト(http://appengine.google.com/)でサインアップを行う必要があります。サインアップを行うと、Googleからの完了通知(メール)が来るまで待たされる。完了通知が来るまでは、アプリケーションのデプロイメントなどが実施できません。

2. アプリケーション作成時の認証認可
アプリケーションを作成する際に、最初の一度だけはSMSによる認証認可が求められます。つまりSMSを受け取れる携帯電話などの端末が必要です。なお、SMSは海外から送信されます。このことが理由なのか、DoCoMoとKDDIはSMSを受け取れないことが多いらしいです。そのため、DoCoMoとKDDI以外の端末を持っていると楽に認証できます。私はSoftbankで実施しました。
「Country and Carrier:」を「Other」にし、SMSを受信したい端末の電話番号の先頭「0」をとり、「+81」をつけた電話番号を指定するとOKです。たとえば、「090-1234-5678」という電話番号だったとすると「+819012345678」になります。うまくいけば、指定した端末に対して、verification codeが送られてきますので、その番号をWEBで入力すれば、アプリケーションの作成が可能になります。

About その他技術

ブログ「GrandNature」のカテゴリ「その他技術」に投稿されたすべてのエントリーのアーカイブのページです。過去のものから新しいものへ順番に並んでいます。

前のカテゴリはAndroidです。

次のカテゴリはゴータマです。

他にも多くのエントリーがあります。メインページアーカイブページも見てください。