こちらのサンプルプログラムは Java 9 以降では動作しません。
Garoon と Google Calendar とを連携させたい場合は、株式会社ノベルワークスのカレンダー連携ソリューション ガル助(有償)の利用をご検討ください。
本サンプルプログラムとの大きな違いは次のとおりです。
・Google Calendar だけでなく、Office 365 とも連携が可能
・双方向連携が可能
・複数ユーザーのスケジュール同期が可能
(著者:サイボウズ 竹内 能彦)
はじめに
Googleカレンダー使っていますか?自分の予定と他の方の予定を並べて表示したり、予定を共有したり出来てとっても便利ですよね。
そこにGaroonの予定を並べて見られたらもっと便利になると思いませんか?
そんな思い付きからGaroonの予定をGoogleカレンダーに表示する連携プログラムを作成しました。事前準備が少し大変ですが、皆さん是非使ってみてください。
概要
連携プログラムは以下の処理をコマンドラインから実行できるサンプルプログラムです。
- Garoonに登録された予定をGoogleカレンダーに登録
- Garoonで更新された予定をGoogleカレンダーに反映
- Garoonから削除された予定をGoogleカレンダーから削除
Googleカレンダーに登録する情報はGaroonの予定の「開始日時」、「終了日時」、「施設」、「メモ」、「コメント」、「参加者」です。
動作環境
- プログラム実行用端末(Java8が動作し、Garoon、Googleカレンダーにネットワーク接続できること)
2018年3月現在、Java9では動作しないことを確認しています。 - Garoon on cybozu、パッケージ版 サイボウズ ガルーン3.0.0以降
- Googleカレンダー
Garoon on cybozu、Googleカレンダーは2018年2月版で確認しています。
事前準備
実行するには連携プログラムの設定だけでなく、GoogleアカウントやGoogleカレンダーの設定が必要になります。
また、GoogleアカウントやGoogleカレンダーの設定内容を連携プログラムの設定に利用するため、メモが必要な項目はその都度注釈を入れてあります。
※現在のGGsyncはOAuth2.0にも対応していますが、本ページではサービスアカウントキー認証を利用します。
1.Googleアカウント作成
下記URLから、Googleアカウントを作成します。Googleアカウントを取得済みの方はログインしてください。
https://accounts.google.com/SignUp
2.Google APIの利用設定
下記URLから、プロジェクトを作成します。
https://console.developers.google.com/project
プロジェクト名には適当な値を入力してください。
プロジェクトの作成完了後、Google Calendar APIを検索し、
Google Calendar APIを有効にします。
認証情報を作成します。
下記画像の通りの内容を選択し、「必要な認証情報」をクリックします。
サービスアカウント名には適当な値を入力し、キーのタイプはP12を選択します。
役割なしで作成します。
自動ダウンロードされたP12キー(以下、秘密鍵(拡張子がp12))は以降の手順で利用しますので任意のフォルダに保存します。
次にサービスアカウント IDを確認します。
画面右の「サービスアカウントの管理」をクリックし、
表示されたサービスアカウント IDをメモします。(以降の手順で利用します)
3.Googleカレンダーの作成
下記URLから、Garoonのスケジュールを連携させるGoogleカレンダーを作成します。
https://www.google.com/calendar
カレンダーの作成完了後、Googleカレンダー設定の「このカレンダーを共有」タブを開きます。先ほどのメールアドレスに予定の変更権限を付与し、保存します。
Googleカレンダー設定の「カレンダー情報」タブを開き、カレンダーIDを確認します。カレンダーIDは以降の手順で利用しますのでメモしてください。
4.連携プログラムの設定
プログラム実行用端末に連携プログラムを動作させるフォルダを作成します。本設定では例として「C:/GGsync」を利用します。
秘密鍵を「C:/GGsync」に移動します。
実行ファイルと設定ファイルをダウンロードしてください。ソースはGitHubで管理しています。(外部サイトが開きます)
実行ファイル「GGsync.jar」と設定ファイル「GGsync.properties」を「C:/GGsync」に移動します。
設定ファイル「GGsync.properties」をテキストエディタで開き、コメントに従い設定します。
Googleカレンダーに登録する予定の色は1から11までの数値を指定できます。下記の色を参考に選択してください。
各カラーIDのカラーコードはこちらのコメントから確認できます。
(tomomo85さん 情報ありがとうございます)
実行手順
プログラム実行用端末でコマンドプロンプトを起動し、以下のコマンドを入力します。
> java -jar C:/GGsync/GGsync.jar C:/GGsync
コマンドの形式は「 java -jar 実行ファイルのパス 設定ファイルが存在するフォルダ」です。
「The sync completed.」と表示されればスケジュール連携に成功しています。
実行結果は設定ファイルが存在するフォルダ配下のGGsync.db(例ではC:/GGsync/GGsync.db)に保存します。GGsync.dbは次回実行時の差分反映に利用します。
プロキシ経由の実行
プロキシを経由する必要がある場合は下記のオプションを追加して実行してください。
> java -Dhttp.proxyHost=ホスト名 -Dhttp.proxyPort=ポート番号 -Dhttps.proxyHost=ホスト名 -Dhttps.proxyPort=ポート番号 -jar C:/GGsync/GGsync.jar C:/GGsync
オプションの詳細はこちら(Oracle社のドキュメントページが開きます)
セキュアアクセス利用時の実行
セキュアアクセスを利用する必要がある場合は、クライアント証明書をGGsync.jarと同じディレクトリに保存し、下記のオプションを追加して実行してください。
> java -Djavax.net.ssl.keyStore=xxxx.pfx -Djavax.net.ssl.keyStorePassword=xxxx -Djavax.net.ssl.keyStoreType=PKCS12 -jar GGsync.jar .
実行例
下記がGaroonのスケジュール、実行結果、予定が反映されたGoogleカレンダーの例になります。
・Garoonのスケジュール
・連携プログラムの実行結果
・Googleカレンダー(プライベートな予定と並べて表示)
Garoonの予定の「メモ」、「コメント」はGoogleカレンダーの「説明」にまとめて登録します。
Garoonの予定が変更された場合は、Googleカレンダーの予定を削除してから再登録します。
下記が変更時の実行例になります。
Garoonの予定が削除された場合は、Googleカレンダーの予定を削除します。
下記が削除時の実行例になります。
定期実行
タスクスケジューラなどを利用することで、定期的にGaroonの予定をGoogleカレンダーに反映できます。
是非試してみてください。
連携プログラムの更新履歴
2015/3/30 繰り返し予定が正常に登録されない不具合を改修しました。
2015/4/24 終了時間未指定の予定がエラーになる不具合を改修しました。
2015/6/18 連携失敗時に詳細なエラーを出力するように修正しました。
2015/9/16 日本語文字のアカウント名に対応しました。
2016/1/14 Googleカレンダーに「参加者」を登録する機能を追加しました。
2016/3/24 ソースコードをGitHubに移しました。
2017/3/21 セキュアアクセス利用時の実行オプションを追記しました。
2017/9/21 ソースコードにライセンス表記を追加しました。
Garoonの予定参加者をGoogleカレンダーの「説明」に追加するよう改修しました。
既にご利用中の方は以下の手順で反映できます。
1.アーカイブを再ダウンロードして、GGsync.jarを上書き更新
2.GGsync.propertiesに以下を追記し、値を変更
# 表示する参加者数の上限(0以上を指定、0は参加者を表示しない)
garoon.member.limit=0
> Yoshimura Takahiro様
大変遅くなりましたが、対応しましたのでもし良ければご確認ください。
> Jun Morimoto様
ご指摘ありがとうございます。
今回の更新のタイミングでsqlite-jdbcのバージョンを更新しました。
> manabubu様
コメントも重要な情報であることが多いため、現時点で対応する予定はありません。 申し訳ありません。
> 今回の更新のタイミングでsqlite-jdbcのバージョンを更新しました。
ありがとうございます! このバージョン (grn3-api-schedule_arc-1.0.5.tar.gz) で無事に運用できています。
以下、3点ご相談です。本当はソースコードを追ってpatchとして提示したいところですが、取り急ぎ意見表明まで…
1) com.google.api.client.googleapis.jsonの例外の扱いを緩和
----------------------------------------------------------------
以下のログを出してGGsyncが停止する状況に遭遇しました。
uniqueな文字列は適宜潰しています。
想像するに、ガルーンからGoogle Calenderに同期済みで、その後ガルーンから削除された予定をGoogle Calenderから削除しようとし、その予定がGoogle Calendarに見当たらなかった、ということなのかなと思いました。
(この問題自体は、GGsync.dbを一旦削除し同期しなおして回避しました。当然重複する予定がGoogle Calendarに大量にできてしまいましたがここは仕方ないです)
上の想定で正しければ、例外でGGsync動作が止まってしまうのは切ないので、
必要ならwarningは出しつつ、動作継続する挙動になっていると嬉しいなと思います。
INFO 11:44:55 The sync beginning with debug mode.
DEBUG 11:44:55 ?????????????????: 000000000000-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx@developer.gserviceaccount.com
DEBUG 11:44:55 ??????????P12???????????: GGSync-xxxxxxxxxxxx.p12
DEBUG 11:44:55 ?????????ID: xxxxxxxxxxxxxxxxxxxxxxxxxx@group.calendar.google.com
DEBUG 11:44:55 ????????????????????: 6
DEBUG 11:44:55 ????????????????????: 8
DEBUG 11:44:55 ?????URL: https://xxxxxxx.cybozu.com/g/
DEBUG 11:44:55 ??????????: xxxxxxxxxxxx
DEBUG 11:44:55 SYNC???????: Sun Jan 31 11:44:55 JST 2016
DEBUG 11:44:55 SYNC???????: Sat Aug 20 11:44:55 JST 2016
DEBUG 11:45:02 [DEL] for updated garoon schedule. GaroonId:0000000 GoogleId:xxxxxxxxxxxxxxxxxxxxxxxxxx Title:??: ??????????????????????
DEBUG 11:45:04 [ADD] GaroonId:0000000 Title:??: ??????????????????????
DEBUG 11:45:05 [DEL for deleted garoon schedule] GoogleId: xxxxxxxxxxxxxxxxxxxxxxxxxx
ERROR 11:45:05 404 Not Found
{
"code" : 404,
"errors" : [ {
"domain" : "global",
"message" : "Not Found",
"reason" : "notFound"
} ],
"message" : "Not Found"
}
com.google.api.client.googleapis.json.GoogleJsonResponseException: 404 Not Found
2) 終日予定の扱いを変更
----------------------------------------------------------------
ガルーンの期間予定は、Google Calendarへは
「YYYYMMDD 00:00からYYYYMMDD 00:00への通常予定」
として作成されると思います。VCALENDERで表現すると以下のように。
BEGIN:VEVENT
SUMMARY: sample
DTSTART:20160204T150000Z
DTEND:20160205T150000Z
DTSTAMP:20160202T031624Z
DESCRIPTION: foo bar..
END:VEVENT
これを、以下のように、Google Calendar / VCALENDER的にも終日予定として同期するように改修するのはいかがでしょうか。
BEGIN:VEVENT
SUMMARY: sample
DTSTART;VALUE=DATE:20160205
DTEND;VALUE=DATE:20160206
DTSTAMP:20160202T031624Z
DESCRIPTION: foo bar..
END:VEVENT
ガルーンの期間予定は「終日予定の集合」だと思います。ですのでGoogle Calendar / VCALENDERとしてもより正しいデータ同期になると思います。
また、OS XのiCalをGoogle Calendarで同期している場合、前者だと、24時間が塗りつぶされた巨大な箱に見えてしまいます。後者だと終日予定の領域に表示されます。
3) github展開
----------------------------------------------------------------
GGsyncは素晴らしいユーティリティで、ソースも公開され、更新も問答もよく行われています。
たとえば、サポートの場をgithubのリポジトリとissueに展開するのはいかがでしょう?
(展開の場がcybozu.com developer networkから外に移動してしまうこととのメリデメではあると思いますが…)
以上、ソースコードを追わず、まずは要望だけ書いてしまってすみません。
取り急ぎコメントまで。よろしくです!
> 1) com.google.api.client.googleapis.jsonの例外の扱いを緩和
これはとりあえず以下のパッチで回避できてます。そりゃそうだろ… って感じですみません ^^
https://gist.github.com/mrmt/847090cbae55046c299d/revisions
相当いい機能ですね!早速利用させていただいています。
ただ1点質問させてください。予定の色を変更できるとありますが、GGsync.propertiesの中に相当するプロパティが見当たりませんでした。
現状デフォルトではすべて黄色で登録されます。変更する方法を教えていただけますでしょうか。
> Kenta Fujiwaraさん
GGsync.properties に
google.calendar.normal.color=6
google.calendar.banner.color=8
みたいに書けばOKです。
GitHubに公開しました。(時間がかかってしまい申し訳ありません)
https://github.com/cybozu/garoon-google
こちらの記事は後ほど修正します。
> Jun Morimoto様
今回はご提案ありがとうございました。
↑のコメントでご指摘いただいたNo1については取り込み済みです。
竹内様
今まで問題無く使用出来ていましたが、本日下記のエラーがでるようになってしまいました。
ERROR 2016/04/25 21:12:23(GGsync:main:429) For input string: ""
java.lang.NumberFormatException: For input string: ""
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.lang.Integer.parseInt(Integer.java:592)
at java.lang.Integer.valueOf(Integer.java:766)
at com.cybozu.garoon3.schedule.ScheduleUtil.getFollowList(ScheduleUtil.java:313)
at com.cybozu.garoon3.schedule.ScheduleUtil.getEventList(ScheduleUtil.java:141)
at com.cybozu.GGsync.main(GGsync.java:161)
ガルーンで登録された、何か特殊なスケジュールが悪さをしているのでしょうか。
竹内様
上記、原因が分かりましたのでお知らせしておきます。
該当のユーザは、ガルーン上から削除されたユーザでした。
つまり、以前同期したスケジュールに参加しているユーザが、ガルーンから削除され、UserIDが取得出来ない場合に発生するようです。
こんにちは。GaroonとGoogleカレンダーを同期させたいと思いこちらのページにたどり着きました。
設定をして動作させましたが、エラーとなりました。
下記エラーが表示されましたので、BASIC認証失敗エラーが原因のようです。
----
情報: No credentials available for BASIC 'xxxxxxxx.cybozu.com'@xxxxxxxx.cybozu.com:443
----
同期したいGaroonはBASIC認証を施してあります。
配布いただいているプログラムおよび設定ファイルはBASIC認証に対応していますか?
もし対応していたら、BASIC認証のID/PWを設定する方法をご教示ください。
ご参考までにエラー全文を以下に記します。
お手数ですがよろしくお願いいたします。
5 26, 2016 10:42:38 午前 org.apache.commons.httpclient.auth.AuthChallengeProcess
or selectAuthScheme
情報: basic authentication scheme selected
5 26, 2016 10:42:38 午前 org.apache.commons.httpclient.HttpMethodDirector proces
sWWWAuthChallenge
情報: No credentials available for BASIC 'xxxxxxxx.cybozu.com'@xxxxxxxx.cybozu.com:443
5 26, 2016 10:42:38 午前 org.apache.axis2.transport.http.HTTPSender sendViaPost
情報: Unable to sendViaPost to url[https://xxxxxxxx.cybozu.com/g//cbpapi/ba
se/api.csp]
org.apache.axis2.AxisFault: Transport error: 401 Error: Unauthorized
at org.apache.axis2.transport.http.HTTPSender.handleResponse(HTTPSender.
java:310)
at org.apache.axis2.transport.http.HTTPSender.sendViaPost(HTTPSender.jav
a:194)
at org.apache.axis2.transport.http.HTTPSender.send(HTTPSender.java:75)
at org.apache.axis2.transport.http.CommonsHTTPTransportSender.writeMessa
geWithCommons(CommonsHTTPTransportSender.java:396)
at org.apache.axis2.transport.http.CommonsHTTPTransportSender.invoke(Com
monsHTTPTransportSender.java:223)
at org.apache.axis2.engine.AxisEngine.send(AxisEngine.java:443)
at org.apache.axis2.description.OutInAxisOperationClient.send(OutInAxisO
peration.java:406)
at org.apache.axis2.description.OutInAxisOperationClient.executeImpl(Out
InAxisOperation.java:229)
at org.apache.axis2.client.OperationClient.execute(OperationClient.java:
165)
at org.apache.axis2.client.ServiceClient.sendReceive(ServiceClient.java:
555)
at org.apache.axis2.client.ServiceClient.sendReceive(ServiceClient.java:
531)
at com.cybozu.garoon3.common.CBServiceClient.sendReceive(CBServiceClient
.java:162)
at com.cybozu.GGsync.main(GGsync.java:149)
ERROR 10:42:38 Transport error: 401 Error: Unauthorized
org.apache.axis2.AxisFault: Transport error: 401 Error: Unauthorized
at org.apache.axis2.transport.http.HTTPSender.handleResponse(HTTPSender.
java:310)
本サンプルをご利用中の皆さん
下記でアナウンスさせていただきました通り、12月の定期メンテナンスでクラウド版GaroonのAPIが更新される予定です。
https://cybozudev.zendesk.com/hc/ja/articles/212164906
スケジュールの公開先機能を利用している場合、現在利用いただいているアーカイブでは動作しなくなります。
12月版に対応したアーカイブを本文に添付していますので、GGsync.jarをダウンロードして上書き保存してください。
・クラウド版Garoonの場合
APIバージョンに合わせて動作を変更するようにしていますので、12月前に更新しても問題ありません。
全てのバージョンで確認しているわけではありませんのでエラーが発生するようでしたら教えてください。
・オンプレ版Garoonの場合
急ぎ対応する必要はありませんがご認識ください。
竹内様
こんにちわ。
>12月版に対応したアーカイブを本文に添付していますので、GGsync.jarをダウンロードして上書き保存してください。
システム上添付できないようで、本文に添付がないようです。
GITHUBのソースも古いように見受けたので、更新いただくことは可能でしょうか?
Akio Harada様
お久しぶりですー。下記からダウンロード可能かお試しください。
https://cybozudev.zendesk.com/hc/article_attachments/210061126/GGsync.jar
※わかりづらい案内で申し訳ないのですが、「4.連携プログラムの設定」にダウンロードリンクがあります
>定期実行
>タスクスケジューラなどを利用することで、定期的にGaroonの予定をGoogleカレンダーに反映できます。
>是非試してみてください。
上記のように記載がありますが、どのくらいの頻度で同期が可能でしょうか?
サイボウズ側に予定を入力した後、Googleカレンダーへ表示する時間のラグを極力無くしたい思っています。
Takafumi Nakabaruさん
プログラムが重複起動しなければ問題ありません。
ただ、1回の実行にかかる時間は期間中の対象スケジュールの数やCPU、ネットワークの性能に依存します。
なので徐々に短くしていただければと思います。
ちなみに私は15分間隔で実行しています。
初めてコメントさせていただきます。
かねてよりGGSyncを使わせていただいておりまして、大変重宝しておりました。
ただここ最近以下エラーが出て同期ができなくなっております。
---
ERROR 11:28:58 For input string: ""
java.lang.NumberFormatException: For input string: ""
at java.lang.NumberFormatException.forInputString(Unknown Source)
---
こちらフォーラムで検索しましたところ、アカウントの削除により同期できなくなっているとのコメントがございましたが、ガルーンのアカウントは存在しますので別の原因かと思います。
こちら何か原因わかりますでしょうか?
utaroさん
下記2点を試してください。
・最新のGGsync.jarを利用する
・GGsync.propertiesのexecution.levelを1にしてエラー出力を貼り付けてください(恐れ入りますが、修正をお約束できるわけではありません)
竹内様
最新版に差し替えましたところ問題なく動作いたしました。ありがとうございました。
お疲れ様です。
GGsyncは、Garoonではなく、「サイボウズ Office (Version 10.5.0)」でも動作するものでしょうか。
お疲れ様です。
サイボウズ Officeでは動作しません。
こんにちは、いつもGGSYNCを便利に使わせて頂いています。
先週までは特に問題なかったのですが、今日から突然次のようなエラーが連続して
発生しています。
何が問題でしょうか?
INFO 2017/02/27 18:00:08(GGsync:main:77) The sync beginning with normal mode.
ERROR 2017/02/27 18:00:15(GGsync:main:443) ログインできません。
org.apache.axis2.AxisFault: ログインできません。
at org.apache.axis2.util.Utils.getInboundFaultFromMessageContext(Utils.java:531)
at org.apache.axis2.description.OutInAxisOperationClient.handleResponse(OutInAxisOperation.java:375)
at org.apache.axis2.description.OutInAxisOperationClient.send(OutInAxisOperation.java:421)
at org.apache.axis2.description.OutInAxisOperationClient.executeImpl(OutInAxisOperation.java:229)
at org.apache.axis2.client.OperationClient.execute(OperationClient.java:165)
at org.apache.axis2.client.ServiceClient.sendReceive(ServiceClient.java:555)
at org.apache.axis2.client.ServiceClient.sendReceive(ServiceClient.java:531)
at com.cybozu.garoon3.common.CBServiceClient.sendReceive(CBServiceClient.java:172)
at com.cybozu.GGsync.main(GGsync.java:162)
おはようございます。
アカウントとパスワードが合っているか確認お願いします。
竹内様
申し訳ありません。パスワードの定期更新時期で変更しましたが、Ggsync.Propertiesの方を
更新し忘れていました。
更新したところ、正常にシンクされました。
こんにちは、お世話になります。
GGsyncを見つけて試してみました。
しかし、I/O exceptionでエラーになりました。
C:\WINDOWS\system32>java -jar C:/GGsync/GGsync.jar C:/GGsync
INFO 10:46:22 The sync beginning with normal mode.
3 21, 2017 10:46:45 午前 org.apache.commons.httpclient.HttpMethodDirector executeWithRetry
情報: I/O exception (java.net.ConnectException) caught when processing request:Connection timed out: connect
以下のようなメッセージも出ていました。
3 21, 2017 10:47:48 午前 org.apache.axis2.transport.http.HTTPSender sendViaPost
情報: Unable to sendViaPost to url[http://group.tsuru-gakuen.ac.jp/cgi-bin/cbgrn/grn.cgi/cbpapi/base/api]
java.net.ConnectException: Connection timed out: connect
考えられる原因や切り分けの方法などアドバイスいただけますか。
よろしくお願いします。
AIさん
GGsyncを設置している端末からガルーンサーバーへの通信に問題がありそうです。
ネットワーク設定の確認をお願いします。
プロキシを利用している場合は本文中の「プロキシ経由の実行」を参考にしてください。
竹内さま
ありがとうございます。調べてみます。
Proxyはなく、同じPCからGaroon、Google Calenderへのログインは
どちらも問題なくできます。APIを使う場合、特殊なポートを開ける
ような対応が必要になりますか?
AIさま
ポートはHTTPとHTTPSが空いていれば問題ありません。
あとは2つ目のエラーメッセージに記載されたURLの「http://・・・/grn.cgi」がガルーンのURLと合っているかですね。
合っていなければGGsync.propertiesの編集をお願いします。
合っていれば、お力になれることはなさそうです・・・
竹内さま
ありがとうございました。
URLを見直して修正したら解決しCompleteしました。
(...cgi-bin/cbgrn/grn.cgiの部分)
助かりました。本件Closedとさせていただきます。
またよろしくお願いします。