[ 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