invio di Lista / Mappa come maglia dei parametri POST

Voglio inviare un object HashMap a una risorsa ReST come variabile POST. Ho usato la class Form per inviare l’object. Il codice cliente:

 public static void main(String[] args) { ClientConfig config = new DefaultClientConfig(); Client client = Client.create(config); WebResource service = client.resource(getBaseURI()); HashMap hashmap = new HashMap(); hashmap.put("Key1", "value1"); hashmap.put("Key2", "value2"); Form form = new Form(); form.add("data1", hashmap); ClientResponse response = service.path("hello2").path("hello2").type(MediaType.APPLICATION_FORM_URLENCODED).post(ClientResponse.class, form); @SuppressWarnings("unchecked") MultivaluedMap map = response.getEntity(MultivaluedMap.class); System.out.println(map.get("response").get(0)); System.out.println(map.get("response2")); } 

La risorsa REST è la seguente:

 @Path("/hello2") public class FormResource { @Context UriInfo uriInfo; @Context Request request; public FormResource() { } public FormResource(UriInfo uriInfo, Request request)// , String data1) { this.uriInfo = uriInfo; this.request = request; } @POST @Consumes(MediaType.APPLICATION_FORM_URLENCODED) public MultivaluedMap newProj(@FormParam("data1") HashMap postVarMap, @Context HttpServletResponse response) { System.out.println(postVarMap); MultivaluedMap hash = new MultivaluedMapImpl(); hash.add("response", "response1"); hash.add("response", "response2"); hash.add("response2", "fbshabfsdb"); URI uri = uriInfo.getAbsolutePathBuilder().build(); Response.created(uri).build(); return hash; } } 

Ottengo la seguente eccezione nel registro di Tomcat 6.0

 Dec 7, 2011 3:38:39 PM org.apache.catalina.core.StandardContext reload INFO: Reloading Context with name [/JerCDemo] has started Dec 7, 2011 3:38:40 PM com.sun.jersey.api.core.PackagesResourceConfig init INFO: Scanning for root resource and provider classs in the packages: com.reflexis.nbe.jersey Dec 7, 2011 3:38:40 PM com.sun.jersey.api.core.ScanningResourceConfig logClasses INFO: Root resource classs found: class com.reflexis.nbe.jersey.FormResource Dec 7, 2011 3:38:40 PM com.sun.jersey.api.core.ScanningResourceConfig init INFO: No provider classs found. Dec 7, 2011 3:38:40 PM com.sun.jersey.server.impl.application.WebApplicationImpl _initiate INFO: Initiating Jersey application, version 'Jersey: 1.9.1 09/14/2011 02:05 PM' Dec 7, 2011 3:38:40 PM com.sun.jersey.spi.inject.Errors processErrorMessages SEVERE: The following errors and warnings have been detected with resource and/or provider classs: SEVERE: Missing dependency for method public javax.ws.rs.core.MultivaluedMap com.reflexis.nbe.jersey.FormResource.newProj(java.util.HashMap,javax.servlet.http.HttpServletResponse) at parameter at index 0 SEVERE: Missing dependency for method public javax.ws.rs.core.MultivaluedMap com.reflexis.nbe.jersey.FormResource.newProj(java.util.HashMap,javax.servlet.http.HttpServletResponse) at parameter at index 0 SEVERE: Method, public javax.ws.rs.core.MultivaluedMap com.reflexis.nbe.jersey.FormResource.newProj(java.util.HashMap,javax.servlet.http.HttpServletResponse), annotated with POST of resource, class com.reflexis.nbe.jersey.FormResource, is not recognized as valid resource method. Dec 7, 2011 3:38:40 PM org.apache.catalina.core.ApplicationContext log SEVERE: StandardWrapper.Throwable com.sun.jersey.spi.inject.Errors$ErrorMessagesException at com.sun.jersey.spi.inject.Errors.processErrorMessages(Errors.java:170) at com.sun.jersey.spi.inject.Errors.postProcess(Errors.java:136) at com.sun.jersey.spi.inject.Errors.processWithErrors(Errors.java:199) at com.sun.jersey.server.impl.application.WebApplicationImpl.initiate(WebApplicationImpl.java:771) at com.sun.jersey.server.impl.application.WebApplicationImpl.initiate(WebApplicationImpl.java:766) at com.sun.jersey.spi.container.servlet.ServletContainer.initiate(ServletContainer.java:488) at com.sun.jersey.spi.container.servlet.ServletContainer$InternalWebComponent.initiate(ServletContainer.java:318) at com.sun.jersey.spi.container.servlet.WebComponent.load(WebComponent.java:609) at com.sun.jersey.spi.container.servlet.WebComponent.init(WebComponent.java:210) at com.sun.jersey.spi.container.servlet.ServletContainer.init(ServletContainer.java:373) at com.sun.jersey.spi.container.servlet.ServletContainer.init(ServletContainer.java:556) at javax.servlet.GenericServlet.init(GenericServlet.java:212) at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1173) at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:993) at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:4420) at org.apache.catalina.core.StandardContext.start(StandardContext.java:4733) at org.apache.catalina.core.StandardContext.reload(StandardContext.java:3460) at org.apache.catalina.loader.WebappLoader.backgroundProcess(WebappLoader.java:426) at org.apache.catalina.core.ContainerBase.backgroundProcess(ContainerBase.java:1357) at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1649) at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1658) at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1658) at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.run(ContainerBase.java:1638) at java.lang.Thread.run(Thread.java:619) Dec 7, 2011 3:38:40 PM org.apache.catalina.core.StandardContext loadOnStartup SEVERE: Servlet /JerCDemo threw load() exception com.sun.jersey.spi.inject.Errors$ErrorMessagesException at com.sun.jersey.spi.inject.Errors.processErrorMessages(Errors.java:170) at com.sun.jersey.spi.inject.Errors.postProcess(Errors.java:136) at com.sun.jersey.spi.inject.Errors.processWithErrors(Errors.java:199) at com.sun.jersey.server.impl.application.WebApplicationImpl.initiate(WebApplicationImpl.java:771) at com.sun.jersey.server.impl.application.WebApplicationImpl.initiate(WebApplicationImpl.java:766) at com.sun.jersey.spi.container.servlet.ServletContainer.initiate(ServletContainer.java:488) at com.sun.jersey.spi.container.servlet.ServletContainer$InternalWebComponent.initiate(ServletContainer.java:318) at com.sun.jersey.spi.container.servlet.WebComponent.load(WebComponent.java:609) at com.sun.jersey.spi.container.servlet.WebComponent.init(WebComponent.java:210) at com.sun.jersey.spi.container.servlet.ServletContainer.init(ServletContainer.java:373) at com.sun.jersey.spi.container.servlet.ServletContainer.init(ServletContainer.java:556) at javax.servlet.GenericServlet.init(GenericServlet.java:212) at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1173) at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:993) at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:4420) at org.apache.catalina.core.StandardContext.start(StandardContext.java:4733) at org.apache.catalina.core.StandardContext.reload(StandardContext.java:3460) at org.apache.catalina.loader.WebappLoader.backgroundProcess(WebappLoader.java:426) at org.apache.catalina.core.ContainerBase.backgroundProcess(ContainerBase.java:1357) at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1649) at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1658) at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1658) at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.run(ContainerBase.java:1638) at java.lang.Thread.run(Thread.java:619) 

