メンチカツには醤油でしょ!!

AWS/Java/Node.js/Spreadsheets/Docker/Jenkins/コミュニティ・勉強会レポを主とした技術系ブログ

EclipseLinkで取得した値のスペースがトリムされてしまう

環境

  • Oracle 12c
  • EclipseLink 2.5.2
  • JPA (Native Query)

現象

EclipseLink(JPA)において、CHAR型の主キー(PK)の値を取得すると
末尾のスペースが取得できない。(rtrimされたような状態で取得される)

こういうフィールドはVARCHARで設計すべきという一般論もありますが
今回はこのCHAR型のスペースがrtimされてしまう現象についてです。

Entityコード

@Entity
public class HogeEntity implements Serializable {
@Id
@Column @Getter @Setter
private String element;

@Column @Getter @Setter
private String // 略
// 略
}

対応方針の検討

stackoverflow.com

stackoverflow.com

これらを参照する所によると、取得後のfillSpaceで対応したり、@PostLoadアノテーションでカバーしたりするのは良くなさそうです。

VARCHARにしたり、SessionCustomizerをextendsするのが良さそうです。

Wildfly/JBossでIllegalStateException: UT000047: The number of parameters exceeded the maximum of 1000

突然のIllegalStateException

こんなエラーが出た時の話です。

YYYY-MM-DD HH:mm:SS,SSS ERROR [io.undertow.request] (default task-40) UT005023: Exception handling request to /MyApplicationWeb/SCREEN_ID/.action: java.lang.IllegalStateException: UT000047: The number of parameters exceeded the maximum of 1000
at io.undertow.server.handlers.form.FormData.add(FormData.java:78)
at io.undertow.server.handlers.form.FormData.add(FormData.java:68)
at io.undertow.server.handlers.form.FormEncodedDataDefinition$FormEncodedDataParser.doParse(FormEncodedDataDefinition.java:185)
at io.undertow.server.handlers.form.FormEncodedDataDefinition$FormEncodedDataParser.parseBlocking(FormEncodedDataDefinition.java:251)
at io.undertow.servlet.spec.HttpServletRequestImpl.parseFormData(HttpServletRequestImpl.java:762)
at io.undertow.servlet.spec.HttpServletRequestImpl.getParameterMap(HttpServletRequestImpl.java:717)
at org.apache.struts2.dispatcher.Dispatcher.createContextMap(Dispatcher.java:634)
at org.apache.struts2.dispatcher.ng.PrepareOperations.createActionContext(PrepareOperations.java:82)
at org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter.doFilter(StrutsPrepareAndExecuteFilter.java:89)
at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:60)
at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
at io.undertow.servlet.handlers.FilterHandler.handleRequest(FilterHandler.java:84)
at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:62)
at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36)
at org.wildfly.extension.undertow.security.SecurityContextAssociationHandler.handleRequest(SecurityContextAssociationHandler.java:78)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:131)
at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:57)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46)
at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:64)
at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:60)
at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:77)
at io.undertow.security.handlers.NotificationReceiverHandler.handleRequest(NotificationReceiverHandler.java:50)
at io.undertow.security.handlers.AbstractSecurityContextAssociationHandler.handleRequest(AbstractSecurityContextAssociationHandler.java:43)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at org.wildfly.extension.undertow.security.jacc.JACCContextIdHandler.handleRequest(JACCContextIdHandler.java:61)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:284)
at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:263)
at io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:81)
at io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:174)
at io.undertow.server.Connectors.executeRootHandler(Connectors.java:202)
at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:793)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)

原因

サーバーサイドへ送られるパラメータが1000を超えると出ます。
検索結果リスト内で<input type="hidden" />でキーを持っていたり
編集可能な検索結果リストで<input type="text" />があったりすると
この制限にすぐ達します。

そうなるとフレームワークにもよりますがエラーハンドリング/Interceptorの外でExceptionになることがあり、500が出ます。

f:id:ryoichi0102:20161017131723j:plain

IEで出るけどChromeで出ないなんてこともあると思いますが、
単にサーバーサイドの問題かと思いきや

<input type="hidden" name="" value="aaaaa" />

のような場合のname=""の送信動作に違うがあるものと思われます。

対応方針

1. 不要な<input />タグのレンダリングをしない
2. パラメータの限界値を上げる

1. 不要な<input />タグのレンダリング排除

これで済むならそうしましょう。
検索結果リスト表示にて内部(hidden)でキー値を保持するためのレンダリングがよくあるパターンかと思いますが、そういう場合は

<a href="#" class="go-detail">詳細へ</a>
<input type="hidden" name="" class="row-id" value="*****" />

みたいな実装になっているかも知れませんが、これは

<a href="#" class="go-detail">詳細へ</a>
<span class="hidden row-id">*****</span>

で済みます。

2. パラメータの限界値を上げる

上記でどうしようもない時は限界値を上げましょう。
どれぐらい上げるかは非機能要件をしっかり見積もることをオススメします。

WildflyとJBossバージョンで対応方法が違います。

Wildfly

C:\wildfly-10.0.0.Final\standalone\configuration\standalone.xml にて、

<http-listener name="default" socket-binding="http" />

<http-listener name="default" socket-binding="http" max-parameters="1500" />

と変更します。

JBoss

C:\jboss-as-7.1.1.Final\standalone\configuration\standalone.xml
の、31行目ぐらいに

<system-properties>
<property name="org.apache.tomcat.util.http.Parameters.MAX_COUNT" value="1500"/>
</system-properties>

を追加します。
(</extensions>と<management>の間ぐらい)

参考

stackoverflow.com

older

stackoverflow.com

Struts2のJSP内でenumやインナークラスへアクセスする方法 (OGNL式)

環境

Struts 2.3.30

今回はenumやインナークラスへのアクセスです

以前も似たようなことを書きました。

ryoichi0102.hatenablog.com

enumへのアクセスもstaticフィールドと同様

こんな実装だったとしたら

package fully.qualified.packagename;
public enum EnumName {
    ENUM_VALUE,
}
<s:property value="%{@fully.qualified.packagename.EnumName@ENUM_VALUE}" />

完全修飾クラス名を@@で囲いフィールド名を繋げ{}で囲って%を接頭語に、という所は同じですね。

インナークラスへのアクセスは$で繋ぐ

例えば外部のpropertiesから設定値を取ってきてenumを返すUtil/メソッドと
Util内のインナーenumを比較するようなコードはこうなります。

package fully.qualified.packagename;
public class UtilClassName {
    public enum InnerEnum {
        ENUM_VAL,,,
    }
    pubic static UtilClassName getInstance() {
        return instance;
    }
    public InnerEnum getSomeEnum() {
        return InnerEnum.valueOf(getSomePropertyValue());
    }
}
<s:if test="%{@fully.qualified.packagename.UtilClassName@getInstance().getSomeEnum() == @fully.qualified.packagename.UtilClassName$InnerEnum@ENUM_VAL}">
    <!-- true -->
</s:if>

※ inner/enumで同時に起こったのでちょっと手間取りました^^

参考

stackoverflow.com