問題
- Service Builder を使用してカスタム サービスを開発しました。 サービス メソッドは、パラメーターとして文字列を受け取ります。
- JSON API を介してアクセスします。
- 文字列の長さが短い場合 (数百キロバイト)、サービスは正常に動作します。
- ただし、文字列の長さが長い場合 (数メガバイト -pe 4 または 5-) ログに次のエラーが表示されます。
[JSONWebServiceServiceAction:114] Unable to deserialize object
Environment
Liferay DXP 7.2-
Tomcat 9.0.33アプリケーション サーバー。
解決策
解析:
- まず、エラーに関する追加情報を取得するために、次の構成が追加されます。
-
portal-ext.propertiesファイルの次のプロパティを trueに設定します。
-
json.service.serialize.throwable=true
- サーバーを再起動し、次のログ カテゴリを DEBUG 値で追加します。
com.liferay.portal.jsonwebservice.JSONWebServiceServiceAction
- これで、
Liferay DXP のログに次のトレースが表示されるはずです。
2022-11-21 13:57:41.055 DEBUG [http-nio-8080-exec-2][JSONWebServiceServiceAction:111] Unable to deserialize object
java.lang.IllegalStateException: Unable to deserialize object
at com.liferay.portal.json.JSONFactoryImpl.looseDeserialize(JSONFactoryImpl.java:229)
at com.liferay.portal.kernel.json.JSONFactoryUtil.looseDeserialize(JSONFactoryUtil.java:103)
at com.liferay.portal.jsonwebservice.action.JSONWebServiceInvokerAction.invoke(JSONWebServiceInvokerAction.java:84)
at com.liferay.portal.jsonwebservice.JSONWebServiceServiceAction.getJSON(JSONWebServiceServiceAction.java:68)
at com.liferay.portal.struts.JSONAction.execute(JSONAction.java:74)
at com.liferay.portal.servlet.JSONServlet.service(JSONServlet.java:63)
at com.liferay.portal.jsonwebservice.JSONWebServiceServlet.service(JSONWebServiceServlet.java:63)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
....Caused by: jodd.json.JsonException: Syntax error! Invalid char: c_offset: 0 near: "cmd=%7B%22..." [Sanitized]
at jodd.json.JsonParser.syntaxError(JsonParser.java:1012)
at jodd.json.JsonParser.parseValue(JsonParser.java:421)
at jodd.json.JsonParser._parse(JsonParser.java:271)
at jodd.json.JsonParser.parse(JsonParser.java:240)
at com.liferay.portal.json.JSONDeserializerImpl.deserialize(JSONDeserializerImpl.java:41)
at com.liferay.portal.json.JSONFactoryImpl.looseDeserialize(JSONFactoryImpl.java:222)
... 75 more
- 根本原因 、アプリケーション サーバーが POST 要求を管理する方法に焦点を当てています。 Tomcat には、POST サイズ リクエストの最大値があります。 デフォルトでは、この制限は 2 メガバイトです。
- この制限を超えると、パラメーターの値が Tomcat によって返されなくなります。
-
Liferay DXPは返されたパラメーターをチェックし、それらが null の場合は、リクエストに含まれる JSON オブジェクトを取得します。
public JSONWebServiceInvokerAction(HttpServletRequest httpServletRequest) {
_httpServletRequest = httpServletRequest;
String command = httpServletRequest.getParameter(Constants.CMD);
if (command == null) {
try {
command = ServletUtil.readRequestBody(httpServletRequest);
}
catch (IOException ioException) {
throw new IllegalArgumentException(ioException);
}
}
_command = command;
}
- パラメータ CMD は
'cmd='文字列で始まるため、有効な JSON オブジェクトではないため、解析エラーが発生します。
Caused by: jodd.json.JsonException: Syntax error! Invalid char: c_offset: 0 near: "cmd=%7B%22..."ソリューション
- したがって、解決策 、Tomcat アプリケーション サーバーの HTTP コネクタでの POST サイズ要求の値を高く設定することです。 基本的には、
server.xmlファイルで設定を行い、<Connector>要素でmaxPostSize属性を定義します。いずれにせよ、この構成を適用する方法については、Tomcat のドキュメントを参照してください。
追加情報
- Tomcat の最大 POST サイズ パラメータ制限:
-
パラメータが null の場合、Liferay DXPは完全なリクエストを取得します。
- Tomcat アプリケーション サーバーの構成: POST サイズ要求