Google Calendar API Client Javaを使ったアプリでサービスアカウントで認証するには

Google Calendar APIの認証はOAuth 2.0を利用しており、Webアプリケーション、クライアント・アプリケーションなどのシナリオをサポートしています。
(参照: Using OAuth 2.0 to Access Google APIs)

Google Appsを利用していて、企業向けのサービスや社内システムとGoogle Calendarを連携したい場合、システム単位でユーザーにアクセス許可を求めずに、ドメイン単位でGoogle Appsへのアクセスを設定したいところです。
このようなサーバー間およびバッチ(デーモン)アプリケーションのシナリオでは、JWT(Json Web Token)でサーバー用のアクセストークンを取得する方法が利用できます(2 Legged OAuthとも言う)。

サーバー間用のアクセストークンは、Google Appsのドメイン全体の委任を有効にしたサービス アカウントを作成し、サービス アカウントの秘密鍵を使って生成した署名を含むJWTをhttps://www.googleapis.com/oauth2/v4/tokenにPOSTすることで取得できます。
(参照: Using OAuth 2.0 for Server to Server Applications)

この記事は、サービス アカウントでGoogle Calendar APIへアクセスするシナリオでのJava API クライアント ライブラリの使い方について説明していきます。
簡単に流れは説明しましたが、クライアント ライブラリを利用するので、JWTの作成およびアクセストークンの取得についてはライブラリにおまかせです。
(参照: Calendar API Client Library for Java)

説明用のコードは、以下のJava API クライアントのサンプルのcalendar-cmdline-sampleを使います。
google/google-api-java-client-samples
このサンプルは、ユーザーに認可を求めるクライアント・アプリケーションです。
まずは元の動作を確認し、その後、サービスアカウント認証へ実装を変更していく流れで説明していきます。
“Google Calendar API Client Javaを使ったアプリでサービスアカウントで認証するには” の続きを読む

Zabbix 2.4 JavaゲートウェイでJMX監視 インストール手順

Zabbix 2.4でJVMの監視を設定してみたメモです

JMXの監視をZabbixに統合するにはZabbix Java gatewayを利用します

公式ドキュメントでは、インストール手順について「5 Java gateway」に、JMXによるJavaアプリケーションの監視設定について「14 JMX monitoring」に記述されています

Java gatewayは2.0から導入された機能で、JMXをネイティブに監視することが可能です。
監視対象のJavaのアプリケーションとしてTomcatを用意してJMXを設定し、ZabbixのHostsに追加するところまでまとめてみます

以下のように、Zabbixサーバーおよびフロントエンドがインストール済みの環境にJavaゲートウェイを追加するように構成してみます
Zabbixサーバー、フロントエンドとエージェントのインストールと設定方法については前回の記事「Zabbix 2.4 サーバー/エージェントをUbuntu 14.04にインストール」を参照ください
zabbix_java_gateway
“Zabbix 2.4 JavaゲートウェイでJMX監視 インストール手順” の続きを読む

Ubuntu 12.04にsun java 7をインストールする手順

[bash gutter=”false”]
$ sudo apt-get update
$ sudo apt-get install python-software-properties
$ sudo add-apt-repository ppa:webupd8team/java
$ sudo apt-get update
$ sudo apt-get install oracle-java7-installer
[/bash]
途中でライセンスの許諾が必要
install-java-on-precise-1
install-java-on-precise-2
インストールの確認
[bash]
$ java -version
java version "1.7.0_60"
Java(TM) SE Runtime Environment (build 1.7.0_60-b19)
Java HotSpot(TM) 64-Bit Server VM (build 24.60-b09, mixed mode)
[/bash]

参考: Install Oracle Java 7 in Ubuntu via PPA Repository ~ Web Upd8: Ubuntu / Linux blog

Eclipse Java開発でよく使うショートカットめとめ

私は普段英語版を使っているのでウィンドウ/パースペクティブの名前は英語で記述しています。

ナビゲーション

Open Resource (Ctrl + Shift + R)

Javaクラスに限らずワークスペース上の任意の種類のファイルを対象に検索したいときには Open Resource が便利です。
ワークスペース上のファイルを開く

Open Type (Ctrl + Shift + T)

