How to Serialize Map in Apache CXF

When developing CXF based web services, did you ever get “org.apache.cxf.interceptor.Fault: Marshalling Error: java.util.Map is not known to this context” error message? This is caused by JAXB, the default databinding used by CXF, unable to marshal/unmarshal Java Maps. The common solution is to provide CXF a customized XmlAdatper.  See the Example codes below:

Step#1:  Annotate the Map type in the web service interface.


import java.util.List;
import java.util.Map;

import javax.jws.WebService;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
@WebService
public interface OrderService {
@XmlJavaTypeAdapter(ClientOrderMapAdapter.class)
Map<String, List<Order>> getOrders();

void updateOrders(@XmlJavaTypeAdapter(ClientOrderMapAdapter.class) Map<String, List<Order>> orders);
}

Step#2: Implement the customized XmlAdapter. Basically the adapter (i.e. the ClientOrderMapAdapter ) is flattening the map into a list of newly defined elements (i.e. ClientOrderElement ) which hold both the key (i.e. the string ) and the value (i.e. the List<Order>) of the original map as their fields.


import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.xml.bind.annotation.adapters.XmlAdapter;

public class ClientOrderMapAdapter extends
XmlAdapter<ClientOrderMapAdapter.Data, Map<String, List<Order>>> {

@Override
public Map<String, List<Order>> unmarshal(Data data) throws Exception {
Map<String, List<Order>> map = new HashMap<>();
for (Data.ClientOrderElement element : data.getClientOrders()) {
map.put(element.getClient(), element.getOrders());
}
return map;
}

@Override
public Data marshal(Map<String, List<Order>> map) throws Exception {
Data data = new Data();
for (Entry<String, List<Order>> entry : map.entrySet()) {
data.addClientOrderElement(entry.getKey(), entry.getValue());
}
return data;
}

public static class Data {

private List<ClientOrderElement> clientOrdersList = new ArrayList<ClientOrderElement>();

public void addClientOrderElement(String client, List<Order> orders) {
ClientOrderElement element = new ClientOrderElement();
element.setClient(client);
element.setOrders(orders);
clientOrdersList.add(element);
}

public List<ClientOrderElement> getClientOrders() {
return clientOrdersList;
}

public void setClientAndOrders(List<ClientOrderElement> list) {
this.clientOrdersList = list;
}

public static class ClientOrderElement {

private String client;
private List<Order> orders;

public String getClient() {
return client;
}

public void setClient(String client) {
this.client = client;
}

public List<Order> getOrders() {
return orders;
}

public void setOrders(List<Order> orders) {
this.orders = orders;
}
}
}
}

Advertisements
This entry was posted in Java, Programming and tagged , , , , , , , . Bookmark the permalink.

One Response to How to Serialize Map in Apache CXF

  1. Ahmed says:

    Thanks a lot. That helped me.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s