Posts

remoteCommand in Composite

JSFにはcompositeというカスタムコンポーネントを作るための仕組みがあります。 PrimeFaces-6.0にはManagedBeanのメソッドを呼び出すためのremoteCommandというコンポーネントがあります。 この二つを使ってカスタムコンポーネントを作ったところ、ManagedBeanのメソッドが呼ばれないという問題が発生しました。

Read the rest of this entry

FreeMarkerでinterpolation部分をそのまま出力

FreeMarker-2.3.23でinterpolation部分をそのまま出力したい。

ただし、テンプレート文字列部分はユーザが自由に入力ができて、さらに、それがFreeMarkerのテンプレートだとは認識していない場合を想定。 つまり、ユーザが${hello}と入力したら、出力結果は${hello}となって欲しい。 調べてみると、下記のようにinterpolation部分を${r"..."}で括ればそのまま出力されるみたい。

TEMPLATE:

${r"${hello}"}

OUTPUT:

${hello}

ということは、ユーザの入力した文字列からinterpolation部分を抽出して、${r"..."}で括るように置換してあげればよさそうだけど、 ユーザが${helloとしか入力しない場合に置換できないし、interpolation部分だけでなく、 <#if>などの制御タグもそのまま出力しなければならないので、この方法はあまり現実的ではなさそう。 で、FreeMarkerのマニュアルを眺めてみると、noparseという項があってそれをみたら「あ、これだ!」となった。 下記のように書くとそのまま出力される。

TEMPLATE:

<#noparse>
  <#if greet>
    ${hello}
  </#if>
</#noparse>

OUTPUT:

<#if greet>
  ${hello}
</#if>

これならユーザが入力した部分を<#noparse>で括ってしまえばいいだけなので簡単。

参考サイト

java.sql.Timestamp の振る舞い

Java6 と Java8 で振る舞いが変わっていたのでメモ。

Java6 では下記コードがエラーにならず結果が出力されます。

System.out.println(java.sql.Timestamp.valueOf("2016-13-01")); // 2017-01-01

ところが Java8 だと下記のエラーが発生します。

Exception in thread "main" java.lang.IllegalArgumentException: Timestamp format must be yyyy-mm-dd hh:mm:ss[.fffffffff]
	at java.sql.Timestamp.valueOf(Timestamp.java:204)

もちろん存在しない日付、例えば 2016-12-32 などを指定した場合にもエラーとなります。 Java6 から Java7 になる際に java.sql.Timestamp に対してかなりの数のバグフィックスが行われたようで、 おそらくその修正のどこかで振る舞いが変わったのだと思います。

IntelliJ IDEAからDocker上のWildFlyでデバッグする

IntelliJ IDEAからDocker上のWildFlyコンテナにアプリケーションをデプロイし、 デバッグモードで起動することでステップ実行ができる環境を作ることが今回の目的です。 Docker上にコンテナを起動できる環境はできている前提になります。

環境

  • OS: Mac OSX 10.11.3
  • Java: Java(TM) SE Runtime Environment (build 1.8.0_60-b27)
  • メモリ: 16GB
  • Docker version 1.9.1

アプリの準備

どんなアプリでも良いのですが最終的な生成物はwarファイルにします。 今回はMavenプロジェクトで下記のようなフォルダ構成にします。

docker-wildfly-example/
├── Dockerfile
├── container_settings.json
├── docker-wildfly-example.iml
├── pom.xml
└── src
    └── main
        ├── java
        │   └── org
        │       └── katsumi
        │           └── HelloBean.java
        └── webapp
            ├── WEB-INF
            │   └── web.xml
            └── index.xhtml

肝心なDockerfileの内容は下記のようになります。

# WildFlyのイメージを取得
FROM jboss/wildfly:latest

# MAINTAINER
MAINTAINER Katsumi

# アプリケーションのデプロイ
COPY target/docker-wildfly-example.war /opt/jboss/wildfly/standalone/deployments/

# ポートの解放
EXPOSE 9999

# WildFlyの実行
CMD ["/opt/jboss/wildfly/bin/standalone.sh", "-b", "0.0.0.0", "--debug", "9999"]

mvn packageすることで生成されるtarget/docker-wildfly-example.warファイルを コンテナ上の/opt/jboss/wildfly/standalone/deployments/に配置することで WildFly起動時に自動的にデプロイさせます。 また、デバッグ用のポートとして9999を使用するためEXPOSEに指定します。

デバッグはリモートデバッグをすることになるので、 WildFly起動オプションに--debugを付与して9999ポートを指定します。

実行環境の構築

IntelliJ IDEAにDocker PluginがインストールされているとRun/Debug ConfigurationsにDocker Deploymentを追加することができます。

Debugポートに9999を指定すると画面下部にワーニングが表示されます。

Warning: Debug port forwarding not found

このワーニングの右側にFixボタンを表示されるのでこれをクリックすると port設定をしたjsonファイルの保存先を聞かれるので任意の場所に保存します。 アプリケーションツリーにあるcontainer_settings.jsonがそれになります。 このファイルはContainerタブのJSON fileの項目に設定されます。

やっていることはContainerタブのport bindingsで9999ポートを追加したのと同じことなのですが、 port bindingsに設定してもワーニングが消えません。 ワーニングは消えなくてもport bindingsの設定は有効になるので ワーニングが気にならないようであればport bindingsに設定しても良いです。 ただし注意点としてjsonファイルとport bindingsの両方を指定するとport bindingsの方の設定が無視されるようです。 9999以外のポートをバインドする場合は注意する必要があります。

これでデバッグ起動すればステップ実行ができるようになります。

subscribe via RSS