Je veux envoyer un objet HashMap à une ressource ReST en tant que variable POST. J'ai utilisé la classe Form
pour envoyer l'objet. Le code client:
public static void main(String[] args)
{
ClientConfig config = new DefaultClientConfig();
Client client = Client.create(config);
WebResource service = client.resource(getBaseURI());
HashMap<String, String> hashmap = new HashMap<String, String>();
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<String, String> map = response.getEntity(MultivaluedMap.class);
System.out.println(map.get("response").get(0));
System.out.println(map.get("response2"));
}
La ressource REST est la suivante:
@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<String, String> newProj(@FormParam("data1") HashMap<String, String> postVarMap, @Context HttpServletResponse response)
{
System.out.println(postVarMap);
MultivaluedMap<String, String> 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;
}
}
J'obtiens l'exception suivante dans le journal 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 classes in the packages:
com.reflexis.nbe.jersey
Dec 7, 2011 3:38:40 PM com.Sun.jersey.api.core.ScanningResourceConfig logClasses
INFO: Root resource classes found:
class com.reflexis.nbe.jersey.FormResource
Dec 7, 2011 3:38:40 PM com.Sun.jersey.api.core.ScanningResourceConfig init
INFO: No provider classes 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 classes:
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)
Le code client que j'ai écrit est-il correct? Existe-t-il un autre moyen d'envoyer un objet HashMap en tant que variable POST?
Juste pour clarifier un peu les choses. Le MultivaluedMap<String, String>
est destiné à être utilisé pour obtenir une carte générale des paramètres de formulaire, par exemple paramètres soumis à votre service via POST requête HTTP. Il est censé être utilisé comme ceci:
@POST
@Consumes("application/x-www-form-urlencoded")
public void post(MultivaluedMap<String, String> formParams) {
// Store the message
}
Cependant, lorsque votre application cliente doit fournir à votre service REST une sorte de données (dans votre cas, un HashMap
contenant, je suppose, beaucoup d'informations importantes), il le sérialise). au format XML d'abord, puis envoyez-le au service qui le désérialisera et l'utilisera. Malheureusement, Jersey n'est pas en mesure de marshaler/dé-marrer automatiquement HashMap
s donc si vous venez de fournir le paramètre HashMap
dans votre newProj
, vous obtiendriez une exception.
Alors, comment envoyer un HashMap à votre service? Eh bien, la clé est le JAXB @XmlRootElement
et un XmlAdapter
:-) personnalisé
Vous devez d'abord écrire votre propre wrapper pour la carte. L'encapsuleur sera annoté avec @XmlRootElement
@XmlRootElement
public class MyHashMapObject<T, U> {
private Map<T, U> mapProperty;
public MyHashMapObject() {
mapProperty = new HashMap<T, U>();
}
@XmlJavaTypeAdapter(MapAdapter.class) // NOTE: Our custom XmlAdaper
public Map<T, U> getMapProperty() {
return mapProperty;
}
public void setMapProperty(Map<T, U> map) {
this.mapProperty = map;
}
}
Ensuite, vous devez définir vos éléments de carte "compatibles 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;
}
}
Et à la fin, définissez votre XmlAdapter personnalisé:
public class MapAdapter extends XmlAdapter<MapElement[], Map<String, String>> {
public MapElement[] marshal(Map<String, String> arg0) throws Exception {
MapElement[] mapElements = new MapElement[arg0.size()];
int i = 0;
for (Map.Entry<String, String> entry : arg0.entrySet())
mapElements[i++] = new MapElement(entry.getKey(), entry.getValue());
return mapElements;
}
public Map<String, String> unmarshal(MapElement[] arg0) throws Exception {
Map<String, String> r = new HashMap<String, String>();
for (MapElement mapelement : arg0)
r.put(mapelement.key, mapelement.value);
return r;
}
}
Une fois que vous avez tout cela en place (il doit être utilisé par votre service et le client, mettez-le dans un pot de tessons), vous pouvez définir votre service comme ceci:
@Path("/hello")
public class FormResource
{
//@GET
@POST
@Produces(MediaType.APPLICATION_XML)
@Consumes(MediaType.APPLICATION_XML)
public MyHashMapObject<String, String> post(
MyHashMapObject<String, String> anotherMap) {
anotherMap.getMapProperty().put("e", "10");
anotherMap.getMapProperty().put("f", "11");
anotherMap.getMapProperty().put("g", "12");
return anotherMap;
}
}
Vous êtes prêt à partir maintenant. Votre client devrait se présenter comme ceci:
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<String, String> map = new MyHashMapObject<String, String>();
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<String, String> myMap = response.getEntity(MyHashMapObject.class).getMapProperty();
for(Map.Entry<String, String> 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();
}
}
Maintenant, vous pouvez facilement passer votre HashMap<String, String>
à votre service REST. Vous pouvez également rendre l'implémentation un peu plus générique. J'espère que cela vous aidera.
Vous pouvez utiliser JSON.stringify (myMap) en javascript, et ainsi passer la carte stringyfied comme paramètre de formulaire.
En Java, vous analysez la chaîne dans une carte comme celle-ci:
@Path("doStuff")
@POST
@Produces(MediaType.APPLICATION_JSON)
public void doStuff(@FormParam("mapAsJson") String mapAsJson) throws JsonParseException, JsonMappingException, IOException {
@SuppressWarnings("unchecked")
HashMap<String,String> mapFromJson = (HashMap<String,String>)new ObjectMapper().readValue(mapAsJson, HashMap.class);
//add your processing
}
envoyer la carte en tant que POST corps de la demande
@POST
@Produces("application/json")
@Consumes("application/json")
@Path("/sendUser")
public Response sendUser(Map<String,String> 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();
}
obtenir une réponse cartographique de POST
@POST
@Produces("application/json")
@Consumes("application/json")
@Path("/getUser")
public Response getUser(String searchInputJsonString) {
Map<String,String> usersMap = new HashMap<>();
usersMap.put("Name","Johm");
usersMap.put("Family","W.R.Klein");
usersMap.put("Phone","87540255");
usersMap.put("Mobile", "112458033");
return Response.ok(usersMap).build();
}