Java SDK ライブラリやビルドパスに含まれるライブラリも含めてJavaのクラス/インタフェースを検索したいときには Open Type を使います。
クラス/インタフェースを検索 width=

任意のメンバーにジャンプ (Ctrl + O / Command + O)

現在開いているクラスのアウトラインを表示して、メンバー(メソッド/フィールド)にジャンプできます。
アウトラインを表示

関連するショートカット

  • 前のメンバーにジャンプ (Ctrl + Shift + Up / Ctrl + Alt + Up)
  • 次のメンバーへジャンプ (Ctrl + Shift + Down / Ctrl + Alt + Down)

クラス階層を表示 (Ctrl + T / Command + T)

現在開いているクラスのクラス階層を表示します。
クラス階層の表示
関連するショートカット

  • Type Hierarchy パースペクティブを開く (F4 / Fn + F4)

Call Hierarchy パースペクティブを開く (Alt + Shift + H)

現在選択されているクラス/フィールド/メソッドの呼び出し階層を Call Hierarchy パースペクティブに表示します。

指定行にジャンプ (Command + L)

メニュー

Refactor メニューを開く (Alt + Shift + T / Alt + Command + T)

Source メニューを開く (Alt + Shift + S / Alt + Command + S)

エディター編用

コメントアウト (Ctrl + / / Command + /)

現在の行を削除 (Ctrl + D / Command + D)

実行 / デバッグ

Run (Ctrl + F11 / Shift + Command + Fn + F11)

Debug (F11 / Shift + Command + Fn + F11)

参考リンク

10 Eclipse Navigation Shortcuts Every Java Programmer Should Know
“Right Click” keyboard short cut for Eclipse?

GWT Remote Loggingで出力されるログを読みやすくする

Google Web Toolkit にはJavaのLoggingインタフェースを利用したロギング機構が用意されています。

中でも強力なのはRemote Loggingが標準でサポートされていることです。
クライアントのエラーをサーバーに集められるため迅速なトラブルシューティングが可能になります。

しかし、GWTのデフォルトのコンパイルスタイル OBFUSCATED だとスタックトレースは以下のように、最も難読化されたモードのまま出力されてしまいます。
例えば、GWT2.5.0のsamplesに含まれるLogExampleを実行して、”Trigger Exception”ボタンをクリックして出力されるスタックトレースは以下のようになります。
[text]
Sat Nov 02 10:15:15 GMT+900 2013 SEVERE: Fake Null Exception Hit
java.lang.NullPointerException: null
at Unknown.Ec(StackTraceCreator.java:174)
at Unknown.jI(StackTraceCreator.java:501)
at Unknown.Rv(OneLoggerController.java:70)
at Unknown.Of(ClickEvent.java:55)
at Unknown.Gh(GwtEvent.java:76)
at Unknown.vh(HandlerManager.java:127)
at Unknown.Sr(Widget.java:129)
at Unknown.Bf(DomEvent.java:116)
at Unknown._r(UIObject.java:557)
at Unknown.ay(DOM.java:1307)
at Unknown.anonymous(DOMImplStandard.java:171)
at Unknown.Xb(Impl.java:189)
at Unknown.$b(Impl.java:242)
at Unknown.anonymous(Impl.java:70)
[/text]
これでは、なかなかエラーを追うのが大変なため、以下のように元のクラス名に変換して出力ように設定していきます。
[text]
2013/11/02 10:15:15 com.google.gwt.logging.server.RemoteLoggingServiceUtil logOnServer
SEVERE: Fake Null Exception Hit
java.lang.Throwable
at com.google.gwt.core.client.impl.StackTraceCreator$CollectorEmulated.$fillInStackTrace(StackTraceCreator.java:174)
at java.lang.NullPointerException.NullPointerException(NullPointerException.java:501)
at com.google.gwt.sample.logexample.client.OneLoggerController_MyUiBinderImpl$Widgets$2.onClick(OneLoggerController_MyUiBinderImpl.java:70)
at com.google.gwt.event.dom.client.ClickEvent.dispatch(ClickEvent.java:55)
at com.google.web.bindery.event.shared.SimpleEventBus.$doFire(SimpleEventBus.java:76)
at com.google.gwt.event.shared.HandlerManager.$fireEvent(HandlerManager.java:127)
at com.google.gwt.user.client.ui.Widget.$fireEvent(Widget.java:129)
at com.google.gwt.event.dom.client.DomEvent.fireNativeEvent(DomEvent.java:116)
at com.google.gwt.user.client.ui.Widget.onBrowserEvent(Widget.java:557)
at com.google.gwt.user.client.DOM.dispatchEvent(DOM.java:1307)
at Unknown.anonymous(DOMImplStandard.java:171)
at com.google.gwt.core.client.impl.Impl.apply(Impl.java:189)
at com.google.gwt.core.client.impl.Impl.entry0(Impl.java:242)
at Unknown.anonymous(Impl.java:70)
[/text]