Il codice client scritto da me è corretto? C’è un altro modo per inviare un object HashMap come variabile POST?

Solo per chiarire un po ‘le cose. MultivaluedMap è pensato per essere utilizzato per ottenere la mappa generale dei parametri del modulo, ad esempio i parametri inviati al servizio tramite la richiesta HTTP POST. Dovrebbe essere usato in questo modo:

  @POST @Consumes("application/x-www-form-urlencoded") public void post(MultivaluedMap formParams) { // Store the message } 

Tuttavia, quando l’applicazione client deve fornire al tuo servizio REST una sorta di dati (nel tuo caso una HashMap contenente suppongo molte informazioni importanti) la serializzerà prima su XML, quindi la invierà al servizio che poi deserializzerà e usarlo. Sfortunatamente, Jersey non è in grado di eseguire automaticamente il marshall / unmmarshal HashMap , quindi se hai appena fornito il parametro HashMap nel tuo metodo newProj , otterrai un’eccezione.

Quindi, come inviare una HashMap al tuo servizio? Bene, la chiave è JAXB @XmlRootElement e un XmlAdapter personalizzato 🙂

Per prima cosa devi scrivere il tuo wrapper per la mappa. Il wrapper sarà annotato con @XmlRootElement

 @XmlRootElement public class MyHashMapObject { private Map mapProperty; public MyHashMapObject() { mapProperty = new HashMap(); } @XmlJavaTypeAdapter(MapAdapter.class) // NOTE: Our custom XmlAdaper public Map getMapProperty() { return mapProperty; } public void setMapProperty(Map map) { this.mapProperty = map; } } 

Quindi devi definire i tuoi elementi di mappa “abilitati JAXB”:

 public class MapElement { @XmlElement public String key; @XmlElement public String value; private MapElement() { } public MapElement(String key, String value) { this.key = key; this.value = value; } } 

E alla fine definisci il tuo XmlAdapter personalizzato:

 public class MapAdapter extends XmlAdapter> { public MapElement[] marshal(Map arg0) throws Exception { MapElement[] mapElements = new MapElement[arg0.size()]; int i = 0; for (Map.Entry entry : arg0.entrySet()) mapElements[i++] = new MapElement(entry.getKey(), entry.getValue()); return mapElements; } public Map unmarshal(MapElement[] arg0) throws Exception { Map r = new HashMap(); for (MapElement mapelement : arg0) r.put(mapelement.key, mapelement.value); return r; } } 

Una volta che tutto questo è stato messo a posto (deve essere usato dal tuo servizio e il cliente lo metta in qualche barattolo di shard), puoi definire il tuo servizio in questo modo:

 @Path("/hello") public class FormResource { //@GET @POST @Produces(MediaType.APPLICATION_XML) @Consumes(MediaType.APPLICATION_XML) public MyHashMapObject post( MyHashMapObject anotherMap) { anotherMap.getMapProperty().put("e", "10"); anotherMap.getMapProperty().put("f", "11"); anotherMap.getMapProperty().put("g", "12"); return anotherMap; } } 

Sei pronto per andare ora. Il tuo cliente dovrebbe andare così:

  public class Test { public static void main(String[] args) { ClientConfig config = new DefaultClientConfig(); Client client = Client.create(config); WebResource service = client.resource(getBaseURI()); // Now do the MAP stuff MyHashMapObject map = new MyHashMapObject(); map.getMapProperty().put("a", "1"); map.getMapProperty().put("b", "2"); ClientResponse response = service.path("rest").path("hello2") .type(MediaType.APPLICATION_XML) .accept(MediaType.APPLICATION_XML) .post(ClientResponse.class, map); Map myMap = response.getEntity(MyHashMapObject.class).getMapProperty(); for(Map.Entry entry : myMap.entrySet()) System.out.format("Key: %s, Value: %s\n", entry.getKey(), entry.getValue()); } private static URI getBaseURI() { return UriBuilder.fromUri( "http://localhost:8080/org.nowaq.jersey.first").build(); } } 

Ora puoi facilmente passare HashMap al tuo servizio REST. Puoi anche rendere l’implementazione un po ‘più generica. Spero che questo ti aiuti.

invia Mappa come corpo della richiesta POST

 @POST @Produces("application/json") @Consumes("application/json") @Path("/sendUser") public Response sendUser(Map usersMap) { String name = usersMap.get("Name"); // first check for existing key String family = usersMap.get("Family"); String phone = usersMap.get("Phone"); String mobile = usersMap.get("Mobile"); return Response.ok("Get user attributes successfully !").build(); } 

ottenere la risposta della mappa dal POST

 @POST @Produces("application/json") @Consumes("application/json") @Path("/getUser") public Response getUser(String searchInputJsonString) { Map usersMap = new HashMap<>(); usersMap.put("Name","Johm"); usersMap.put("Family","WRKlein"); usersMap.put("Phone","87540255"); usersMap.put("Mobile", "112458033"); return Response.ok(usersMap).build(); } 

È ansible utilizzare JSON.stringify (myMap) in javascript e quindi passare la mappa con stringhe come parametro del modulo.

In java, si analizza la stringa in una mappa come questa:

  @Path("doStuff") @POST @Produces(MediaType.APPLICATION_JSON) public void doStuff(@FormParam("mapAsJson") String mapAsJson) throws JsonParseException, JsonMappingException, IOException { @SuppressWarnings("unchecked") HashMap mapFromJson = (HashMap)new ObjectMapper().readValue(mapAsJson, HashMap.class); //add your processing }