[
https://issues.apache.org/jira/browse/CXF-4534?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Vassilis Virvilis updated CXF-4534:
-----------------------------------
Description:
We have recently upgraded to 2.6.2 and revisit our test suite. Looks like all
bugs submitted by use have been fixed. Very impressive, thanks a lot.
In our test suite there is a bug that has not been submitted in JIRA. A
discussion about that bug can be found at
http://comments.gmane.org/gmane.comp.apache.cxf.user/12388
I decided to submit this bug anyway for documentation purposes.
The problem:
------------
The problem is when the interface declares a SortedMap as an argument or as a
returned value. Here is the relevant snippets.
Interface
---------
// fail -- throws exception in the server
public boolean testSortedMapArgument(SortedMap<Integer, Integer> map);
// fail -- puts data into a hashmap instead of a SortedMap
public SortedMap<Integer, Integer> testSortedMapResult();
// fail -- puts data into a hashmap instead of a SortedMap
public Map<String, SortedMap<Integer, Integer>>
testDirectComplexTreeMapResult();
Implementation
--------------
@Override
public boolean testSortedMapArgument(SortedMap<Integer, Integer> map) {
final Class map_class = map.getClass();
final Collection<Class> klasses = Arrays.asList(map_class.getClasses());
log.info(String.format("Classes of %s are %s", map_class, klasses));
return klasses.contains(SortedMap.class);
}
@Override
public SortedMap<Integer, Integer> testSortedMapResult() {
final SortedMap<Integer, Integer> result = new TreeMap<Integer,
Integer>();
result.put(1, 3);
result.put(0, 2);
return result;
}
@Override
public Map<String, SortedMap<Integer, Integer>>
testDirectComplexTreeMapResult() {
final Map<String, SortedMap<Integer, Integer>> result = new
HashMap<String, SortedMap<Integer, Integer>>();
final TreeMap<Integer, Integer> map1 = new TreeMap<Integer, Integer>();
map1.put(1, 3);
map1.put(0, 2);
result.put("key1", map1);
return result;
}
Test Client:
------------
@Test
public void testSortedMapArgument() {
final SortedMap<Integer, Integer> map = new TreeMap<Integer, Integer>();
map.put(1, 3);
map.put(0, 2);
Assert.assertTrue(TestServiceFactory.getService()
.testSortedMapArgument(map));
}
@Test
public void testSortedMapResult() {
final Class map_class = ((Object) TestServiceFactory.getService()
.testDirectComplexTreeMapResult()).getClass();
final Collection<Class> klasses = Arrays.asList(map_class.getClasses());
log.info(String.format("Classes of %s are %s", map_class, klasses));
Assert.assertTrue(klasses.contains(SortedMap.class));
}
@Test
public void testDirectComplexTreeMapResult() {
final Class map_class = ((Object) TestServiceFactory.getService()
.testDirectComplexTreeMapResult().get("key1")).getClass();
final Collection<Class> klasses = Arrays.asList(map_class.getClasses());
log.info(String.format("Classes of %s are %s", map_class, klasses));
Assert.assertTrue(klasses.contains(SortedMap.class));
}
The result:
-----------
In cases 2 and 3 I get a hashmap instead of a SortedMap. This is very dangerous
since it changes program semantics in a very subtle way.
In case 1 I get an exception. Here is the server side part:
WARNING: Application
{http://iface/}TestInterface#{http://iface/}testSortedMapArgument has thrown
exception, unwinding now
org.apache.cxf.interceptor.Fault: argument type mismatch while invoking public
abstract boolean iface.TestInterface.testSortedMapArgument(java.util.SortedMap)
with params [{0=2, 1=3}].
at
org.apache.cxf.service.invoker.AbstractInvoker.createFault(AbstractInvoker.java:166)
at
org.apache.cxf.service.invoker.AbstractInvoker.invoke(AbstractInvoker.java:140)
at
org.apache.cxf.service.invoker.AbstractInvoker.invoke(AbstractInvoker.java:75)
at
org.apache.cxf.interceptor.ServiceInvokerInterceptor$1.run(ServiceInvokerInterceptor.java:58)
at
java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)
at java.util.concurrent.FutureTask.run(FutureTask.java:166)
at
org.apache.cxf.workqueue.SynchronousExecutor.execute(SynchronousExecutor.java:37)
at
org.apache.cxf.interceptor.ServiceInvokerInterceptor.handleMessage(ServiceInvokerInterceptor.java:107)
at
org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:262)
at
org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:121)
at
org.apache.cxf.transport.http.AbstractHTTPDestination.invoke(AbstractHTTPDestination.java:211)
at
org.apache.cxf.transport.servlet.ServletController.invokeDestination(ServletController.java:213)
at
org.apache.cxf.transport.servlet.ServletController.invoke(ServletController.java:193)
at
org.apache.cxf.transport.servlet.CXFNonSpringServlet.invoke(CXFNonSpringServlet.java:130)
at
org.apache.cxf.transport.servlet.AbstractHTTPServlet.handleRequest(AbstractHTTPServlet.java:221)
at
org.apache.cxf.transport.servlet.AbstractHTTPServlet.doPost(AbstractHTTPServlet.java:141)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:641)
at
org.apache.cxf.transport.servlet.AbstractHTTPServlet.service(AbstractHTTPServlet.java:197)
at
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
at
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at
org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:225)
at
org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
at
org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
at
org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168)
at
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)
at
org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:927)
at
org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
at
org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1001)
at
org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:579)
at
org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:312)
at
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
at
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
at java.lang.Thread.run(Thread.java:722)
Caused by: java.lang.IllegalArgumentException: argument type mismatch
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at
org.apache.cxf.service.invoker.AbstractInvoker.performInvocation(AbstractInvoker.java:180)
at
org.apache.cxf.service.invoker.AbstractInvoker.invoke(AbstractInvoker.java:96)
... 33 more
Expected result:
----------------
To safely transfer a SortedMap both ways.
I would understand if due to WSDL constraints reliably transferring a
sortedMap is not possible. What it would be nice is at least during the deploy
time an error / warning is issued stating that fact.
Right now we are getting incorrect results in a silent way or a the best case
an exception at run time.
was:
We have recently upgraded to 2.6.2 and revisit our test suite. Looks like all
bugs submitted by use have been fixed. Very impressive, thanks a lot.
In our test suite there is a bug that has not been submitted in JIRA. A
discussion about that bug can be found at
http://comments.gmane.org/gmane.comp.apache.cxf.user/12388
I decided to submit this bug anyway for documentation purposes.
The problem:
------------
The problem is when the interface declares a SortedMap as an argument or as a
returned value. Here is the relevant snippets.
Interface
---------
// fail -- throws exception in the server
public boolean testSortedMapArgument(SortedMap<Integer, Integer> map);
// fail -- puts data into a hashmap instead of a SortedMap
public SortedMap<Integer, Integer> testSortedMapResult();
// fail -- puts data into a hashmap instead of a SortedMap
public Map<String, SortedMap<Integer, Integer>>
testDirectComplexTreeMapResult();
Implementation
--------------
@Override
public boolean testSortedMapArgument(SortedMap<Integer, Integer> map) {
final Class map_class = map.getClass();
final Collection<Class> klasses = Arrays.asList(map_class.getClasses());
log.info(String.format("Classes of %s are %s", map_class, klasses));
return klasses.contains(SortedMap.class);
}
@Override
public SortedMap<Integer, Integer> testSortedMapResult() {
final SortedMap<Integer, Integer> result = new TreeMap<Integer,
Integer>();
result.put(1, 3);
result.put(0, 2);
return result;
}
@Override
public Map<String, SortedMap<Integer, Integer>>
testDirectComplexTreeMapResult() {
final Map<String, SortedMap<Integer, Integer>> result = new
HashMap<String, SortedMap<Integer, Integer>>();
final TreeMap<Integer, Integer> map1 = new TreeMap<Integer, Integer>();
map1.put(1, 3);
map1.put(0, 2);
result.put("key1", map1);
return result;
}
Test Client:
------------
@Test
public void testSortedMapArgument() {
final SortedMap<Integer, Integer> map = new TreeMap<Integer, Integer>();
map.put(1, 3);
map.put(0, 2);
Assert.assertTrue(TestServiceFactory.getService()
.testSortedMapArgument(map));
}
@Test
public void testSortedMapResult() {
final Class map_class = ((Object) TestServiceFactory.getService()
.testDirectComplexTreeMapResult()).getClass();
final Collection<Class> klasses = Arrays.asList(map_class.getClasses());
log.info(String.format("Classes of %s are %s", map_class, klasses));
Assert.assertTrue(klasses.contains(SortedMap.class));
}
@Test
public void testDirectComplexTreeMapResult() {
final Class map_class = ((Object) TestServiceFactory.getService()
.testDirectComplexTreeMapResult().get("key1")).getClass();
final Collection<Class> klasses = Arrays.asList(map_class.getClasses());
log.info(String.format("Classes of %s are %s", map_class, klasses));
Assert.assertTrue(klasses.contains(SortedMap.class));
}
The result:
-----------
In cases 2 and 3 I get a hashmap instead of a SortedMap. This is very dangerous
since it changes program semantics in a very subtle way.
In case 1 I get an exception. Here is the server side part:
@Test
public void testSortedMapArgument() {
final SortedMap<Integer, Integer> map = new TreeMap<Integer, Integer>();
map.put(1, 3);
map.put(0, 2);
Assert.assertTrue(TestServiceFactory.getService()
.testSortedMapArgument(map));
}
@Test
public void testSortedMapResult() {
final Class map_class = ((Object) TestServiceFactory.getService()
.testDirectComplexTreeMapResult()).getClass();
final Collection<Class> klasses = Arrays.asList(map_class.getClasses());
log.info(String.format("Classes of %s are %s", map_class, klasses));
Assert.assertTrue(klasses.contains(SortedMap.class));
}
@Test
public void testDirectComplexTreeMapResult() {
final Class map_class = ((Object) TestServiceFactory.getService()
.testDirectComplexTreeMapResult().get("key1")).getClass();
final Collection<Class> klasses = Arrays.asList(map_class.getClasses());
log.info(String.format("Classes of %s are %s", map_class, klasses));
Assert.assertTrue(klasses.contains(SortedMap.class));
}
Expected result:
----------------
To safely transfer a SortedMap both ways.
I would understand if due to WSDL constraints reliably transferring a
sortedMap is not possible. What it would be nice is at least during the deploy
time an error / warning is issued stating that fact.
Right now we are getting incorrect results in a silent way or a the best case
an exception at run time.
> SortedMap is returned as HashMap
> --------------------------------
>
> Key: CXF-4534
> URL: https://issues.apache.org/jira/browse/CXF-4534
> Project: CXF
> Issue Type: Bug
> Components: Aegis Databinding
> Affects Versions: 2.6.2
> Environment: debian wheezy/testing, unstable
> Reporter: Vassilis Virvilis
>
> We have recently upgraded to 2.6.2 and revisit our test suite. Looks like all
> bugs submitted by use have been fixed. Very impressive, thanks a lot.
> In our test suite there is a bug that has not been submitted in JIRA. A
> discussion about that bug can be found at
> http://comments.gmane.org/gmane.comp.apache.cxf.user/12388
> I decided to submit this bug anyway for documentation purposes.
> The problem:
> ------------
> The problem is when the interface declares a SortedMap as an argument or as a
> returned value. Here is the relevant snippets.
> Interface
> ---------
> // fail -- throws exception in the server
> public boolean testSortedMapArgument(SortedMap<Integer, Integer> map);
> // fail -- puts data into a hashmap instead of a SortedMap
> public SortedMap<Integer, Integer> testSortedMapResult();
> // fail -- puts data into a hashmap instead of a SortedMap
> public Map<String, SortedMap<Integer, Integer>>
> testDirectComplexTreeMapResult();
> Implementation
> --------------
> @Override
> public boolean testSortedMapArgument(SortedMap<Integer, Integer> map) {
> final Class map_class = map.getClass();
> final Collection<Class> klasses =
> Arrays.asList(map_class.getClasses());
> log.info(String.format("Classes of %s are %s", map_class, klasses));
> return klasses.contains(SortedMap.class);
> }
> @Override
> public SortedMap<Integer, Integer> testSortedMapResult() {
> final SortedMap<Integer, Integer> result = new TreeMap<Integer,
> Integer>();
> result.put(1, 3);
> result.put(0, 2);
> return result;
> }
> @Override
> public Map<String, SortedMap<Integer, Integer>>
> testDirectComplexTreeMapResult() {
> final Map<String, SortedMap<Integer, Integer>> result = new
> HashMap<String, SortedMap<Integer, Integer>>();
> final TreeMap<Integer, Integer> map1 = new TreeMap<Integer,
> Integer>();
> map1.put(1, 3);
> map1.put(0, 2);
> result.put("key1", map1);
> return result;
> }
> Test Client:
> ------------
> @Test
> public void testSortedMapArgument() {
> final SortedMap<Integer, Integer> map = new TreeMap<Integer,
> Integer>();
> map.put(1, 3);
> map.put(0, 2);
> Assert.assertTrue(TestServiceFactory.getService()
> .testSortedMapArgument(map));
> }
> @Test
> public void testSortedMapResult() {
> final Class map_class = ((Object) TestServiceFactory.getService()
> .testDirectComplexTreeMapResult()).getClass();
> final Collection<Class> klasses =
> Arrays.asList(map_class.getClasses());
> log.info(String.format("Classes of %s are %s", map_class, klasses));
> Assert.assertTrue(klasses.contains(SortedMap.class));
> }
> @Test
> public void testDirectComplexTreeMapResult() {
> final Class map_class = ((Object) TestServiceFactory.getService()
> .testDirectComplexTreeMapResult().get("key1")).getClass();
> final Collection<Class> klasses =
> Arrays.asList(map_class.getClasses());
> log.info(String.format("Classes of %s are %s", map_class, klasses));
> Assert.assertTrue(klasses.contains(SortedMap.class));
> }
> The result:
> -----------
> In cases 2 and 3 I get a hashmap instead of a SortedMap. This is very
> dangerous since it changes program semantics in a very subtle way.
> In case 1 I get an exception. Here is the server side part:
> WARNING: Application
> {http://iface/}TestInterface#{http://iface/}testSortedMapArgument has thrown
> exception, unwinding now
> org.apache.cxf.interceptor.Fault: argument type mismatch while invoking
> public abstract boolean
> iface.TestInterface.testSortedMapArgument(java.util.SortedMap) with params
> [{0=2, 1=3}].
> at
> org.apache.cxf.service.invoker.AbstractInvoker.createFault(AbstractInvoker.java:166)
> at
> org.apache.cxf.service.invoker.AbstractInvoker.invoke(AbstractInvoker.java:140)
> at
> org.apache.cxf.service.invoker.AbstractInvoker.invoke(AbstractInvoker.java:75)
> at
> org.apache.cxf.interceptor.ServiceInvokerInterceptor$1.run(ServiceInvokerInterceptor.java:58)
> at
> java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
> at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)
> at java.util.concurrent.FutureTask.run(FutureTask.java:166)
> at
> org.apache.cxf.workqueue.SynchronousExecutor.execute(SynchronousExecutor.java:37)
> at
> org.apache.cxf.interceptor.ServiceInvokerInterceptor.handleMessage(ServiceInvokerInterceptor.java:107)
> at
> org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:262)
> at
> org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:121)
> at
> org.apache.cxf.transport.http.AbstractHTTPDestination.invoke(AbstractHTTPDestination.java:211)
> at
> org.apache.cxf.transport.servlet.ServletController.invokeDestination(ServletController.java:213)
> at
> org.apache.cxf.transport.servlet.ServletController.invoke(ServletController.java:193)
> at
> org.apache.cxf.transport.servlet.CXFNonSpringServlet.invoke(CXFNonSpringServlet.java:130)
> at
> org.apache.cxf.transport.servlet.AbstractHTTPServlet.handleRequest(AbstractHTTPServlet.java:221)
> at
> org.apache.cxf.transport.servlet.AbstractHTTPServlet.doPost(AbstractHTTPServlet.java:141)
> at javax.servlet.http.HttpServlet.service(HttpServlet.java:641)
> at
> org.apache.cxf.transport.servlet.AbstractHTTPServlet.service(AbstractHTTPServlet.java:197)
> at
> org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
> at
> org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
> at
> org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:225)
> at
> org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
> at
> org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
> at
> org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168)
> at
> org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)
> at
> org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:927)
> at
> org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
> at
> org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
> at
> org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1001)
> at
> org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:579)
> at
> org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:312)
> at
> java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
> at
> java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
> at java.lang.Thread.run(Thread.java:722)
> Caused by: java.lang.IllegalArgumentException: argument type mismatch
> at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
> at
> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
> at
> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
> at java.lang.reflect.Method.invoke(Method.java:601)
> at
> org.apache.cxf.service.invoker.AbstractInvoker.performInvocation(AbstractInvoker.java:180)
> at
> org.apache.cxf.service.invoker.AbstractInvoker.invoke(AbstractInvoker.java:96)
> ... 33 more
> Expected result:
> ----------------
> To safely transfer a SortedMap both ways.
> I would understand if due to WSDL constraints reliably transferring a
> sortedMap is not possible. What it would be nice is at least during the
> deploy time an error / warning is issued stating that fact.
> Right now we are getting incorrect results in a silent way or a the best case
> an exception at run time.
--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators
For more information on JIRA, see: http://www.atlassian.com/software/jira