1. Remote Loggingを有効にする

gwt.xmlで以下のプロパティを設定するとサーバーにログが送信されるようになります。
[xml]
<set-property name="gwt.logging.simpleRemoteHandler" value="ENABLED" />
[/xml]
LogExampleの場合は、既に設定済みですので、samples/LogExample/src/com/google/gwt/sample/logexample/LogExample.gwt.xml を確認してください。

2. コンパイル時にsymbolMapsをwarに含める

symbolMapsは、コンパイルされたJavascriptのメソッド名と実際のクラス/メソッドのマップを保持するファイルを含みます。
デフォルトでは、コンパイル時に -war に指定されたディレクトリの WEB-INF/deplay/<モジュール名>/symbolMaps ディレクトリに出力されるので、そのままwarファイルに含まれます。

3. symbolMapsを読み込むRemoteLoggingServiceを実装する

サーバーでクライアントのログを受けるためには、RemoteLoggingServiceImpl を web.xml に追加します。
samples/LogExample/war/WEB-INF/web.xml で確認できます。

いくつかのブログや掲示板では、この RemoteLoggingServiceImpl の init-param に symbolMaps のパスを渡すとスタックトレースが実際のJavaのクラス/メソッドに変換されて出力される記述されていますが RemoteLoggingServiceImp はinit-paramをハンドリングしません。

そのため、RemoteLoggingServiceImp を拡張するクラスを実装する必要があります。
Removing obfuscation from a stack trace.

LogExampleを用いて確認するために、src/com/google/gwt/sample/logexample/server/MyRemoteLoggingService.java を以下のように記述しました。
[java]
package com.google.gwt.sample.logexample.server;

import com.google.gwt.logging.server.RemoteLoggingServiceImpl;
import javax.servlet.*;
public class MyRemoteLoggingService extends RemoteLoggingServiceImpl {

@Override
public void init() throws ServletException {
super.init();
setSymbolMapsDirectory(getServletContext().getRealPath("/WEB-INF/deploy/logexample/symbolMaps"));
}

}
[/java]
web.xml のサーブレット設定も RemoteLoggingServiceImpl から MyRemoteLoggingService へ変更します。
[xml]
<servlet>
<servlet-name>remoteLoggingServlet</servlet-name>
<servlet-class>com.google.gwt.sample.logexample.server.MyRemoteLoggingService</servlet-class>
<init-param>
<param-name>symbolMaps</param-name>
<param-value>WEB-INF/deploy/logexample/symbolMaps</param-value>
</init-param>
</servlet>
[/xml]

以上を設定して実行すると、上記のJavaのクラス・メソッド名に変換されたスタックトレースが出力されるようになります。

参考:
7 Tips for Exception Handling in GWT
Using the GWT Compiler for Better Builds

MavenでGWTプロジェクトを作成/管理する

[bash]
$ mvn archetype:generate

