Apache CXF实战之三 Map门类绑定
Apache CXF实战之三Map类型绑定在CXF中,如果Web Service返回类型是Map的时候,比如方法签名如下?[java] vie
Apache CXF实战之三 Map类型绑定
在CXF中,如果Web Service返回类型是Map的时候,比如方法签名如下
?
[java] view plaincopyprint?
- @WebMethod??@WebResult?Map<String,?User>?getUserMap();??
此时如果运行程序会得到类似下面的异常
[java] view plaincopyprint?
- ...??Caused?by:?com.sun.xml.bind.v2.runtime.IllegalAnnotationsException:?2?counts?of?IllegalAnnotationExceptions??
- java.util.Map?is?an?interface,?and?JAXB?can't?handle?interfaces.??????this?problem?is?related?to?the?following?location:??
- ????????at?java.util.Map??????????at?private?java.util.Map?com.googlecode.garbagecan.cxfstudy.type.sample2.jaxws_asm.GetUserMapResponse._return??
- ????????at?com.googlecode.garbagecan.cxfstudy.type.sample2.jaxws_asm.GetUserMapResponse??java.util.Map?does?not?have?a?no-arg?default?constructor.??
- ????this?problem?is?related?to?the?following?location:??????????at?java.util.Map??
- ????????at?private?java.util.Map?com.googlecode.garbagecan.cxfstudy.type.sample2.jaxws_asm.GetUserMapResponse._return??????????at?com.googlecode.garbagecan.cxfstudy.type.sample2.jaxws_asm.GetUserMapResponse??
- ????at?com.sun.xml.bind.v2.runtime.IllegalAnnotationsException$Builder.check(IllegalAnnotationsException.java:102)??????at?com.sun.xml.bind.v2.runtime.JAXBContextImpl.getTypeInfoSet(JAXBContextImpl.java:472)??
- ????at?com.sun.xml.bind.v2.runtime.JAXBContextImpl.<init>(JAXBContextImpl.java:302)??????at?com.sun.xml.bind.v2.runtime.JAXBContextImpl$JAXBContextBuilder.build(JAXBContextImpl.java:1136)??
- ????at?com.sun.xml.bind.v2.ContextFactory.createContext(ContextFactory.java:154)??????at?com.sun.xml.bind.v2.ContextFactory.createContext(ContextFactory.java:121)??
- ????at?sun.reflect.NativeMethodAccessorImpl.invoke0(Native?Method)??????at?sun.reflect.NativeMethodAccessorImpl.invoke(Unknown?Source)??
- ????at?sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown?Source)??????at?java.lang.reflect.Method.invoke(Unknown?Source)??
- ????at?javax.xml.bind.ContextFinder.newInstance(Unknown?Source)??????at?javax.xml.bind.ContextFinder.newInstance(Unknown?Source)??
- ????at?javax.xml.bind.ContextFinder.find(Unknown?Source)??????at?javax.xml.bind.JAXBContext.newInstance(Unknown?Source)??
- ????at?org.apache.cxf.jaxb.JAXBDataBinding.createContext(JAXBDataBinding.java:560)??????at?org.apache.cxf.jaxb.JAXBDataBinding.createJAXBContextAndSchemas(JAXBDataBinding.java:500)??
- ????at?org.apache.cxf.jaxb.JAXBDataBinding.initialize(JAXBDataBinding.java:320)??????...?25?more??
- ...??
如果把方法签名改为如下时
?
?
[java] view plaincopyprint?
- @WebMethod??@WebResult?HashMap<String,?User>?getUserMap();??
运行程序会发现返回的结果总是一个空的HashMap。
?
?
对于以上问题,此时需要对Map类型做一下数据绑定或者说转换,看下面详细例子
1. 首先是一个实体类
?
[java] view plaincopyprint?
- package?com.googlecode.garbagecan.cxfstudy.type.sample2;????
- public?class?User?{??????private?String?id;??
- ????private?String?name;??????private?String?password;??
- ????public?String?getId()?{??????????return?id;??
- ????}??????public?void?setId(String?id)?{??
- ????????this.id?=?id;??????}??
- ????public?String?getName()?{??????????return?name;??
- ????}??????public?void?setName(String?name)?{??
- ????????this.name?=?name;??????}??
- ????public?String?getPassword()?{??????????return?password;??
- ????}??????public?void?setPassword(String?password)?{??
- ????????this.password?=?password;??????}??
- }??
2. 对Map类型做转换的类和适配器类
?
?
[java] view plaincopyprint?
- package?com.googlecode.garbagecan.cxfstudy.type.sample2;????
- import?java.util.HashMap;??import?java.util.Map;??
- ??import?javax.xml.bind.annotation.adapters.XmlAdapter;??
- ??public?class?MapAdapter?extends?XmlAdapter<MapConvertor,?Map<String,?Object>>?{??
- ??????@Override??
- ????public?MapConvertor?marshal(Map<String,?Object>?map)?throws?Exception?{??????????MapConvertor?convertor?=?new?MapConvertor();??
- ????????for?(Map.Entry<String,?Object>?entry?:?map.entrySet())?{??????????????MapConvertor.MapEntry?e?=?new?MapConvertor.MapEntry(entry);??
- ????????????convertor.addEntry(e);??????????}??
- ????????return?convertor;??????}??
- ??????@Override??
- ????public?Map<String,?Object>?unmarshal(MapConvertor?map)?throws?Exception?{??????????Map<String,?Object>?result?=?new?HashMap<String,?Object>();??
- ????????for?(MapConvertor.MapEntry?e?:?map.getEntries())?{??????????????result.put(e.getKey(),?e.getValue());??
- ????????}??????????return?result;??
- ????}??}??
- ??package?com.googlecode.garbagecan.cxfstudy.type.sample2;??
- ??import?java.util.ArrayList;??
- import?java.util.List;??import?java.util.Map;??
- ??import?javax.xml.bind.annotation.XmlAccessType;??
- import?javax.xml.bind.annotation.XmlAccessorType;??import?javax.xml.bind.annotation.XmlType;??
- ??@XmlType(name?=?"MapConvertor")??
- @XmlAccessorType(XmlAccessType.FIELD)??public?class?MapConvertor?{??
- ????private?List<MapEntry>?entries?=?new?ArrayList<MapEntry>();????
- ????public?void?addEntry(MapEntry?entry)?{??????????entries.add(entry);??
- ????}????
- ????public?List<MapEntry>?getEntries()?{??????????return?entries;??
- ????}????????
- ????public?static?class?MapEntry?{????
- ????????private?String?key;????
- ????????private?Object?value;????????????
- ????????public?MapEntry()?{??????????????super();??
- ????????}????
- ????????public?MapEntry(Map.Entry<String,?Object>?entry)?{??????????????super();??
- ????????????this.key?=?entry.getKey();??????????????this.value?=?entry.getValue();??
- ????????}????
- ????????public?MapEntry(String?key,?Object?value)?{??????????????super();??
- ????????????this.key?=?key;??????????????this.value?=?value;??
- ????????}????
- ????????public?String?getKey()?{??????????????return?key;??
- ????????}????
- ????????public?void?setKey(String?key)?{??????????????this.key?=?key;??
- ????????}????
- ????????public?Object?getValue()?{??????????????return?value;??
- ????????}????
- ????????public?void?setValue(Object?value)?{??????????????this.value?=?value;??
- ????????}??????}??
- }??
3. 下面是WebService接口类,注意其中的@XmlJavaTypeAdapter注解部分
?
?
[java] view plaincopyprint?
- package?com.googlecode.garbagecan.cxfstudy.type.sample2;????
- import?java.util.List;??import?java.util.Map;??
- ??import?javax.jws.WebMethod;??
- import?javax.jws.WebResult;??import?javax.jws.WebService;??
- import?javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;????
- @WebService??public?interface?UserService?{??
- ??????@WebMethod??
- ????@WebResult?List<User>?getUserList();????
- ????@WebMethod??????@XmlJavaTypeAdapter(MapAdapter.class)??
- ????@WebResult?Map<String,?User>?getUserMap();??}??
4. WebService接口实现类
?
?
[java] view plaincopyprint?
- package?com.googlecode.garbagecan.cxfstudy.type.sample2;????
- import?java.util.ArrayList;??import?java.util.LinkedHashMap;??
- import?java.util.List;??import?java.util.Map;??
- ??public?class?UserServiceImpl?implements?UserService?{??
- ??????public?List<User>?getUserList()?{??
- ????????List<User>?userList?=?new?ArrayList<User>();??????????for?(int?i?=?0;?i?<?10;?i++)?{??
- ????????????User?user?=?new?User();??????????????user.setId(""?+?i);??
- ????????????user.setName("user_"?+?i);??????????????user.setPassword("password_"?+?i);??
- ????????????userList.add(user);??????????}??
- ????????return?userList;??????}??
- ??????public?Map<String,?User>?getUserMap()?{??
- ????????Map<String,?User>?userMap?=?new?LinkedHashMap<String,?User>();??????????for?(int?i?=?0;?i?<?10;?i++)?{??
- ????????????User?user?=?new?User();??????????????user.setId(""?+?i);??
- ????????????user.setName("user_"?+?i);??????????????user.setPassword("password_"?+?i);??
- ????????????userMap.put(user.getId(),?user);??????????}??
- ????????return?userMap;??????}??
- }??
5. 最后是一个单元测试类
?
?
[java] view plaincopyprint?
- package?com.googlecode.garbagecan.cxfstudy.type.sample2;????
- import?java.util.List;??import?java.util.Map;??
- ??import?javax.xml.ws.Endpoint;??
- ??import?org.apache.cxf.jaxws.JaxWsProxyFactoryBean;??
- import?org.junit.After;??import?org.junit.Assert;??
- import?org.junit.Before;??import?org.junit.BeforeClass;??
- import?org.junit.Test;????
- public?class?UserServiceTest?{????
- ????private?static?final?String?address?=?"http://localhost:9000/ws/type/sample2/userService";????????
- ????private?UserService?userService;????????
- ????@BeforeClass??????public?static?void?setUpBeforeClass()?throws?Exception?{??
- ????????Endpoint.publish(address,?new?UserServiceImpl());??????}??
- ??????????@Before??
- ????public?void?setUp()?throws?Exception?{??????????JaxWsProxyFactoryBean?factoryBean?=?new?JaxWsProxyFactoryBean();??
- ????????factoryBean.setAddress(address);??????????factoryBean.setServiceClass(UserService.class);??
- ????????Object?obj?=?factoryBean.create();??????????userService?=?(UserService)obj;??
- ????}????
- ????@After??????public?void?tearDown()?throws?Exception?{??
- ????????userService?=?null;??????}??
- ??????@Test??
- ????public?void?testGetUserList()?{??????????Assert.assertNotNull(userService);??
- ????????List<User>?users?=?userService.getUserList();??????????Assert.assertNotNull(users);??
- ????????Assert.assertEquals(10,?users.size());??????}??
- ??????@Test??
- ????public?void?testGetUserMap()?{??????????Assert.assertNotNull(userService);??
- ????????Map<String,?User>?users?=?userService.getUserMap();??????????Assert.assertNotNull(users);??
- ????????Assert.assertEquals(10,?users.size());??????}??
- ??}??
6. 运行单元测试类验证上面的实现。