2011-10-07 11 views
7

Tengo una aplicación struts2 que usa struts2-rest-plugin v.2.2.3.Solicitud POST a Struts2 con el complemento REST sin respuesta

Todo está funcionando muy bien cuando se trata de enrutar las solicitudes a las acciones y sus métodos, y también estoy usando ModelDriven para especificar el objeto a serializar cuando se utilizan extensiones como JSON y XML.

El problema que tengo es que cuando envío una solicitud de POST o PUT a la capa de struts me sale una respuesta vacía.

Estoy enviando una solicitud POST a la acción como tal: http://localhost:8080/alert-settings!update.json. Tengo un punto de interrupción en ese método y se llama y el código se ejecuta y completa. Tengo la sensación de que el problema podría ser que estoy tratando de usar la interfaz ModelDriven para enviarme la respuesta y por alguna razón el resto del complemento no le gusta, pero no sé por qué se comportaría así.

¿Existe un problema conocido con la recepción de respuestas de solicitudes POST al usar el complemento de reposo? He buscado en todas partes y no puedo encontrar nada al respecto realmente.

Cualquier ayuda apreciada y puedo proporcionar más detalles a petición.

+0

no pude encontrar una forma de evitar esto, pero me decidí por alterar el código de respuesta mediante la devolución de DefaultHttpHeaders vez del éxito. Creo que esta podría ser la forma de ir con las solicitudes POST y PUT. – noShowP

+0

Hola, también estoy usando struts2-rest-plugin y tengo problemas para que el método update() acepte una carga útil JSON y la asigne correctamente al modelo. ¿Te importa compartir cómo lo hiciste? Gracias. – shaunlim

Respuesta

4

Tuve el mismo problema. ¿Ha tratado de establecer en el archivo struts.xml:

struts.rest.content.restrictToGET = false 

Ver el último ajuste en the rest plugin docs

1

realidad me di cuenta de que era una línea en el resto de plugins causando esto:

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

Esto está en org.apache.struts2.rest.RestActionInvocation en el método selectTarget(). Encuentro esto bastante molesto ya que realmente no sigue la arquitectura REST, id como la opción de poder devolver los objetos de respuesta para las solicitudes POST, DELETE y PUT en algunos casos.

trabajé en torno a esta extendiendo RestActionProxyFactory y RestActionInvocation y especificando el uso de XML en mi puntales de este modo:

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

Esto me permite utilizar los puntales plugin de largo mientras que volvía objeto en las peticiones 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; 
//  } 
    } 

} 
+0

Puede haber una mejor manera de resolver este problema, así que por favor comparte si existe. – noShowP

0

He usado acciones puntales con tipos de resultados mixtos en el pasado, volviendo JSON, XML, y las baldosas, por ejemplo. No estoy seguro de si es la forma recomendada de hacerlo, pero requiere alguna configuración con struts.xml aunque se estén utilizando convenciones. Tal vez ya lo haya hecho, no estoy seguro de que no haya suficiente información para contar.

configuración 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> 

He fijado los tipos de resultados adicionales para ser utilizado en acciones específicas más tarde. En la clase de acción, puede configurar sus tipos de resultados por acción o método.

Acción Clase:

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

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

Otra cosa a tener en cuenta sobre los resultados JSON, me he dado cuenta de que cuando tengo un objeto serializable ser devueltos como resultado, si ese objeto contiene otros objetos complejos con una getter/setter que devuelve el objeto incrustado, a menudo recibiré un resultado vacío o sin resultado. A menudo termino escribiendo objetos json wrapper para usar en mis resultados json con getters/setters que solo devuelven tipos java (String, int, boolean, etc.) y no los objetos incrustados. Creo que he resuelto esto utilizando deleters/setters de delegados, pero tendré que volver y mirar algún código antiguo.

+0

He terminado lo que ha hecho aquí, excepto que he utilizado struts2-rest-plugin v.2.2.3, que maneja los resultados por usted. Así que no necesita especificar un tipo de JsonSuccess. Simplemente agrega .json al final de la url, de modo que /job.json llamará al método de índice JobAction y devolverá su resultado en JSON. La pregunta era específica del comportamiento de que no devolviera nada de ninguna acción cuando la solicitud era un POST (por lo que POST a /job.json no devolvería ningún dato, solo un éxito o error). – noShowP

Cuestiones relacionadas