Choose a number or apply filter (format: [groupId:]artifactId, case sensitive contains): 314: gwt-maven-plugin
Choose archetype:
1: remote -> org.codehaus.mojo:gwt-maven-plugin (Maven plugin for the Google Web Toolkit.)
Choose a number or apply filter (format: [groupId:]artifactId, case sensitive contains): : 1
Choose org.codehaus.mojo:gwt-maven-plugin version:
1: 1.1
2: 1.2
3: 2.1.0
4: 2.1.0-1
5: 2.4.0
6: 2.5.0-rc1
7: 2.5.0-rc2
8: 2.5.0
9: 2.5.1-rc1
10: 2.5.1
Choose a number: 10: 10
Downloading: http://repo1.maven.org/maven2/org/codehaus/mojo/gwt-maven-plugin/2.5.1/gwt-maven-plugin-2.5.1.jar
Downloaded: http://repo1.maven.org/maven2/org/codehaus/mojo/gwt-maven-plugin/2.5.1/gwt-maven-plugin-2.5.1.jar (181 KB at 78.2 KB/sec)
Downloading: http://repo1.maven.org/maven2/org/codehaus/mojo/gwt-maven-plugin/2.5.1/gwt-maven-plugin-2.5.1.pom
Downloaded: http://repo1.maven.org/maven2/org/codehaus/mojo/gwt-maven-plugin/2.5.1/gwt-maven-plugin-2.5.1.pom (21 KB at 44.4 KB/sec)
Define value for property ‘groupId’: : com.example
Define value for property ‘artifactId’: : HelloGWT2.5.1
Define value for property ‘version’: 1.0-SNAPSHOT: :
Define value for property ‘package’: com.example: :
Define value for property ‘module’: : helloworld
Confirm properties configuration:
groupId: com.example
artifactId: HelloGWT2.5.1
version: 1.0-SNAPSHOT
package: com.example
module: helloworld
Y: : y
[INFO] —————————————————————————-
[INFO] Using following parameters for creating project from Archetype: gwt-maven-plugin:2.5.1
[INFO] —————————————————————————-
[INFO] Parameter: groupId, Value: com.example
[INFO] Parameter: artifactId, Value: HelloGWT2.5.1
[INFO] Parameter: version, Value: 1.0-SNAPSHOT
[INFO] Parameter: package, Value: com.example
[INFO] Parameter: packageInPathFormat, Value: com/example
[INFO] Parameter: package, Value: com.example
[INFO] Parameter: version, Value: 1.0-SNAPSHOT
[INFO] Parameter: module, Value: helloworld
[INFO] Parameter: groupId, Value: com.example
[INFO] Parameter: artifactId, Value: HelloGWT2.5.1
[INFO] project created from Archetype in dir: /Users/hrendoh/workspace/HelloGWT2.5.1
[INFO] ————————————————————————
[INFO] BUILD SUCCESS
[INFO] ————————————————————————
[INFO] Total time: 1:29.365s
[INFO] Finished at: Fri Nov 01 16:48:36 JST 2013
[INFO] Final Memory: 7M/81M
[INFO] ————————————————————————
[/bash]

[bash]
$ cd HelloGWT2.5.1
$ mvn gwt:run
[/bash]
ant devmodeした場合と同じく、”GWT Development Mode”が起動します。

参考:
Compile GWT application into JavaScript

MavenでWebアプリケーションプロジェクト HelloWorld jettyプラグインで実行

Mavenは、Rubyで言うところのrakeにあたる、Javaのプロジェクト管理ツールです。
おそらくデファクトスタンダードなはずですが、antから乗り換える動機が無いためあまりちゃんと勉強したことが無かったので改めてまとめてみました。

で、一番良く使うシンプルなWebアプリプロジェクトを作成してみます。

Mavenのインストール

Macだとhomebrewとかmacportsでお手軽にインストールできます。

Mavenプロジェクトの生成

[bash]
$ mvn archetype:generate -DarchetypeArtifactId=maven-archetype-webapp

[INFO] Generating project in Interactive mode
Define value for property ‘groupId’: : com.example
Define value for property ‘artifactId’: : HelloMavenWebApp
Define value for property ‘version’: 1.0-SNAPSHOT: :
Define value for property ‘package’: com.example: :
Confirm properties configuration:
groupId: com.example
artifactId: HelloMavenWebApp
version: 1.0-SNAPSHOT
package: com.example
Y: : y
….
[INFO] ————————————————————————
[INFO] BUILD SUCCESS
[INFO] ————————————————————————
[INFO] Total time: 45.392s
[INFO] Finished at: Fri Nov 01 14:27:49 JST 2013
[INFO] Final Memory: 7M/81M
[INFO] ————————————————————————
[/bash]

