2011-10-07 6 views
7

Ho un'applicazione struts2 che utilizza il plug-in-rest-plugin v.2.2.3.Richiesta POST a Struts2 con plug-in REST che non riceve risposta

Tutto funziona perfettamente quando si tratta del routing delle richieste alle azioni e ai relativi metodi e sto anche utilizzando ModelDriven per specificare l'oggetto da serializzare quando si usano estensioni come JSON e XML.

Il problema che sto avendo è che quando invio una richiesta POST o PUT al layer struts, ottengo solo una risposta vuota.

Sto inviando una richiesta POST all'azione in questo modo: http://localhost:8080/alert-settings!update.json. Ho un punto di interruzione in quel metodo e viene chiamato e il codice viene eseguito e completato. Ho la sensazione che il problema potrebbe essere che sto cercando di utilizzare l'interfaccia ModelDriven per inviarmi indietro la risposta e per qualche motivo il resto-plugin non piace questo, ma non so perché si comporterebbe in quel modo.

C'è un problema noto con la ricezione di risposte dalle richieste POST mentre si utilizza il resto del plugin? Ho cercato ovunque e non riesco a trovare nulla al riguardo davvero.

Qualsiasi aiuto apprezzato e posso fornire ulteriori dettagli su richiesta.

+0

non riuscivo a trovare un modo per aggirare questo, ma ho optato per alterare il codice di risposta restituendo DefaultHttpHeaders invece di SUCCESSO. Penso che questo potrebbe essere il modo di andare con le richieste POST e PUT. – noShowP

+0

Ciao, sto usando anche il plugin struts2-rest-plugin e sto avendo problemi ad ottenere il metodo update() per accettare un payload JSON e mapparlo correttamente al modello. Ti dispiace condividere come hai fatto? Grazie .. – shaunlim

risposta

4

Ho riscontrato lo stesso problema. Hai provato a impostare nel file struts.xml:

struts.rest.content.restrictToGET = false 

vedere l'ultima impostazione the rest plugin docs

1

in realtà ho capito che si trattava di una linea nel resto del plugin causando questo:

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

Questo è in org.apache.struts2.rest.RestActionInvocation nel metodo selectTarget(). Trovo che questo sia piuttosto fastidioso in quanto in realtà non segue l'architettura REST, id come l'opzione di essere in grado di restituire gli oggetti risposta per le richieste POST, DELETE e PUT in alcuni casi.

ho lavorato intorno a questo estendendo RestActionProxyFactory e RestActionInvocation e specificando l'uso di questo nel mio montanti xml in questo modo:

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

Questo mi permette di utilizzare i montanti plug tutto mentre tornava oggetto richieste 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

Potrebbe esserci un modo migliore per risolvere questo problema, quindi per favore condividi se c'è. – noShowP

0

Ho usato le azioni Struts con i tipi di risultato misti in passato, di ritorno JSON, XML e piastrelle per esempio. Non sono sicuro che sia il modo consigliato per farlo, ma richiede alcune configurazioni usando struts.xml anche se vengono utilizzate le convenzioni. Forse l'hai già fatto, non sono sicuro che non ci siano abbastanza informazioni per dirlo.

impostazioni 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> 

Ho installato i tipi di risultato in più per essere utilizzato su azioni specifiche in seguito. Nella classe azione è quindi possibile impostare i tipi di risultati per azione o metodo.

Class Action:

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

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

Un'altra cosa da notare su risultati JSON, ho notato che quando ho un oggetto serializzabile viene restituito come risultato, se l'oggetto contiene altri oggetti complessi con un getter/setter che restituisce l'oggetto incorporato, spesso riceverò un risultato vuoto o nessun risultato. Spesso finisco per scrivere oggetti json wrapper da utilizzare per i miei risultati json con getter/setter che restituiscono solo i tipi java (String, int, Boolean, ecc.) E non gli oggetti incorporati. Penso che abbia risolto questo problema con getter/setter delegati, ma dovrò tornare indietro e guardare un vecchio codice.

+0

Ho praticamente fatto ciò che hai fatto qui eccetto che ho usato il plugin struts2-rest-plugin v.2.2.3 che gestisce i risultati per te. Quindi non è necessario specificare un tipo di JsonSuccess, basta aggiungere .json alla fine dell'url così /job.json chiamerà il metodo index di JobAction e restituirà il suo risultato in JSON. La domanda era specifica per il comportamento di non restituire nulla da qualsiasi azione quando la richiesta era un POST (quindi POST a /job.json non restituirebbe alcun dato, solo un successo o un fallimento). – noShowP

Problemi correlati