■
<p>iPod touch 欲しい! id:hatenablog</p>
mavenでandroidを管理してみた
androidもmavenで管理したい!ってことで、実際にやってみた。
まずは、eclipseの設定から。 eclipseのheliosまたは、indigoが入っている事が前提。
- ADTのインストール。
- m2eのインストール。(m2eclipseじゃないよ。)
- m2e-androidのインストール。
んで、mavenのarchetypeがgithub上で公開されているので、そちらを使用。
今回は、android-release-archetypeを使用した。
mvn archetype:generate \ -DarchetypeArtifactId=android-release \ -DarchetypeGroupId=de.akquinet.android.archetypes \ -DarchetypeVersion=1.0.5 \ -DgroupId=com.foo.bar \ -DartifactId=my-android-project \ -Dpackage=com.foo.bar.android \ -Dplatform=4
あとは、eclipseにmavenImportするだけ。
ADTのバージョンが12以上になると、以下のプラグインではAPKBuilderのエラーが出てダメでした。
- m2eclipse
- m2eclipse-android-integration
SNSボタンを設置してみた
自分が使用した、SNSボタンの設置方法。
設置方法
facebook like button
http://developers.facebook.com/docs/reference/plugins/like/
上記のURLから自分のサイトのlikeボタンを作成した場合の例が下記。
iframeとxfbmlの2種類がある。個人的にはiframe版の方がよいかと思う。
<!-- iframe版 --> <iframe src="http://www.facebook.com/plugins/like.php?app_id=204714862912458&href=http%3A%2F%2Fsites.google.com%2Fsite%2Fdaimyou0410%2F&send=false&layout=box_count&width=450&show_faces=true&action=like&colorscheme=light&font&height=90" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:450px; height:90px;" allowTransparency="true"></iframe> <!-- XFBML版 --> <div id="fb-root"></div> <script src="http://connect.facebook.net/ja_JS/all.js#xfbml=1"></script> <fb:like href="http://sites.google.com/site/daimyou0410/" send="false" layout="box_count" width="450" show_faces="true" font=""></fb:like>
mixi check
http://developer.mixi.co.jp/connect/mixi_plugin/mixi_check/spec_mixi_check/
※mixi developerに登録する。その後、サービス登録し、mixiチェックキーを発行してもらい、ページの内容、許可ドメイン等を書く。
下記が自分のサイトでmixiチェックを設置する場合の例。
<a href="http://mixi.jp/share.pl" data-button="button-1" class="mixi-check-button d_inline" data-key="発行したチェックキー" data-url="http://sites.google.com/site/daimyou0410/" target="_blank">mixiチェック</a> <script type="text/javascript" src="http://static.mixi.jp/js/share.js"></script>
twitter tweet button
http://twitter.com/about/resources/tweetbutton
上記のURLから自分のサイトのtweetボタンを作成した場合の例が下記。
<a href="http://twitter.com/share" class="twitter-share-button" data-url="http://sites.google.com/site/daimyou0410/" data-text="#soba" data-count="vertical" data-via="daimyo_wakatono" data-lang="ja">Tweet</a> <script type="text/javascript" src="http://platform.twitter.com/widgets.js"></script>
snsのサーバがアクセス可能にする
下記のUser-Agentを見て、アクセス可能にする。
※twitterの場合は、snsサーバ側からコンテンツを取得しにこないので、特に必要はない。
facebookexternalhit/1.1 (+http://www.facebook.com/externalhit_uatext.php)
mixi
mixi-check/1.0 (http://mixi.jp/)
Open Graph タグの設置
そのページが何について書かれているかの情報を記述する。
※こちらを参照。
<meta property="og:title" content="タイトル" /> <meta property="og:url" content="ページのURL" /> <meta property="og:site_name" content="サイト名" /> <meta property="og:description" content="詳細" />
facebook URLリンターを利用して、どのように解析されるかを確認することが出来る。
テストパッケージをjarに固めてみた
フレームワークを自作するときに、共通的なテストユーティリティを提供する場合があった。
その場合、pomの設定でmvn installするとテストパッケージ(src/test配下)をjarに固めることが出来る。
pomの設定(共通的なテストユーティリティ)
クラス、ソースとJavaDocをJarに固める設定。
... <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <executions> <execution> <phase>package</phase> <goals> <goal>test-jar</goal> </goals> </execution> </executions> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-javadoc-plugin</artifactId> <executions> <execution> <phase>package</phase> <goals> <goal>jar</goal> <goal>test-jar</goal> </goals> </execution> </executions> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-source-plugin</artifactId> <executions> <execution> <phase>package</phase> <goals> <goal>jar</goal> <goal>test-jar</goal> </goals> </execution> </executions> </plugin> </plugins> </build> ...
pomの設定(使用する側)
実際に提供されたテストユーティリティを使う側の設定。
dependencyに先ほど作成したJarの依存設定を追加する。
... <dependencies> <dependency> <groupId>com.myco.app</groupId> <artifactId>hoge</artifactId> <classifier>tests</classifier> <scope>test</scope> </dependency> </dependencies> ...
tips
mvn installでパッケージングするが、ビルド時にテストが走ってしまうので、テストをパスしたい場合のコマンド。
テスト対象オプションの「test」に存在しないテストを指定。
テストの失敗を無視する設定「maven.test.failure.ignore」をtrueにする。
※無理やり感は満載です。
$ mvn install -Dtest=none -Dmaven.test.failure.ignore=true
※ちなみに下記でもテストをパスできるが、test用のjarが出来ません。
$ mvn install -Dmaven.test.skip=true
S2JDBCで複数データソースを使い分ける
S2JDBCで複数データソースを使い分ける方法はこちらにあった。
今回自分がしたいのは、同じ構成のテーブルでデータソースを分けたいので、dataSourceFactoryを使って分けるようにする。
一応自分がした設定を記述してみる。
設定ファイル
jdbc_datasource1.diconとjdbc_datasource2.diconはこちらにあるような感じで書いた。
で、2つのファイルをインクルードして、SelectableDataSourceProxyとDataSourceFactoryImplを定義した。
s2jdbc.diconもjdbcManagerは1つにするので、変更していない。
jdbc_datasource1.dicon
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE components PUBLIC "-//SEASAR//DTD S2Container 2.4//EN" "http://www.seasar.org/dtd/components24.dtd"> .... <components namespace="jdbc"> <component name="datasource1DataSource" class="org.seasar.extension.dbcp.impl.DataSourceImpl"/> </components>
jdbc_datasource2.dicon
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE components PUBLIC "-//SEASAR//DTD S2Container 2.4//EN" "http://www.seasar.org/dtd/components24.dtd"> .... <components namespace="jdbc"> <component name="datasource2DataSource" class="org.seasar.extension.dbcp.impl.DataSourceImpl"/> </components>
jdbc.dicon
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE components PUBLIC "-//SEASAR//DTD S2Container 2.4//EN" "http://www.seasar.org/dtd/components24.dtd"> <components namespace="jdbc"> <include path="jdbc_datasource1.dicon"/> <include path="jdbc_datasource2.dicon"/> <component name="dataSource" class="org.seasar.extension.datasource.impl.SelectableDataSourceProxy"/> <component name="dataSourceFactory" class="org.seasar.extension.datasource.impl.DataSourceFactoryImpl"/> </components>
インターセプタ
データソース用のアノテーション、enumとインターセプタを作った。
アノテーションで指定されているデータソースenumを見て、データソースを動的に切り替える仕組み。
インターセプタ
public class DataSourceSettingInterceptor extends AbstractInterceptor { /** データソースファクトリ */ @Resource protected DataSourceFactory dataSourceFactory; /** デフォルトデータソース */ private static final DataSourceType DEFAULT_DATA_SOURCE = DataSourceType.DATASOURCE1; /** * {@inheritDoc} */ @Override public Object invoke(MethodInvocation invocation) throws Throwable { DataSourceType currentDataSourceType = findCurrentDataSourceType(); try { DataSourceType dataSourceType = findDataSourceType(invocation.getMethod()); dataSourceFactory.setSelectableDataSourceName(dataSourceType.getDataSourceName()); return invocation.proceed(); } finally { dataSourceFactory.setSelectableDataSourceName(currentDataSourceType.getDataSourceName()); } } /** * 現在のデータソースタイプを取得する。<br> * @return 現在のデータソースタイプ */ private DataSourceType findCurrentDataSourceType() { String currentDataSourceName = dataSourceFactory.getSelectableDataSourceName(); if (StringUtils.isEmpty(currentDataSourceName)) { return DEFAULT_DATA_SOURCE; } DataSourceType dataSourceType; try { dataSourceType = DataSourceType.toDataSourceType(currentDataSourceName); } catch (IllegalArgumentException e) { // 想定外のデータソース名が渡された場合は、デフォルトデータソースを返す。 return DEFAULT_DATA_SOURCE; } return dataSourceType; } /** * データソースタイプを取得する。<br> * @param method メソッド * @return データソースタイプ */ private DataSourceType findDataSourceType(Method method) { DataSource dataSource = method.getAnnotation(DataSource.class); if (dataSource == null) { return DEFAULT_DATA_SOURCE; } return dataSource.type(); } }
アノテーション
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface DataSource { /** * データソースタイプを設定する。<br> */ DataSourceType type(); }
enum
public enum DataSourceType { /** データソース1用 */ DATASOURCE1("datasource1"), /** データソース2用 */ DATASOURCE2("datasource2"); /** データソース名 */ private String dataSourceName; /** * コンストラクタ<br> * @param newDataSourceName データソース名 */ private DataSourceType(String newDataSourceName) { this.dataSourceName = newDataSourceName; } /** * データソース名を取得する。<br> * @return データソース名 */ public String getDataSourceName() { return this.dataSourceName; } /** * 指定のデータソース名から対応するデータソースタイプを取得する。<br> * @param dataSourceName データソース名 * @return 対応するデータソースタイプ */ public static DataSourceType toDataSourceType(String dataSourceName) { for (DataSourceType dataSourceType : DataSourceType.values()) { if (dataSourceType.getDataSourceName().equals(dataSourceName)) { return dataSourceType; } } throw new IllegalArgumentException("指定のデータソース名に合致するデータソースタイプはありません。"); } }
インターセプタの使い方
一応、使い方。
@DataSource(type = DataSourceType.DATASOURCE1) public String hoge() { // do something }
あと、一部の機能のみデータソースを切り替えて実行したいときのために、エグゼキュータを作ってみた。
エグゼキュータ
public final class SelectableDataSourceExecutor { /** * コンストラクタ<br> */ private SelectableDataSourceExecutor() { } /** * データソースを指定のデータソースタイプに切り替えて実行する。 * @param <RESULT> 戻り値の型 * @param dataSourceType データソースタイプ * @param handler ハンドラ * @return 結果 */ public static <RESULT> RESULT execute(DataSourceType dataSourceType, Handler<RESULT> handler) { DataSourceFactory dataSourceFactory = SingletonS2Container.getComponent(DataSourceFactory.class); String currentDataSourceName = dataSourceFactory.getSelectableDataSourceName(); try { dataSourceFactory.setSelectableDataSourceName(dataSourceType.getDataSourceName()); return handler.handle(); } finally { dataSourceFactory.setSelectableDataSourceName(currentDataSourceName); } } /** * データソースの切り替え時に呼び出されるハンドラ。<br> * @param <RESULT> 結果の型 */ public interface Handler<RESULT> { /** * データソースの切り替え後に実行する。<br> * @return 結果 */ RESULT handle(); } }
エグゼキュータの使い方
一応、使い方。
public void hoge(final HogeDao dao, final HogeEntity entity) // do something SelectableDataSourceExecutor.execute(DataSourceType.DATASOURCE1, new SelectableDataSourceExecutor.Handler<Integer>() { /** * {@inheritDoc} */ @Override public Integer handle() { return dao.insert(entity); } }); // do something }
NodeJSをインストールしてみた
前から気になっていたNodeJSの開発をするために、インストールしたので、まとめておく。
基本的には、UnixとかMacでのインストールになるので、Windowsの場合はCYGWINでのインストールとなる。
CYGWINのインストール&設定
CYGWINをダウンロードする。
node.jsをインストールするために、必要なパッケージを導入。
今回、自分がいれたのは、下記。
インストール後、まれにDLLが読み込めないので、cygwin\bin\ash.exeで下記のコマンドをうつ。
※cygwin\bin配下を環境変数「PATH」に設定しておかないと自分の環境ではうまくいかず。
$ rebaseall
node.jsのインストール
CYGWINを起動する。
一応、パッケージがインストールされているかの確認。
$ gcc --version $ make --version $ python --version
今回は、wgetでダウンロードする。(GITでもいい。)
$ wget http://nodejs.org/dist/node-v0.4.8.tar.gz $ tar xvf node-v0.4.8.tar.gz
ダウンロード後、node.jsのインストールガイドにしたがって、コマンドをうつ。
$ ./configure $ make $ make install
※makeに時間が結構かかる。
インストールの確認。
$ node --version
動作検証
インストールが完了したら、動作検証を行う。
とりあえず、お決まりの「Hello world.」を表示するプログラム。
sample.js
var http = require('http'); http.createServer(function (request, response) { response.writeHead(200, {'Content-Type': 'text/plain'}); response.end('Hello World\n'); }).listen(8124);
で、起動。
$ node sample.js
http://localhost:8124/で起動確認できる。
ブラウザ上に「Hello world」と表示された。
npmのインストール
$ curl http://npmjs.org/install.sh | sh
で、npmで今回使うsocket.ioのインストール。
$ npm install socket.io
出来たー。
Ehcacheとterracottaの連携を試してみた。
大量のアクセスがあるWebサービスを運用している場合に、DBの負荷が非常に高くなっている場合がある。
RDBMSはスケールアウトしずらく、スケールアップでその高負荷に対応するなどして、ボトルネックを解消しようとすると思う。
RDBMSの高負荷の解消のためには、キャッシュ機構を使用して、DBへのアクセスを減らすという方法がある。
キャッシュ機構には、自分の知っているものは下記がある。
Ehchace
オープンソースの分散キャッシュサーバ。
memcachedと比べると、多機能である。
●キャッシュ方法
ディスクキャッシュ、メモリキャッシュをサポートする。
(※memcachedはメモリキャッシュのみ)
●キャッシュの追い出しポリシー
- LRU(Last Recently Used)
最後に参照された日時が最も古い順に削除する。
- LFU(Last Frequently Used)
参照された回数が最も少ない要素から順に削除する。
- FIFO(First In First Out)
要素がキャッシュに追加された順に削除する。
※memcachedはLRUが採用されている。
●レプリケーション
RMI(Remote Method Invocation)や、JMS(Java Message Service)を使用してレプリケーション・キャッシュ*1を実現することができる。
また、後で記述するが、Terracottaを用いたレプリケーションも可能である。
●その他機能
トランザクション、ロック、モニタリング等の機能も存在する。
Terracotta
複数のJVM間でJavaオブジェクトのクラスタリングを行う。
また、HiberfnateやSpringとの連携も容易である。(各ミドルウェア向けのモジュールが提供されている)
Ehcacheのインストール
現在、最新のバージョンは2.4.2。
今回はmaven2を使用してプロダクトをインストールする。
pom.xmlに下記を追記する。
<repository> <id>terracotta-release</id> <url>http://repo.terracotta.org/maven2</url> <releases><enabled>true</enabled></releases> <snapshots><enabled>false</enabled></snapshots> </repository> <dependency> <groupId>net.sf.ehcache</groupId> <artifactId>ehcache</artifactId> <version>2.4.2</version> <type>pom</type> </dependency>
また、APIでslf4jを使用しているので、下記も追記する。
<dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-jdk14</artifactId> <version>1.6.1</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.6.1</version> </dependency>
Terracottaのインストール
terracottaサーバの起動のために、Terracottaサイトから下記をダウンロードする。
現在の最新バージョンは3.5.1。
terracotta-3.5.1-installer.jar
下記コマンドでインストールする。
java -jar terracotta-3.5.1-installer.jar
また、TerracottaのruntimeAPIをダウンロードするために、pom.xmlに下記を記述する。
<dependency> <groupId>org.terracotta</groupId> <artifactId>terracotta-toolkit-1.2-runtime-ee</artifactId> <version>3.1.0</version> </dependency>
EhcacheとTerracottaの連携
下記のような構成の場合のEhcacheとTerracottaの連携方法をサンプルとして記述します。
●設定ファイルの作成
EhcacheとTerracottaを連携するためには、ehcache.xmlを作成する必要がある。
ehcache.xmlはクラスパスのルート位置に作成する。
ehcache.xml
<?xml version="1.0" encoding="UTF-8"?> <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="ehcache.xsd" updateCheck="true" monitoring="autodetect"> <!-- ディスクキャッシュ時のデータ保存領域 --> <diskStore path="java.io.tmpdir"/> <!-- terracottaの設定 --> <!-- <terracottaConfig url="localhost\:9510, your.domain:9510" /> --> <terracottaConfig> <tc-config> <system> <configuration-model>development</configuration-model> </system> <servers> <server host="localhost" name="server1"> <!-- permanent-store(ディスクに保存)に設定しないと再接続ができない。 --> <dso> <persistence> <mode>permanent-store</mode> </persistence> </dso> </server> <server host="your.domain" name="server2"> <dso> <persistence> <mode>permanent-store</mode> </persistence> </dso> </server> </servers> <clients> <logs>C:\app\logs-%i</logs> </clients> </tc-config> </terracottaConfig> <!-- デフォルトキャッシュ --> <defaultCache /> <!-- name: キャッシュ名 eternal:キャッシュオブジェクトの有効期限の有無(true:無) maxElementsInMemory:メモリ上にキャッシュするオブジェクトの最大数(0の場合は無制限) maxElementsOnDisk:ディクス上にキャッシュするオブジェクトの最大数(0の場合は無制限) overflowToDisk:キャッシュオブジェクトの最大数を超えた時、Diskに保持するかどうか。(true:する) ※terracottaを使用する場合はfalseに設定する。 timeToIdleSeconds:未アクセスの削除期限 timeToLiveSeconds:キャッシュオブジェクトの寿命 memoryStoreEvictionPolicy:メモリに格納するエントリが最大値に達したときの振る舞い(LRU、FIFOまたは、LFU) --> <cache name="terracottaTest" eternal="false" maxElementsInMemory="1000" maxElementsOnDisk="10000" overflowToDisk="false" timeToIdleSeconds="3600" timeToLiveSeconds="3600" memoryStoreEvictionPolicy="LFU"> <!-- terracottaを使用する --> <terracotta clustered="true" valueMode="serialization" consistency="strong" storageStrategy="DCV2"> <!-- 読み取り中にタイムアウトした場合は、ローカルから読み取る設定 --> <nonstop enabled="true" immediateTimeout="false" timeoutMillis="1000"> <timeoutBehavior type="localReads" /> </nonstop> </terracotta> </cache> </ehcache>
次に、Terracottaの設定ファイル「tc-config.xml」を任意の位置に作成する。
serversタグで書かれたサーバの起動順によって、アクティブサーバとスタンバイサーバになる。
tc-config.xml
<?xml version="1.0" encoding="UTF-8" ?> <tc:tc-config xmlns:tc="http://www.terracotta.org/config" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.terracotta.org/schema/terracotta-6.xsd"> <system> <configuration-model>development</configuration-model> </system> <servers> <server host="localhost" name="server1"> <data>%(user.home)/terracotta/server-data</data> <logs>%(user.home)/terracotta/server-logs</logs> </server> <server host="your.domain" name="server2"> <data>%(user.home)/terracotta/server-data</data> <logs>%(user.home)/terracotta/server-logs</logs> </server> <ha> <mode>networked-active-passive</mode> <networked-active-passive> <election-time>5</election-time> </networked-active-passive> </ha> </servers> </tc:tc-config>
●Terracottaサーバの起動
Windowsの場合とMac/Linuxの場合で起動バッチファイルまたはシェルファイルとなる。
先ほど作成した設定ファイルを使用する場合は、-fオプションで設定ファイルのパスを指定するとよい。
{terracottaのインストールディレクトリ}\bin\start-tc-server.bat (-f tc-config.xml)
{terracottaのインストールディレクトリ}/bin/start-tc-server.sh (-f tc-config.xml)
app.dicon
<component name="cacheManager" class="net.sf.ehcache.CacheManager"> @net.sf.ehcache.CacheManager@getInstance() <destroyMethod name="shutdown" /> </component>
実際にキャッシュに保存、取得するロジックは下記。
public class EhcacheLogic { @Resource protected CacheManager cacheManager; private Cache cache; /** * 初期処理。 */ public void init() { if (!this.cacheManager.cacheExists("terracottaTest")) { this.cacheManager.addCache("terracottaTest"); } cache = cacheManager.getCache("terracottaTest"); } /** * キャッシュに保存する。 * @param key キー値 * @param value 値 */ public void put(String key, String value) { Element element = new Element(key, value); cache.put(element); } /** * キャッシュから取りだす。 * @param key キー値 * @return 値 */ public Object get(String key) { Element element = cache.get(key); if (element == null) { return new String(""); } Serializable originalResult = element.getValue(); return SerializationUtils.clone(originalResult); } /** * キャッシュから削除する。 * @param key キー値 */ public void remove(String key) { cache.remove(key); } }
Terracottaでのクラスタリングは検証中であるが、からり早く各JVMにオブジェクトがコピーされていた。
Terracottaには開発者コンソールというものもある。どのような設定で動作しているのか、また、キャッシュの保存、取得、取得ミスなどの情報が閲覧できる。
調査をすすめて、こちらに追記していきたいと思う。
EhcacheとTerracottaの連携に関して、下記の本を参考にさせていただいた。
- 作者: 西岡祐弥,濱田章吾,横山彰子,浜本階生,ミック,uupaa,塙与志夫,はまちや2,大沢和宏,中島聡,矢野りん,中島拓,浦嶌啓太,角田直行,佐々木一,倉井龍太郎,深町英太郎,岩永賢明,高橋健一,柴田博志,井上誠一郎,大谷弘喜,荻野淳也,原悠,増井俊之,WEB+DB PRESS編集部
- 出版社/メーカー: 技術評論社
- 発売日: 2011/02/24
- メディア: 大型本
- 購入: 37人 クリック: 2,058回
- この商品を含むブログ (38件) を見る
*1:あるアプリケーションサーバのキャッシュにデータを格納すると他のアプリケーションサーバのキャッシュへデータをレプリケートするキャッシング方式