Maven プロジェクトを生成するコマンドは mvn archetype:generate です。
パラメータ archetypeArtifactId に archetype(Mavenプロジェクトのテンプレート)を指定します。
archetypeを指定しない場合は、コマンドライン上で選択できますが、数が膨大なので目的のテンプレートを探すのは困難です。
今回利用した maven-archetype-webapp はMavenの公式archetype(groupIdがorg.apache.maven.archetypes)です。
Introduction to Archetypes で確認できます。

必要なプロパティは、すべてプロプントで聞かれるので簡単にプロジェクトを生成できます。

  • groupId は、Javaでいつも使っているパッケージを指定します(例:com.co-meeting)。groupId は archetype を検索する際に条件にも利用できます。
  • artifactId は、プロジェクトの名前を指定します。
  • version は、今回はデフォルトのまま、Enter。
  • package は、通常groupIdと同じになるので、Enter。

プロジェクトをビルドして実行

[bash]
$ cd HelloMavenWebApp/
$ mvn compile war:war
[/bash]
http://maven.apache.org/plugins/maven-war-plugin/usage.html

pom.xmlのbuildの下にpluginsを追加します。
[xml]
<build>
<finalName>HelloMavenWebApp</finalName>
  <plugins>
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
[/xml]

注意: 似た名前の maven-jetty-plugin は古いので Jetty7以上を使う場合は jetty-maven-plugin をしていすること

jettyプラグインを実行
[bash]
$ mvn jetty:run
[/bash]

http://localhost:8080/ にアクセスして “Hello World!” と表示されれば成功です。

Jetty9 を利用する場合は、org.eclipse.jettyのjetty-maven-pluginを利用する必要があります。

ただし、org.eclipse.jettyのプラグインはデフォルトのリポジトリには含まれていないため Maven の settings.xml に追加する必要があります。
settings.xmlについての説明は Settings Reference を参照してください。

.m2/settings.xml を以下のように記述します。
[xml]
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0
http://maven.apache.org/xsd/settings-1.0.0.xsd">
<localRepository/>
<interactiveMode/>
<usePluginRegistry/>
<offline/>
<pluginGroups>
<pluginGroup>org.eclipse.jetty</pluginGroup>
</pluginGroups>
<servers/>
<mirrors/>
<proxies/>
<profiles/>
<activeProfiles/>
</settings>
[/xml]

pom.xmlのpluginsを以下の用に書き換えます。
[xml]
<build>
<finalName>HelloMavenWebApp</finalName>
  <plugins>
<plugin>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
[/xml]
実行方法は同じです。
[bash]
$ mvn jetty:run
[/bash]

GWT (Google Web Toolkit) 2.5.0 Hello World

1. ダウンロードサイトからgwtを入手する
https://code.google.com/p/google-web-toolkit/downloads/detail?name=gwt-2.5.0.zip
2. 解凍
[bash]
$ unzip gwt-2.5.1.zip
[/bash]
3. webAppCreatorを使ってプロジェクトを生成
[bash]
$ ./webAppCreator -out ../HelloWorldGWT com.example.HelloWorldGWT
[/bash]
以下のパラメータが必須

  • -out: 出力先ディレクトリ
  • プロジェクト名 “fully-qualified” java的なパッケージ名を指定する必要があります。

4. 開発モードで動作確認
GWTはJavaでコードを記述してJavascriptにコンパイルする開発ツールですが、毎回コンパイルしながら開発しなくても良いように開発用ツールが用意されています。まずは開発ツールを利用して動作を確認します。
[bash]
$ cd ../HelloWorldGWT/
$ ant devmode
[/bash]
開発ツール”GWT Development Mode”が開くので Development Mode タブで [Launch Default Browser]をクリックするか、[Copy Clip Board]をクリックしてURLをコピーしてブラウザのアドレスバーにペーストしてテストサーバーにアクセスできます。

この内容は本家サイトで確認できます。
http://www.gwtproject.org/gettingstarted.html

5. コンパイル
次にJavascriptにコンパイルして動作させてみます。
[bash]
$ ant war
[/bash]
生成された、HelloWorldGWT.warをTomcatやJettyにデプロイします。