POST-запрос к Struts2 с плагином REST, не получающим ответ

У меня есть приложение Struts2, которое использует Struts2-Rest-плагин v.2.2.3.

Все отлично работает, когда дело доходит до маршрутизации запросов к действиям и их методам, и я также использую ModelDriven, чтобы указать объект для сериализации при использовании расширений, таких как JSON и XML.

У меня проблема в том, что когда я отправляю запрос POST или PUT на слой Struts, я просто получаю пустой ответ.

Я отправляю запрос POST к действию следующим образом: http://localhost:8080/alert-settings!update.json, У меня есть точка останова в этом методе, и он вызывается, и код выполняется и завершается. У меня есть ощущение, что проблема может заключаться в том, что я пытаюсь использовать интерфейс ModelDriven, чтобы отправить мне ответ, и по какой-то причине плагину rest это не нравится, но я не знаю, почему он будет себя так вести.

Известна ли проблема с получением ответов от запросов POST при использовании плагина rest? Я искал повсюду и ничего не могу найти по этому поводу.

Любая помощь приветствуется, и я могу предоставить более подробную информацию по запросу.

3 ответа

Решение

Я столкнулся с той же проблемой. Вы пытались установить в файле struts.xml:

struts.rest.content.restrictToGET = false

Смотрите последние настройки на остальных плагин документации

Я на самом деле понял, что это была строка в плагине отдыха, вызывающая это:

// don't return any content for PUT, DELETE, and POST where there are no errors
if (!hasErrors && !"get".equalsIgnoreCase(ServletActionContext.getRequest().getMethod())) {
  target = null;
}

Это в org.apache.struts2.rest.RestActionInvocation в selectTarget() метод. Я нахожу это довольно раздражающим, так как он на самом деле не следует архитектуре REST, например, возможность в некоторых случаях возвращать объекты ответа для запросов POST, DELETE и PUT.

Я работал над этим, расширяя RestActionProxyFactory а также RestActionInvocation и указав использование этого в моих стояках xml, вот так:

<bean type="com.opensymphony.xwork2.ActionProxyFactory" name="restOverride" class="uk.co.ratedpeople.tp.rest.RPRestActionProxyFactory" />
<constant name="struts.actionProxyFactory" value="restOverride" />

Это позволяет мне использовать плагин struts повсюду, возвращая объект по запросам POST.

RestActionProxyFactory

public class RPRestActionProxyFactory extends RestActionProxyFactory {

    @Override
    public ActionProxy createActionProxy(String namespace, String actionName, String methodName, Map extraContext, boolean executeResult, boolean cleanupContext) {
        if (namespace.startsWith(this.namespace)) {
            ActionInvocation inv = new RPRestActionInvocation(extraContext, true);
            container.inject(inv);
            return createActionProxy(inv, namespace, actionName, methodName, executeResult, cleanupContext);
        } else {
            return super.createActionProxy(namespace, actionName, methodName, extraContext, executeResult, cleanupContext);
        }
    }

}

RestActionInvocation

public class RPRestActionInvocation extends RestActionInvocation {

    public RPRestActionInvocation(Map extraContext, boolean pushAction) {
        super(extraContext, pushAction);
    }

    @SuppressWarnings("unchecked")
    @Override
    protected void selectTarget() {

        // Select target (content to return)
        Throwable e = (Throwable)stack.findValue("exception");
        if (e != null) {

            // Exception
            target = e;
            hasErrors = true;

        } else if (action instanceof ValidationAware && ((ValidationAware)action).hasErrors()) {

            // Error messages
            ValidationAware validationAwareAction = ((ValidationAware)action);

            Map errors = new HashMap();
            if (validationAwareAction.getActionErrors().size() > 0) {
                errors.put("actionErrors", validationAwareAction.getActionErrors());
            }
            if (validationAwareAction.getFieldErrors().size() > 0) {
                errors.put("fieldErrors", validationAwareAction.getFieldErrors());
            }
            target = errors;
            hasErrors = true;

        } else if (action instanceof ModelDriven) {

            // Model
            target = ((ModelDriven)action).getModel();

        } else {
            target = action;
        }

        // don't return any content for PUT, DELETE, and POST where there are no errors
//      if (!hasErrors && !"get".equalsIgnoreCase(ServletActionContext.getRequest().getMethod())) {
//          target = null;
//      }
    }

}

В прошлом я использовал действия Struts со смешанными типами результатов, например, возвращая json, xml и тайлы. Я не уверен, является ли это рекомендуемым способом сделать это, но он требует некоторой конфигурации с использованием struts.xml, даже если используются соглашения. Возможно, вы уже сделали это, но не уверены, что недостаточно информации, чтобы рассказать.

Настройки Struts.xml:

<constant name="struts.convention.default.parent.package" value="restful"/>

<package name="restful"  extends="rest-default, struts-default, json-default">
    <result-types>
        <result-type name="tiles" class="org.apache.struts2.views.tiles.TilesResult" />
        <result-type name="json" class="com.googlecode.jsonplugin.JSONResult"/>
    </result-types>

    ....
</package>

Я настроил дополнительные типы результатов, которые будут использоваться для определенных действий позже. В классе действий вы можете настроить типы результатов с помощью действия или метода.

Класс действий:

@Results({
    @Result(name = "JsonSuccess", type = "json"),
    @Result(name = "success", type = "tiles", location = "/tickets.tiles")
})

public class EventController extends RestActionSupport implements ModelDriven<EventBean>{
     ...
}

Что еще следует отметить в отношении результатов json, я заметил, что когда у меня есть возвращаемый в результате сериализуемый объект, если этот объект содержит другие сложные объекты с getter/setter, который возвращает внедренный объект, я часто получаю пустой результат или нет результата. Я часто заканчиваю тем, что пишу объекты-обертки json для использования с результатами json с помощью методов получения / установки, которые возвращают только типы java (String, int, Boolean и т. Д.), А не внедренные объекты. Я думаю, что это решено с использованием делегатов getter/setters, но мне придется вернуться и посмотреть на старый код.

Другие вопросы по тегам