Googleカレンダーで書込権限のあるカレンダーをその他のカレンダーに追加する
会社でGoogleカレンダーを使い始めてから一つずっと気になっていたのが、他人のカレンダーがマイカレンダーに追加されて、Macのカレンダーアプリで予定承認の通知が表示されてうざいということでした。
Googleカレンダーの仕様として、書込権限のあるカレンダーを追加するとマイカレンダーのところに追加されます。
そして、マイカレンダーにあるカレンダーはMacのカレンダーアプリでは問答無用で表示されます。
今回、Googleカレンダーにて以下の儀式を行うことで、書込権限のあるカレンダーをその他のカレンダーに追加できることを発見しました。
- Googleカレンダーで対象のカレンダーを追加する(マイカレンダーに追加される)
- MacのカレンダーアプリのDelegateで対象のカレンダーを選択する
- Googleカレンダーで対象のカレンダーを削除する
- Macのカレンダーアプリでカレンダーを更新する
以上の手順は2015/1/29時点のGoogleカレンダーとMacにて動作が確認されております。
Spring Roo の database コマンドでスキーマが見つからないと言われる
database.propertiesに
database.url = jdbc:postgresql://localhost:5432/hoge
と設定されているとき
roo> database reverse engineer --schema hoge --package ~.entity
とか
roo> database introspect --schema hoge
とかコマンドを打っても
Schema(s) 'hoge' do not exist or does not have any tables. Note that the schema names of some databases are case-sensitive
などと言われてしまう。
--schema
オプションには public
と指定するらしい。これは分かりづらい...
relation "hibernate_sequence" does not exist
PostgreSQL + Hibernate JPA で relation "hibernate_sequence" does not exist ってエラーが出た。
@GeneratedValue(strategy = GenerationType.AUTO)
これを
@GeneratedValue(strategy = GenerationType.IDENTITY)
こっちにしたら直った。
Spring MVC で独自バリデーション
組込のバリデーション
Spring MVC では JSR-303 のバリデーションが使える。
@NotNull @Size(min=1, max=50) @Pattern(regexp = "[a-zA-Z-_.]+@[a-zA-Z-\\.]+")
とかのバリデーションをBeanのフィールドに宣言して、アクションのメソッドで
public String save(Model model, @Valid @ModelAttribute("form") HogeForm form, BindingResult bindingResult) { if (bindingResult.hasErrors()) { model.addAttribute("form", form); return "hoge/edit"; }
こんな感じにエラー分岐すれば、form:errorsタグでエラーが表示できる。
<form:errors path="email" cssClass="text-error" />
独自のバリデーション
標準のバリデーションで足りない分をどうすすか。
最初は org.springframework.validation.Validator を実装して、アクションの頭で
ValidationUtils.invokeValidator(hogeValidator, form, bindingResult);
とかやってみたけど、これはきれいじゃない。
調べたら、独自のアノテーションを定義できるらしい。
以下のように ConstraintValidator と、ペアになるアノテーションをセットで定義してやればOK
/** * JSR-303 Validation Annotation for List empty check */ @Target({ElementType.METHOD, ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) @Constraint(validatedBy=ListNotEmpty.ListNotEmptyValidator.class) public @interface ListNotEmpty { public String message() default "{ListNotEmpty}"; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; /** * Validator */ public static class ListNotEmptyValidator implements ConstraintValidator<ListNotEmpty, List<?>> { @Override public void initialize(ListNotEmpty annotation) { } @Override public boolean isValid(List<?> target, ConstraintValidatorContext context) { if (target == null || target.size() == 0) { return false; } return true; } } }
複数フィールドをチェックする必要がある場合はクラスをバリデーションの対象にすればOK
/** * JSR-303 Validation Annotation for Password confirmation. * Target bean should implement PasswordConfirmation.PasswordConfirmable. * (No need to put PasswordConfirmation annotation) */ @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Constraint(validatedBy=PasswordConfirmation.PasswordConfirmationValidator.class) public @interface PasswordConfirmation { public String message() default "{PasswordConfirmation}"; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; /** * Interface for password confirmation */ @PasswordConfirmation public interface PasswordConfirmable { public String getPassword(); public String getPasswordConfirmation(); } /** * Validator */ public class PasswordConfirmationValidator implements ConstraintValidator<PasswordConfirmation, PasswordConfirmable> { @Override public void initialize(PasswordConfirmation annotation) { } @Override public boolean isValid(PasswordConfirmable bean, ConstraintValidatorContext context) { if (bean.getPassword() != null && !bean.getPassword().equals(bean.getPasswordConfirmation())) { context.disableDefaultConstraintViolation(); context.buildConstraintViolationWithTemplate(context.getDefaultConstraintMessageTemplate()) .addNode("passwordConfirmation") .addConstraintViolation(); return false; } return true; } } }
AJDT configurator for m2e
Aspect J のプロジェクトをEclipseで扱ったら、Plugin execution not covered by lifecycle configuration
とか表示されてコンパイルが止まってしまう問題に遭遇。
stackoverflowとかを徘徊して、SPRINGSOURCE BLOGにあるUPGRADING MAVEN INTEGRATION FOR SPRINGSOURCE TOOL SUITE 2.8.0という記事のUh oh…my projects no longer build
という項目がそれっぽいかなぁと思ったのだが、記事の手順通りにconnectorを探してみたものの、それらしきものが全く見当たらない。
その後質問をいろいろ変えてGoogle先生に問い合わせたところ、aspectj-users mailing list の過去ログからAJDT configurator for m2eというスレッドを見つけ、Eclipse の Install New Software に http://dist.springsource.org/release/AJDT/configurator/ を追加して、AJDT configurator for m2e を入れたところ、ようやく解決した。
ネット断線
起床
4/24、いつもよりかなり早く起きた。週末のんびりしたおかげだろうか。
二度寝した後シャワーを浴びて、ホテルの朝食を摂った。
朝食の場所にはいつもだいたい同じスタッフがいる。
今日は少し暇だったからかこっちに話しかけてきてくれた。
歌が大好きで(だいたいのフィリピン人は歌が好きみたいだ)、日本の曲も一曲携帯に入っているという。
尾崎の「最後の言い訳」だった。フィリピンのほとんどの人がこれを知っているという。
気になってネットで調べてみたら、どうやら本当のことらしい。タガログ語でカバーされたことがあるのだとか。
断線
事務所に赴き仕事をしている、と、夕方に少し近づいた頃ネットが断線した。
ネットがなくてもできるようなプロジェクトの打ち合わせをやった。
何故かアルファベット書くのうまいですねって褒められた。遠回しな意味でなければ良いのだが。
打ち合わせ後も断線したままだったので、Perlを最近始めたというフィリピン人の若者に「リファレンスにblessするとオブジェクトになるんだ、祝福だよ、祝福されるんだ!」と熱っぽく語ってみた。
たぶん納得してくれたと思う。
結局帰る時間になっても復旧しなかった。
夕飯
夕飯はADOBOというフィリピンの煮込み料理を食べた。日本人に違和感のない味だと思う。おいしい。
食事後は日本語やタガログ語についての話をしていた。
何気なく話している言葉でも、振り返ってみるとなかなか興味深い。