tokuhirom's blog

Freemarker で uriFor する

いわゆるひとつの uriFor 的なものを freemarker 用に実装してみるという。

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.List;

import freemarker.template.TemplateCollectionModel;
import freemarker.template.TemplateHashModelEx;
import freemarker.template.TemplateMethodModelEx;
import freemarker.template.TemplateModel;
import freemarker.template.TemplateModelException;
import freemarker.template.TemplateModelIterator;

/**
* {@code uriFor("/path/", {"query":"value"})}
*/
public class URIForFunction implements TemplateMethodModelEx {
    private final String encoding = "UTF-8";

    @Override
    public Object exec(final List arguments) throws TemplateModelException {
        String path = arguments.get(0).toString();
        TemplateHashModelEx params = (TemplateHashModelEx)arguments.get(1);

        StringBuilder buf = new StringBuilder();
        buf.append(path).append("?");

        try {
            TemplateCollectionModel entries = params.keys();
            long size = params.size();
            int n = 1;
            TemplateModelIterator iterator = params.keys().iterator();
            while (iterator.hasNext()) {
                TemplateModel key = iterator.next();
                buf.append(URLEncoder.encode(key.toString(), encoding))
                    .append("=")
                    .append(URLEncoder.encode(params.get(key.toString()).toString(), encoding));
                if (n != size) {
                    buf.append("&");
                }
                ++n;
            }
            return buf.toString();
        } catch (UnsupportedEncodingException e) {
            // Normally, this shouldn't happen.
            throw new RuntimeException(e);
        }
    }
}
Created: 2015-01-29 15:44:51
Updated: 2015-01-29 15:44:51

Freemarker で文字列のテンプレートを適当にレンダリングする

なんかこんな感じです。

private String render(String templateString, Object dateModel) throws IOException, TemplateException {
    final Configuration cfg = new Configuration();
    StringTemplateLoader loader = new StringTemplateLoader();
    loader.putTemplate("x", templateString);
    cfg.setTemplateLoader(loader);
    Template template = cfg.getTemplate("x");
    final StringWriter writer = new StringWriter();
    template.process(null, writer);
    return writer.toString();
}
Created: 2015-01-29 15:42:22
Updated: 2015-01-29 15:42:22

mod_jk な apache に、「自分は HTTPS を扱っている」と思い込ませる

SetEnv HTTPS on

で OK です。

HTTPS という名前を避けたい場合は

JkHTTPSIndicator HOGE

などと設定すればよい。

Created: 2015-01-27 18:09:42
Updated: 2015-01-27 18:09:42

"default" servlet はどこから来るの?

Servlet container で static contents を serve するには web.xml に default servlet を設定するといいらしいです。

