Неожиданное исключение: обнаружена настройка "xxx" для класса "xxx": ошибка при установке выражения "xxx" со значением ['x', ]
Я передаю некоторые параметры реализации класса действий ModelDriven<Transporter>
через строку запроса.
<s:form namespace="/admin_side" action="Test" id="dataForm" name="dataForm">
<s:url id="editURL" action="EditTest" escapeAmp="false">
<s:param name="transporterId" value="1"/>
<s:param name="transporterName" value="'DHL'"/>
</s:url>
<s:a href="%{editURL}">Click</s:a>
</s:form>
Класс действий выглядит следующим образом.
@Namespace("/admin_side")
@ResultPath("/WEB-INF/content")
@ParentPackage(value = "struts-default")
public final class TestAction extends ActionSupport
implements Serializable, Preparable, ModelDriven<Transporter>
{
private static final long serialVersionUID = 1L;
private Transporter transporter = new Transporter();
@Action(value = "Test",
results = {
@Result(name = ActionSupport.SUCCESS, location = "Test.jsp"),
@Result(name = ActionSupport.INPUT, location = "Test.jsp")},
interceptorRefs = {
@InterceptorRef(value = "paramsPrepareParamsStack",
params = {"params.acceptParamNames", "transporterId, transporterName"})})
public String load() throws Exception {
return ActionSupport.SUCCESS;
}
@Action(value = "EditTest",
results = {
@Result(name = ActionSupport.SUCCESS, location = "Test.jsp"),
@Result(name = ActionSupport.INPUT, location = "Test.jsp")},
interceptorRefs = {
@InterceptorRef(value = "paramsPrepareParamsStack",
params = {"params.acceptParamNames", "transporterId, transporterName"})})
public String edit() {
System.out.println(transporter.getTransporterId()
+ " : " + transporter.getTransporterName());
return ActionSupport.SUCCESS;
}
@Override
public Transporter getModel() {
return transporter;
}
@Override
public void prepare() throws Exception {}
}
Терминал сервера отображает следующие сообщения.
Jan 09, 2014 4:06:32 PM com.opensymphony.xwork2.interceptor.ParametersInterceptor error
SEVERE: Developer Notification (set struts.devMode to false to disable this message):
Unexpected Exception caught setting 'transporterId' on 'class actions.TestAction: Error setting expression 'transporterId' with value ['1', ]
Jan 09, 2014 4:06:32 PM com.opensymphony.xwork2.interceptor.ParametersInterceptor error
SEVERE: Developer Notification (set struts.devMode to false to disable this message):
Unexpected Exception caught setting 'transporterName' on 'class actions.TestAction: Error setting expression 'transporterName' with value ['DHL', ]
Хотя уровень журнала SEVERE
значения этих параметров доступны в классе действий как
System.out.println(transporter.getTransporterId()
+ " : " + transporter.getTransporterName());
в edit()
метод.
Если paramsPrepareParamsStack
заменяется defaultStack
затем эти сообщения исчезают.
Выражения как ['DHL', ]
указать массив. transporterId
а также transporterName
в модели, однако типа Long
а также String
соответственно.
Что я делаю неправильно?
1 ответ
Здесь нет проблем с массивами (даже если это выглядит так): такого рода исключение означает, что Struts не может найти Setter для вашего параметра:
Из документации ParametersInterceptor:
Предупреждение о пропущенных параметрах
Если для заданного имени параметра нет установщика, в devMode будет записано предупреждающее сообщение, подобное приведенному ниже:
SEVERE: Developer Notification (set struts.devMode to false to disable this message): Unexpected Exception caught setting 'search' on 'class demo.ItemSearchAction: Error setting expression 'search' with value ['search', ] Error setting expression 'search' with value ['search', ] - [unknown location] at com.opensymphony.xwork2.ognl.OgnlValueStack.handleRuntimeException(OgnlValueStack.java:201) at com.opensymphony.xwork2.ognl.OgnlValueStack.setValue(OgnlValueStack.java:178) at com.opensymphony.xwork2.ognl.OgnlValueStack.setParameter(OgnlValueStack.java:152)
Таким образом, ожидается поведение, позволяющее разработчику обнаружить отсутствующий установщик или опечатку либо в имени параметра, либо в установщике.
Вы можете легко воспроизвести эту ошибку, поместив в JSP элемент, который не существует в действии.
Так как ваши свойства существуют (с их сеттерами) в модели, и вы используете ModelDriven
а также paramsPrepareParamsStack
Я думаю, что происходит:
ModelDriven Interceptor
делегирован для обработки объекта Model;- Первый раз звонишь
Parameters Interceptor
,ModelDriven Interceptor
еще не побежал; - Тогда ваше действие ничего не знает об объекте модели и попытается найти сеттеры для ваших параметров в действии, а не в модели.
- Вместо этого второй перехватчик запускается после ModelDriven и точно знает, где установить параметры. Вот почему параметры правильно установлены в методе Action.
Но если это так, то вы НЕ сможете получить эти параметры в prepare()
Метод (вот почему вы используете этот стек...):
Пожалуйста, попробуйте и опубликуйте здесь результат.
Первое, что приходит мне в голову, чтобы решить эту проблему, это разместить ModelDriven Interceptor
до первого Parameters Interceptor
(либо копируя его, либо перемещая, я не уверен, какой побочный эффект, если таковой имеется, может возникнуть в обоих случаях, вы должны снова попытаться сообщить об этом здесь).
Затем определите следующий стек и используйте его.
<interceptor-stack name="modelParamsPrepareParamsStack">
<interceptor-ref name="exception"/>
<interceptor-ref name="alias"/>
<interceptor-ref name="i18n"/>
<interceptor-ref name="checkbox"/>
<interceptor-ref name="multiselect"/>
<!-- NEW ModelDriven Position -->
<interceptor-ref name="modelDriven"/>
<interceptor-ref name="params">
<param name="excludeParams">^dojo\..*,^struts\..*,^session\..*,^request\..*,^application\..*,^servlet(Request|Response)\..*,^parameters\..*,^action:.*,^method:.*</param>
</interceptor-ref>
<interceptor-ref name="servletConfig"/>
<interceptor-ref name="prepare"/>
<interceptor-ref name="chain"/>
<!-- OLD ModelDriven Position -->
<!--interceptor-ref name="modelDriven"/-->
<interceptor-ref name="fileUpload"/>
<interceptor-ref name="staticParams"/>
<interceptor-ref name="actionMappingParams"/>
<interceptor-ref name="params">
<param name="excludeParams">^dojo\..*,^struts\..*,^session\..*,^request\..*,^application\..*,^servlet(Request|Response)\..*,^parameters\..*,^action:.*,^method:.*</param>
</interceptor-ref>
<interceptor-ref name="conversionError"/>
<interceptor-ref name="validation">
<param name="excludeMethods">input,back,cancel,browse</param>
</interceptor-ref>
<interceptor-ref name="workflow">
<param name="excludeMethods">input,back,cancel,browse</param>
</interceptor-ref>
</interceptor-stack>
Надеюсь, это поможет.
В коде, который вы дали, я не могу найти объявление класса Transporter.
Поэтому я думаю, что это может быть потому, что ваш класс Transpoter имеет больше параметров, чем 2, а не только идентификатор и имя.
На самом деле, это сообщение об ошибке всегда возникало в ситуации, о которой я говорил.
Чтобы решить эту проблему, вы можете определить объект передачи данных (DTO), который имеет только 2 атрибута, id и name. Используйте это DTO, чтобы принять параметры из jsp, а затем передать значение атрибутов объекту Transporter.
Я вижу эту проблему в 2019 году и предлагаю решение, надеясь, что оно может быть полезным для других в будущем.