Logback-0.9.19 以降の設定記法がちょっと変わっていた
Logbackのライブラリを最新版にUpdateすると、アプリケーションの起動時にエラーが発生するようになりました。
ERROR in ch.qos.logback.core.joran.spi.Interpreter@11:13 - no applicable action for [encoding], current pattern is [[configuration][appender][encoding]]
以下、直したのでメモ。
調べてみると、Logback-0.9.19から、xmlの設定記法がちょっと変わっていました。
いままでのlayoutタグなどはencoderタグとして結果的に簡略化、そしてencodingタグはcharsetタグに変更になった模様。
というわけで、以前書いたlogback.xml を編集しなおし、
コンソールの出力には、
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <Target>System.out</Target> <encoder> <Pattern>[%-5level][%d{yyyy-MM-dd HH:mm:ss.SSS}] %class - %msg%n</Pattern> </encoder> </appender>
外部ファイルに出力したいときは、
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <FileNamePattern>logs/logFile.%d{yyyy-MM}.log</FileNamePattern> <MaxHistory>7</MaxHistory> </rollingPolicy> <encoder> <charset>UTF-8</charset> <Pattern>[%-5level][%d{yyyy-MM-dd HH:mm:ss.SSS}] %class - %msg%n</Pattern> </encoder> </appender>
とすることで、エラーを抑えることができました。
実行環境は
- logback-0.9.20
- slf4j-1.5.11
です。
任意実行のJavaプログラムでLogbackのログファイルをRollingさせる設定メモ
cronによるバッチ処理の様な任意実行のJavaプログラムでlogbackを使うときに、ログのrolling設定でハマったのでメモ。
logbackのTimeBasedRollingPolicyを使って、過去一週間の日ごとのログに分けたかったので、公式のドキュメントのExample 4.6を参考にして下記のように設定しました。
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> <Encoding>UTF-8</Encoding> <File>logs/logFile.log</File> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <FileNamePattern>logs/logFile.%d{yyyy-MM-dd}.log</FileNamePattern> <MaxHistory>7</MaxHistory> </rollingPolicy> <layout class="ch.qos.logback.classic.PatternLayout"> <Pattern>[%-5level][%d{yyyy-MM-dd HH:mm:ss}] %class - %msg%n</Pattern> </layout> </appender>
ところが実際に動かしてみると、実行日が変わっても全てlogs/logFile.logにログが書き込まれてしまい、日ごとのログファイルも作成されません。
結果的にFileタグを除去して、
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> <Encoding>UTF-8</Encoding> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <FileNamePattern>logs/logFile.%d{yyyy-MM-dd}.log</FileNamePattern> <MaxHistory>7</MaxHistory> </rollingPolicy> <layout class="ch.qos.logback.classic.PatternLayout"> <Pattern>[%-5level][%d{yyyy-MM-dd HH:mm:ss}] %class - %msg%n</Pattern> </layout> </appender>
とすると、実施日ごとに直接ログファイル(例:logFile.2009-12-22.log)を作成してくれるようになりました。
未検証ですが、サーブレットコンテナで常時動くようなシステムであればFileタグを指定していても大丈夫なのかな。
上記の設定をTomcat上で動くアプリケーションに設定すると、$CATALINA_HOME/logs の中に保存されます。
2010年4月9日の記事に、新しい設定記法についてのせました。こちら。
そうそう、実行環境は
- logback-0.9.18
- slf4j-1.5.10
でした。
b-mobileのWebアクセラレータは本当にSSLに対応していないのか?
モバイル環境としてMacBookAirでb-mobile3G(MF626)を使ってます。
でもb-mobile接続でGmailを使おうとすると、ログイン処理から先に進まなかったり、運良くメールタイトル一覧が表示されても記事が開かない…などなど、まったく使えないことがほとんど。
静的なページはスムーズに表示されていて、これがまた混乱の元でしたが、mixiや職場のシステムなど、特にログイン時のHTTPSでの通信が必須なWebサービスで同様のタイムアウトが起こっていることに気がつきました。
一方、b-mobileでは、Webアクセラレータをproxyとして提供しています。
静的なHTTPのアクセスがOKなのにHTTPSのアクセスを挟むと駄目なのは、単純にHTTPSにアクセラレータのproxyが通っていないからじゃね?
というわけで、
試してみたこと。
b-mobileのドライバとb-Accessを通常通りインストールすると、「システム環境設定」>「ネットワーク」に「ZTEUSBModem」というインターフェースが追加されます。これの「詳細」>「プロキシ」を見ると、
mao.bmobile.ne.jp:32080
というアクセラレータのproxyが、「Webプロキシ(HTTP)」にだけ設定されています。
そこでこのproxy設定を「保護されたWebプロキシ(HTTPS)」にも入力して、再度Gmailを閲覧してみると、非常にスムーズに動作するようになりました。タイムアウトが頻発していたのが信じられないぐらい(定量的な評価じゃなくてごめんなさい)。
b-mobileサイトでの情報と、とりあえずの結論
けれども実は、b-mobileのアクセラレータのQ&AにはSSLには対応していないと明記されていて、利用ガイドにもWebプロキシだけにWebアクセラレータのproxyが設定されています。
netstatで見ている限りは、HTTPSへの設定後はHTTPS通信を行っても、直接相手サーバの443ポートへのアクセスは無く、アクセラレータのproxyがちゃんと経由してくれているように見えます。
ネットワーク屋さんではないのでこの程度のテストしかできないのですが、結論としては、
といったところでしょうか。
これでFirefoxのUserAgentをiPhoneにして転送量を抑えて頑張るとか、涙ぐましい(無駄な)努力の日々ともオサラバです。
Restlet(1.2-m2)へ入門してみんとす
あるWebサービスから別個稼働しているWebサービスのデータを表示したくて、RESTで解決できないかなあということで、検証がてらRestletを勉強してみます。
(私の現状でのRESTへの知識:HTTPリクエストに対してxmlが帰ってくるから適当にパーサして使ってね!)
下準備
ひとまず環境を作ります。
FirstStepsをなぞってみる
公式サイトのFirstStepをなぞってみます。パッケージ名はrestlet.testingにしました。
HelloWorldResourceの作成
package restlet.testing; import org.restlet.resource.Get; import org.restlet.resource.ServerResource; public class HelloWorldResource extends ServerResource { @Get public String represent() { return "Hello, world."; } }
HelloWorldApplicationの作成(公式だとFirstStepsApplicationですね)
package restlet.testing; import org.restlet.Application; import org.restlet.Restlet; import org.restlet.routing.Router; public class HelloWorldApplication extends Application { @Override public Restlet createRoot() { Router router = new Router(getContext()); router.attachDefault(HelloWorldResource.class); return router; } }
web.xmlの作成
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> <display-name>Testing Rest Application</display-name> <description> This is only a test of the Restlet. </description> <context-param> <param-name>org.restlet.application</param-name> <param-value>restlet.testing.HelloWorldApplication</param-value> </context-param> <servlet> <servlet-name>RestletServlet</servlet-name> <servlet-class>org.restlet.ext.servlet.ServerServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>RestletServlet</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping> </web-app>
context.xmlの作成
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> <display-name>Testing Rest Application</display-name> <description> This is only a test of the Restlet. </description> <context-param> <param-name>org.restlet.application</param-name> <param-value>restlet.testing.HelloWorldApplication</param-value> </context-param> <servlet> <servlet-name>RestletServlet</servlet-name> <servlet-class>org.restlet.ext.servlet.ServerServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>RestletServlet</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping> </web-app>
第2回 wicket勉強会に参加できませんでした……
当日朝、ちょうど出発の準備をしていたら身内の訃報が入り、残念ながら参加できませんでした。訃報と参加できなかった事、両方の意味で無念です。
参加された方の記事を地引き網方式で巡回しましたが、とても盛況したようですね。
一緒に行く予定だった後輩達にも好評だったようで、次回こそ再び参加したいと思います。できれば学生を引き連れて。
私も前回参加させていただいて肌で感じたことですが、kk_ataka(d:id:kk_ataka:20090305) の言うとおり、IT分野を目指している学生こそ、こういう勉強会に就職前に行っておくべきだと思うんですよね(勿論、懇親会も)。
第1回 大学ポータル・デベロッパーズ・ワークショップに参加してきました
第1回 大学ポータル・デベロッパーズ・ワークショップ 『CAS3 によるシングルサインオン環境の実現』
第2回Wicket勉強会には残念ながら参加できませんでしたが、こちらには何とか参加できました。
ご存じの方も多いかと思いますが、CASというのはLDAPやRDBMSを認証源にして、手軽なシングルサインオン環境の提供を目指したJavaベースの認証サーバーです。アメリカのYale大学が先立って開発し、現在はJA-SIGが引き継いでいます。会場となった名古屋大学や熊本大学が日本の大学での先行導入事例として有名ですね。
内容に関しては特に公開の許可をいただいていないので、軽く感想程度など。
CAS 概要
CASの動作の流れを丁寧に教えていただきました。いきなり私が詰まっていた問題が氷塊。
CAS3になってから内部構造がSpring2.5+Spring Webflowになっているとのこと。Webflowで作られたアプリケーションのソースコードを読んだのは初めてだったのですが、フローチャートの考え方をそのまま流用できて便利ですね(でもXmlを見た瞬間、めんどいなあ、Wicketにしてほしいなあと思ってしまった)。
Webアプリケーションに配備する認証Clientに関しては、JA-SIGのサンプル(Yale大学版)はServletFilterを使って認証を実現しているのですが、ワークショップのサンプルではもっと基本的な、SessionにuserIdがあるかどうか見てリダイレクト先を変える形の様でした。この辺は今後、Wicketアプリケーションと組み合わせて上手く行くかを日記に書いてみたいです。
Yale大学版にはバグがあるとおっしゃっていたのですが、詳細を聞けなかったことを後悔……orz
CAS 3.x による実装、ウェブアプリケーションの CAS 化
実際にソースコードをさわって、動作の確認・認証源の変更を行いました。 またCAS同様、大学のポータル(Portlet)サーバとして注目されているuPortalとCASを連携させたりしました。
このあたりはソースコードを修正してはmavenでコンパイル・デプロイを繰り返す形で、参加者の足並みがなかなか揃いませんでしたが、設定ファイルを書き換えるだけで認証方法の変更やサーバを変更できる便利さが良くわかりました。
CAS 3 の機能拡張
時間が迫ってきていたため、OpenIDについては割愛されましたが、X.509認証のしくみと、CASと組み合わせた認証の概念の解説がありました。
懇親会にも参加させていただきました。
特に記憶に残ったのは、大学のICTシステムは業者委託からオープンソース等を使った内部開発へシフトしつつあるということと、大学でC言語を教えるべきか?という話題。この辺は長くなるので、その内、自分の考えを投稿してみようかなあ。
ワークショップ自体は、まだまだ参加大学の数も少なかったですが、今後、大学でいかに内部開発を可能にするかという視点から、いろいろ検討する場として大成できるんじゃないかなあと思いました。
次回は一年後かな……ということで。大変楽しみです。
年末頃にwickeXtを試してみた 今さらまとめ(2)
ひとまずWickeXtのQuickStart(Modal)が無事に動いたので、今度はAccordionを試してみました。
確か紅白のPerfumeを見ながら、多分Modalと同じなんだろうなーと思いつつ、安易に下記の様な感じでコードを書きました。
Step003.html
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org/" lang="ja" xml:lang="ja"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> </head> <body> <h3>アコーディオンに挑戦してみる(1)</h3> <ul class="accordion" wicket:id="accordion"> <li> <a class="head">title1</a> <div>message1</div> </li> <li> <a class="head">title2</a> <div>message2</div> </li> <li> <a class="head">title3</a> <div><a wicket:id="backHome">戻る</a></div> </li> </ul> </body> </html>
Step003.java
package wickext.testing.view; import org.objetdirect.wickext.ui.accordion.Accordion; public class Step003 extends WebPage { public Step003() { Accordion accordion = new Accordion("accordion"); // デフォルトのヘッダタグは a だが、すべての a が反応してしまうので、class属性を敢えて指定する accordion.setHeader("a.head"); accordion.add(homePageLink("backHome")); this.add(accordion); } }
WebApplicationクラスは割愛します。
これで無事Accordionリストがブラウザに表示されました。なまら簡単。JQueryってJavaScriptわかんないとキツいんじゃね?とか喰わず嫌いしてた自分がアホみたいです。
ハマったポイントとしては、Accordionの中に違うページへのリンク等を作りたい時。
コメントアウトにも書いていますが、たとえばHTMLを
<li> <a>title3</a> <div><a wicket:id="backHome">戻る</a></div> </li>
としてclass属性を外して、またソースコード上でAccordion#setHeader()でヘッダの指定("タグ.class属性")を行わないと、LinkComponentをAccordionComponentへaddしても、全てAccordion制御用のリンクになってしまって画面遷移しません。
……多分JQuery的には常識なんでしょうけれども。orz