Просто чтобы немного прояснить ситуацию.MultivaluedMap<String, String>
предназначен для получения общей карты параметров формы, например, параметров, переданных вашему сервису через HTTP-запрос POST.Предполагается, что он будет использоваться следующим образом:
@POST
@Consumes("application/x-www-form-urlencoded")
public void post(MultivaluedMap<String, String> formParams) {
// Store the message
}
Однако, когда вашему клиентскому приложению необходимо предоставить REST-сервису какие-либо данные (в вашем случае HashMap
, содержащий, я полагаю, много важныхинформация) он сначала сериализует его в XML, а затем отправляет в службу, которая затем десериализует и использует его.К сожалению, Джерси не может автоматически маршалировать / unmmarshal HashMap
s, поэтому, если вы просто указали параметр HashMap
в своем методе newProj
, вы получите исключение.
Итак, как отправить HashMap наваш сервис?Ну, ключом является JAXB @XmlRootElement
и пользовательский XmlAdapter
: -)
Сначала вам нужно написать свою собственную обертку для карты.Оболочка будет помечена @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;
}
}
Затем вам нужно определить элементы карты "JAXB enabled":
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;
}
}
И в конце определить свой пользовательский XmlAdapter:
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;
}
}
Как только все это будет на месте (оно должно использоваться вашим сервисом и клиентом, поэтому положите его в какую-нибудь осколок), вы можете определить свой сервис следующим образом:
@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;
}
}
Теперь все готово.Ваш клиент должен выглядеть следующим образом:
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();
}
}
Теперь вы можете легко передать свой HashMap<String, String>
в службу REST.Вы также можете сделать реализацию более общей.Надеюсь, это поможет.