Repository: apache/dubbo (Java)
Date: 2020-02-24 09:39:20+00:00
Task type: Bug Fix

Issue:
PojoUtils realize type convert not support localdatetime,localdate,localtime
- [x] I have searched the [issues](https://github.com/apache/dubbo/issues) of this repository and believe that this is not a duplicate.
- [x] I have checked the [FAQ](https://github.com/apache/dubbo/blob/master/FAQ.md) of this repository and believe that this is not a duplicate.

### Environment

* Dubbo version: 2.6.5
* Operating System version: macos10.14
* Java version: 1.8

### Steps to reproduce this issue

1. String convert to java.time.LocalDateTime
2. String convert to java.time.LocalDate
3. String convert to java.time.LocalTime


### Expected Result

The Convert is successful and you can get the object of the converted type.

### Actual Result

Conversion failed.

PojoUtils class invoke realize0 ,then invoke method of  CompatibleTypeUtils class. I think it's missing of localdatetime 。

If there is an exception, please attach the exception trace:

```
java.io.IOException: Read response data failed.
java.lang.RuntimeException: Failed to set pojo MonitorIdlResp property execTime value 2018-01-29 12:00:00(class java.lang.String), cause: argument type mismatch
	at com.alibaba.dubbo.common.utils.PojoUtils.realize0(PojoUtils.java:480)
	at com.alibaba.dubbo.common.utils.PojoUtils.realize0(PojoUtils.java:391)
	at com.alibaba.dubbo.common.utils.PojoUtils.realize(PojoUtils.java:216)
	at com.alibaba.dubbo.common.serialize.support.json.FastJsonObjectParser.parseObjectTwoType(FastJsonObjectParser.java:30)
	at com.alibaba.dubbo.common.serialize.support.json.FastJsonObjectParser.parseResultObject(FastJsonObjectParser.java:38)
	at com.alibaba.dubbo.rpc.protocol.dubbo.DecodeableRpcResult.decode(DecodeableRpcResult.java:173)
	at com.alibaba.dubbo.rpc.protocol.dubbo.DecodeableRpcResult.decode(DecodeableRpcResult.java:87)
	at com.alibaba.dubbo.rpc.protocol.dubbo.DubboCodec.decodeResponseDataInternal(DubboCodec.java:212)
	at com.alibaba.dubbo.rpc.protocol.dubbo.DubboCodec.decodeResponseData(DubboCodec.java:251)
	at com.alibaba.dubbo.remoting.exchange.codec.ExchangeCodec.decodeBody(ExchangeCodec.java:204)
	at com.alibaba.dubbo.remoting.exchange.codec.ExchangeCodec.decode(ExchangeCodec.java:158)
	at com.alibaba.dubbo.remoting.exchange.codec.ExchangeCodec.decode(ExchangeCodec.java:108)
	at com.alibaba.dubbo.rpc.protocol.dubbo.DubboCountCodec.decode(DubboCountCodec.java:53)
	at com.alibaba.dubbo.remoting.transport.netty.NettyCodecAdapter$InternalDecoder.messageReceived(NettyCodecAdapter.java:135)
	at org.jboss.netty.channel.SimpleChannelUpstreamHandler.handleUpstream(SimpleChannelUpstreamHandler.java:70)
	at org.jboss.netty.channel.DefaultChannelPipeline.sendUpstream(DefaultChannelPipeline.java:564)
	at org.jboss.netty.channel.DefaultChannelPipeline.sendUpstream(DefaultChannelPipeline.java:559)
	at org.jboss.netty.channel.Channels.fireMessageReceived(Channels.java:268)
	at org.jboss.netty.channel.Channels.fireMessageReceived(Channels.java:255)
	at org.jboss.netty.channel.socket.nio.NioWorker.read(NioWorker.java:88)
	at org.jboss.netty.channel.socket.nio.AbstractNioWorker.process(AbstractNioWorker.java:109)
	at org.jboss.netty.channel.socket.nio.AbstractNioSelector.run(AbstractNioSelector.java:312)
	at org.jboss.netty.channel.socket.nio.AbstractNioWorker.run(AbstractNioWorker.java:90)
	at org.jboss.netty.channel.socket.nio.NioWorker.run(NioWorker.java:178)
	at org.jboss.netty.util.ThreadRenamingRunnable.run(ThreadRenamingRunnable.java:108)
	at org.jboss.netty.util.internal.DeadLockProofWorker$1.run(DeadLockProofWorker.java:42)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.IllegalArgumentException: argument type mismatch
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at com.alibaba.dubbo.common.utils.PojoUtils.realize0(PojoUtils.java:478)
	... 28 more

	at com.alibaba.dubbo.rpc.protocol.dubbo.DecodeableRpcResult.decode(DecodeableRpcResult.java:188)
	at com.alibaba.dubbo.rpc.protocol.dubbo.DecodeableRpcResult.decode(DecodeableRpcResult.java:87)
	at com.alibaba.dubbo.rpc.protocol.dubbo.DubboCodec.decodeResponseDataInternal(DubboCodec.java:212)
	at com.alibaba.dubbo.rpc.protocol.dubbo.DubboCodec.decodeResponseData(DubboCodec.java:251)
	at com.alibaba.dubbo.remoting.exchange.codec.ExchangeCodec.decodeBody(ExchangeCodec.java:204)
	at com.alibaba.dubbo.remoting.exchange.codec.ExchangeCodec.decode(ExchangeCodec.java:158)
	at com.alibaba.dubbo.remoting.exchange.codec.ExchangeCodec.decode(ExchangeCodec.java:108)
	at com.alibaba.dubbo.rpc.protocol.dubbo.DubboCountCodec.decode(DubboCountCodec.java:53)
	at com.alibaba.dubbo.remoting.transport.netty.NettyCodecAdapter$InternalDecoder.messageReceived(NettyCodecAdapter.java:135)
	at org.jboss.netty.channel.SimpleChannelUpstreamHandler.handleUpstream(SimpleChannelUpstreamHandler.java:70)
	at org.jboss.netty.channel.DefaultChannelPipeline.sendUpstream(DefaultChannelPipeline.java:564)
	at org.jboss.netty.channel.DefaultChannelPipeline.sendUpstream(DefaultChannelPipeline.java:559)
	at org.jboss.netty.channel.Channels.fireMessageReceived(Channels.java:268)
	at org.jboss.netty.channel.Channels.fireMessageReceived(Channels.java:255)
	at org.jboss.netty.channel.socket.nio.NioWorker.read(NioWorker.java:88)
	at org.jboss.netty.channel.socket.nio.AbstractNioWorker.process(AbstractNioWorker.java:109)
	at org.jboss.netty.channel.socket.nio.AbstractNioSelector.run(AbstractNioSelector.java:312)
	at org.jboss.netty.channel.socket.nio.AbstractNioWorker.run(AbstractNioWorker.java:90)
	at org.jboss.netty.channel.socket.nio.NioWorker.run(NioWorker.java:178)
	at org.jboss.netty.util.ThreadRenamingRunnable.run(ThreadRenamingRunnable.java:108)
	at org.jboss.netty.util.internal.DeadLockProofWorker$1.run(DeadLockProofWorker.java:42)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:748)

	at com.alibaba.dubbo.remoting.exchange.support.DefaultFuture.returnFromResponse(DefaultFuture.java:232)
	at com.alibaba.dubbo.remoting.exchange.support.DefaultFuture.get(DefaultFuture.java:141)
	at com.alibaba.dubbo.remoting.exchange.support.DefaultFuture.get(DefaultFuture.java:110)
	at com.alibaba.dubbo.rpc.protocol.dubbo.DubboInvoker.doInvoke(DubboInvoker.java:111)
	... 36 more
```



Issue discussion:
sounds like an issue that generic invocation doesn't support new type in Java8.
Yeah, Java8's new time type is not supported.Thanks for added this feature of milestone.
looking forward this feature too 🙏
这个有了吗对java8中的LocalDateTime的支持？
@complone Could you help to fix this issue ?

Solution patch:
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/CompatibleTypeUtils.java b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/CompatibleTypeUtils.java
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/CompatibleTypeUtils.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/CompatibleTypeUtils.java
@@ -21,6 +21,7 @@
 import java.math.BigInteger;
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
+import java.time.LocalDateTime;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Date;
@@ -110,6 +111,18 @@ public static Object compatibleTypeConvert(Object value, Class<?> type) {
                             + DATE_FORMAT + ", cause: " + e.getMessage(), e);
                 }
             }