<servlet-mapping>
        <servlet-name>default</servlet-name>
        <url-pattern>/static/*</url-pattern>
</servlet-mapping>

http://stackoverflow.com/questions/132052/servlet-for-serving-static-content


じゃあこの default servlet って servlet API の仕様に入っているの? というところですが、実際のところ別に標準ではないという噂を聞きました。 http://stackoverflow.com/questions/1661082/is-the-default-servlet-a-de-facto-standard

とは言え、一般的なサーブレットコンテナ実装では default コンテナが定義されているとのことで、まあ微妙なところですね!

Created: 2015-01-26 19:15:26
Updated: 2015-01-26 19:15:26

JavaMail でメール送ったらどういう挙動になるか試すやつを書いた

https://github.com/tokuhirom/javamail-checker

JavaMail でメール送る奴書いたけど、それがちゃんとその環境で送れるかとか試すのがだるいという向きのためのやつです。

fat jar で javamail でなんとなくメールを送ります。

以下のようにすると適当にメール送ってくれます。

$ java -Dmail.smtp.host=localhost -jar javamail-checker-0.0.1-SNAPSHOT.jar \
    from@example.com \
    to@example.com

それだけ。

↓このへんからコンパイル済みバイナリが取れる。 https://github.com/tokuhirom/javamail-checker/releases/tag/0.0.1-SNAPSHOT

Created: 2015-01-25 22:09:10
Updated: 2015-01-25 22:09:10

git flow を使ってみている

Java で開発するにあたって、なんだかんだ git flow とかにしたほうが説明の手間とか少なくて楽だな、とおもって git flow にしている。

Created: 2015-01-15 16:50:04
Updated: 2015-01-15 16:50:04

mprofile-python がパワーアップしていた

setup.py が設定されてちゃんとした python のパッケージになりました。pip でインストールできるようになって便利。

mpdump を直接いじって使ってね、という怠惰な実装だったのが、ちゃんと外部からコマンドライン引数で処理できるように変更されました。

という変更が @t2y さんから p-r されてきたのでマージしました。 オープンソースってすばらしい。

Created: 2015-01-12 19:02:33
Updated: 2015-01-12 19:02:33

詳解Tomcatを読んだ

  • Valve は Starlet::Plugin::* 的なもの。
  • SemaphoreValve は便利そう
  • RemoteIpValve はよさそう。
    • RemoteIpFilter は web.xml に書くことになるのでテストするときとか jetty に deploy したくなった時とかにダルい。Valve なら server.xml に書けばいいのでアプリケション側に影響がない。
  • StuckThreadDetectionValve もよさそう。
  • RewriteValve は mod_rewrite の再実装。あまり使い道なさそう。
Created: 2015-01-09 14:22:13
Updated: 2015-01-09 14:22:13

MySQL Connector/J を利用するときは cacheServerConfiguration=true を設定する

MySQL は一般に接続コストが低いことで知られており、コネクションプーリング等しなくても使えるので便利。

だが、Java 用の MySQL Driver であるところの MySQL Connector/J はデフォルトでは数個のクエリを接続時に発行しており、デフォルトのままでは無駄に負荷がかかる。

デフォルトでは以下のように4つの準備クエリが発行される! どう考えてもおかしいですよね!やばいっす!

150108  9:18:11         5 Connect     root@localhost on test
            5 Query     /* mysql-connector-java-5.1.34 ( Revision: jess.balint@oracle.com-20141014163213-wqbwpf1ok2kvo1om ) */SHOW VARIABLES WHERE Variable_name ='language' OR Variable_name = 'net_write_timeout' OR Variable_name = 'interactive_timeout' OR Variable_name = 'wait_timeout' OR Variable_name = 'character_set_client' OR Variable_name = 'character_set_connection' OR Variable_name = 'character_set' OR Variable_name = 'character_set_server' OR Variable_name = 'tx_isolation' OR Variable_name = 'transaction_isolation' OR Variable_name = 'character_set_results' OR Variable_name = 'timezone' OR Variable_name = 'time_zone' OR Variable_name = 'system_time_zone' OR Variable_name = 'lower_case_table_names' OR Variable_name = 'max_allowed_packet' OR Variable_name = 'net_buffer_length' OR Variable_name = 'sql_mode' OR Variable_name = 'query_cache_type' OR Variable_name = 'query_cache_size' OR Variable_name = 'license' OR Variable_name = 'init_connect'
            5 Query     /* mysql-connector-java-5.1.34 ( Revision: jess.balint@oracle.com-20141014163213-wqbwpf1ok2kvo1om ) */SELECT @@session.auto_increment_increment
            5 Query     SET character_set_results = NULL
            5 Query     SET autocommit=1
            5 Query     SELECT 4649
            5 Quit

とりあえず cacheServerConfiguration=true は必ず設定しておいたほうが良い。なぜならば MySQL のサーバー側の設定は基本的に変更しないし、Failover した場合に設定が変わることもないからだ(変わっていたらそれは設定ミスでしょう)。 設定するだけで2つのクエリが削減できる。

↓このへんが詳しいので見ておくとよいでしょう。

Created: 2015-01-08 09:47:22
Updated: 2015-01-08 09:47:22

homebrew で入れた MySQL 5.6 で general log を取る

デバッグ時には general log を取るようにしたら便利。 発行されたログを全部見れる。

/usr/local/Cellar/mysql/5.6.22/my.cnf あたりに以下のように追記

[mysqld]

general_log=1
general_log_file=/usr/local/var/mysql/general.log

できたら、以下のようにコマンドを打ち込んで再起動する。

$ mysql.stop
$ mysql.start

あとは以下のようにして流れるログを眺めながらコーヒーを飲めば完成となる。

$ tali -F /usr/local/var/mysql/general.log
Created: 2015-01-08 09:08:49
Updated: 2015-01-08 09:08:49