+            if (type == java.time.LocalDateTime.class || type == java.time.LocalDate.class
+                    || type == java.time.LocalTime.class) {
+
+                LocalDateTime localDateTime = LocalDateTime.parse(string);
+                if (type == java.time.LocalDate.class) {
+                    return localDateTime.toLocalDate();
+                }
+                if (type == java.time.LocalTime.class) {
+                    return localDateTime.toLocalTime();
+                }
+                return localDateTime;
+            }
             if (type == Class.class) {
                 try {
                     return ReflectUtils.name2class(string);


Test patch:
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/CompatibleTypeUtilsTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/CompatibleTypeUtilsTest.java
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/CompatibleTypeUtilsTest.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/CompatibleTypeUtilsTest.java
@@ -21,6 +21,7 @@
 import java.math.BigDecimal;
 import java.math.BigInteger;
 import java.text.SimpleDateFormat;
+import java.time.format.DateTimeFormatter;
 import java.util.ArrayList;
 import java.util.Date;
 import java.util.HashSet;
@@ -77,6 +78,15 @@ public void testCompatibleTypeConvert() throws Exception {
             result = CompatibleTypeUtils.compatibleTypeConvert("2011-12-11 12:24:12", java.sql.Timestamp.class);
             assertEquals(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format((java.sql.Timestamp) result), "2011-12-11 12:24:12");
 
+            result = CompatibleTypeUtils.compatibleTypeConvert("2011-12-11T12:24:12.047", java.time.LocalDateTime.class);
+            assertEquals(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format((java.time.LocalDateTime) result), "2011-12-11 12:24:12");
+
+            result = CompatibleTypeUtils.compatibleTypeConvert("2011-12-11T12:24:12.047", java.time.LocalTime.class);
+            assertEquals(DateTimeFormatter.ofPattern("HH:mm:ss").format((java.time.LocalTime) result), "12:24:12");
+
+            result = CompatibleTypeUtils.compatibleTypeConvert("2011-12-11T12:24:12.047", java.time.LocalDate.class);
+            assertEquals(DateTimeFormatter.ofPattern("yyyy-MM-dd").format((java.time.LocalDate) result), "2011-12-11");
+
             result = CompatibleTypeUtils.compatibleTypeConvert("ab", char[].class);
             assertEquals(2, ((char[]) result).length);
             assertEquals('a', ((char[]) result)[0]);