[TD-5506]<hotfix>: fix NullPointerException in JDBC-RESTful (#7021)
* change jdbc version * [TD-5506]<fix>: throw SQLException in HttpClientPoolUtil
This commit is contained in:
parent
606119e3a5
commit
f734285282
|
@ -32,7 +32,7 @@ ELSEIF (TD_WINDOWS)
|
|||
#INSTALL(TARGETS taos RUNTIME DESTINATION driver)
|
||||
#INSTALL(TARGETS shell RUNTIME DESTINATION .)
|
||||
IF (TD_MVN_INSTALLED)
|
||||
INSTALL(FILES ${LIBRARY_OUTPUT_PATH}/taos-jdbcdriver-2.0.33-dist.jar DESTINATION connector/jdbc)
|
||||
INSTALL(FILES ${LIBRARY_OUTPUT_PATH}/taos-jdbcdriver-2.0.34-dist.jar DESTINATION connector/jdbc)
|
||||
ENDIF ()
|
||||
ELSEIF (TD_DARWIN)
|
||||
SET(TD_MAKE_INSTALL_SH "${TD_COMMUNITY_DIR}/packaging/tools/make_install.sh")
|
||||
|
|
|
@ -8,7 +8,7 @@ IF (TD_MVN_INSTALLED)
|
|||
ADD_CUSTOM_COMMAND(OUTPUT ${JDBC_CMD_NAME}
|
||||
POST_BUILD
|
||||
COMMAND mvn -Dmaven.test.skip=true install -f ${CMAKE_CURRENT_SOURCE_DIR}/pom.xml
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/target/taos-jdbcdriver-2.0.33-dist.jar ${LIBRARY_OUTPUT_PATH}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/target/taos-jdbcdriver-2.0.34-dist.jar ${LIBRARY_OUTPUT_PATH}
|
||||
COMMAND mvn -Dmaven.test.skip=true clean -f ${CMAKE_CURRENT_SOURCE_DIR}/pom.xml
|
||||
COMMENT "build jdbc driver")
|
||||
ADD_CUSTOM_TARGET(${JDBC_TARGET_NAME} ALL WORKING_DIRECTORY ${EXECUTABLE_OUTPUT_PATH} DEPENDS ${JDBC_CMD_NAME})
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
<groupId>com.taosdata.jdbc</groupId>
|
||||
<artifactId>taos-jdbcdriver</artifactId>
|
||||
<version>2.0.33</version>
|
||||
<version>2.0.34</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>JDBCDriver</name>
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.taosdata.jdbc</groupId>
|
||||
<artifactId>taos-jdbcdriver</artifactId>
|
||||
<version>2.0.33</version>
|
||||
<version>2.0.34</version>
|
||||
<packaging>jar</packaging>
|
||||
<name>JDBCDriver</name>
|
||||
<url>https://github.com/taosdata/TDengine/tree/master/src/connector/jdbc</url>
|
||||
|
|
|
@ -130,7 +130,7 @@ public abstract class TSDBConstants {
|
|||
case TSDBConstants.TSDB_DATA_TYPE_NCHAR:
|
||||
return Types.NCHAR;
|
||||
}
|
||||
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNKNOWN_TAOS_TYPE_IN_TDENGINE);
|
||||
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNKNOWN_TAOS_TYPE);
|
||||
}
|
||||
|
||||
public static String taosType2JdbcTypeName(int taosType) throws SQLException {
|
||||
|
@ -160,7 +160,7 @@ public abstract class TSDBConstants {
|
|||
case TSDBConstants.TSDB_DATA_TYPE_NCHAR:
|
||||
return "NCHAR";
|
||||
default:
|
||||
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNKNOWN_TAOS_TYPE_IN_TDENGINE);
|
||||
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNKNOWN_TAOS_TYPE);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -31,8 +31,8 @@ public class TSDBError {
|
|||
TSDBErrorMap.put(TSDBErrorNumbers.ERROR_URL_NOT_SET, "url is not set");
|
||||
TSDBErrorMap.put(TSDBErrorNumbers.ERROR_INVALID_SQL, "invalid sql");
|
||||
TSDBErrorMap.put(TSDBErrorNumbers.ERROR_NUMERIC_VALUE_OUT_OF_RANGE, "numeric value out of range");
|
||||
TSDBErrorMap.put(TSDBErrorNumbers.ERROR_UNKNOWN_TAOS_TYPE_IN_TDENGINE, "unknown taos type in tdengine");
|
||||
TSDBErrorMap.put(TSDBErrorNumbers.ERROR_UNKNOWN_TIMESTAMP_PERCISION, "unknown timestamp precision");
|
||||
TSDBErrorMap.put(TSDBErrorNumbers.ERROR_UNKNOWN_TAOS_TYPE, "unknown taos type in tdengine");
|
||||
TSDBErrorMap.put(TSDBErrorNumbers.ERROR_UNKNOWN_TIMESTAMP_PRECISION, "unknown timestamp precision");
|
||||
|
||||
TSDBErrorMap.put(TSDBErrorNumbers.ERROR_UNKNOWN, "unknown error");
|
||||
|
||||
|
|
|
@ -25,8 +25,10 @@ public class TSDBErrorNumbers {
|
|||
public static final int ERROR_URL_NOT_SET = 0x2312; // url is not set
|
||||
public static final int ERROR_INVALID_SQL = 0x2313; // invalid sql
|
||||
public static final int ERROR_NUMERIC_VALUE_OUT_OF_RANGE = 0x2314; // numeric value out of range
|
||||
public static final int ERROR_UNKNOWN_TAOS_TYPE_IN_TDENGINE = 0x2315; //unknown taos type in tdengine
|
||||
public static final int ERROR_UNKNOWN_TIMESTAMP_PERCISION = 0x2316; // unknown timestamp precision
|
||||
public static final int ERROR_UNKNOWN_TAOS_TYPE = 0x2315; //unknown taos type in tdengine
|
||||
public static final int ERROR_UNKNOWN_TIMESTAMP_PRECISION = 0x2316; // unknown timestamp precision
|
||||
public static final int ERROR_RESTFul_Client_Protocol_Exception = 0x2317;
|
||||
public static final int ERROR_RESTFul_Client_IOException = 0x2318;
|
||||
|
||||
public static final int ERROR_UNKNOWN = 0x2350; //unknown error
|
||||
|
||||
|
@ -62,8 +64,11 @@ public class TSDBErrorNumbers {
|
|||
errorNumbers.add(ERROR_URL_NOT_SET);
|
||||
errorNumbers.add(ERROR_INVALID_SQL);
|
||||
errorNumbers.add(ERROR_NUMERIC_VALUE_OUT_OF_RANGE);
|
||||
errorNumbers.add(ERROR_UNKNOWN_TAOS_TYPE_IN_TDENGINE);
|
||||
errorNumbers.add(ERROR_UNKNOWN_TIMESTAMP_PERCISION);
|
||||
errorNumbers.add(ERROR_UNKNOWN_TAOS_TYPE);
|
||||
errorNumbers.add(ERROR_UNKNOWN_TIMESTAMP_PRECISION);
|
||||
errorNumbers.add(ERROR_RESTFul_Client_IOException);
|
||||
|
||||
errorNumbers.add(ERROR_RESTFul_Client_Protocol_Exception);
|
||||
|
||||
errorNumbers.add(ERROR_SUBSCRIBE_FAILED);
|
||||
errorNumbers.add(ERROR_UNSUPPORTED_ENCODING);
|
||||
|
|
|
@ -213,7 +213,7 @@ public class RestfulResultSet extends AbstractResultSet implements ResultSet {
|
|||
long nanoAdjustment = Integer.parseInt(value.substring(20));
|
||||
return Timestamp.from(Instant.ofEpochSecond(epochSec, nanoAdjustment));
|
||||
}
|
||||
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNKNOWN_TIMESTAMP_PERCISION);
|
||||
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNKNOWN_TIMESTAMP_PRECISION);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,15 +1,18 @@
|
|||
package com.taosdata.jdbc.utils;
|
||||
|
||||
import com.taosdata.jdbc.TSDBError;
|
||||
import com.taosdata.jdbc.TSDBErrorNumbers;
|
||||
import org.apache.http.HeaderElement;
|
||||
import org.apache.http.HeaderElementIterator;
|
||||
import org.apache.http.HttpEntity;
|
||||
import org.apache.http.client.ClientProtocolException;
|
||||
import org.apache.http.client.HttpRequestRetryHandler;
|
||||
import org.apache.http.client.config.RequestConfig;
|
||||
import org.apache.http.client.methods.*;
|
||||
import org.apache.http.client.protocol.HttpClientContext;
|
||||
import org.apache.http.conn.ConnectionKeepAliveStrategy;
|
||||
import org.apache.http.entity.StringEntity;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
|
||||
import org.apache.http.impl.client.HttpClients;
|
||||
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
|
||||
import org.apache.http.message.BasicHeaderElementIterator;
|
||||
|
@ -17,35 +20,24 @@ import org.apache.http.protocol.HTTP;
|
|||
import org.apache.http.protocol.HttpContext;
|
||||
import org.apache.http.util.EntityUtils;
|
||||
|
||||
import javax.net.ssl.SSLException;
|
||||
import java.io.IOException;
|
||||
import java.io.InterruptedIOException;
|
||||
import java.net.UnknownHostException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import java.sql.SQLException;
|
||||
|
||||
public class HttpClientPoolUtil {
|
||||
|
||||
private static final String DEFAULT_CONTENT_TYPE = "application/json";
|
||||
private static final int DEFAULT_MAX_TOTAL = 200;
|
||||
private static final int DEFAULT_MAX_PER_ROUTE = 20;
|
||||
private static final int DEFAULT_TIME_OUT = 15000;
|
||||
private static final int DEFAULT_MAX_PER_ROUTE = 32;
|
||||
private static final int DEFAULT_MAX_TOTAL = 1000;
|
||||
private static final int DEFAULT_HTTP_KEEP_TIME = 15000;
|
||||
|
||||
private static CloseableHttpClient httpClient;
|
||||
|
||||
private static synchronized void initPools() {
|
||||
if (httpClient == null) {
|
||||
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();
|
||||
connectionManager.setDefaultMaxPerRoute(DEFAULT_MAX_PER_ROUTE);
|
||||
connectionManager.setMaxTotal(DEFAULT_MAX_TOTAL);
|
||||
httpClient = HttpClients.custom()
|
||||
.setKeepAliveStrategy(DEFAULT_KEEP_ALIVE_STRATEGY)
|
||||
.setConnectionManager(connectionManager)
|
||||
.setRetryHandler(new DefaultHttpRequestRetryHandler(3, true))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
private static final int DEFAULT_MAX_RETRY_COUNT = 5;
|
||||
|
||||
private static final ConnectionKeepAliveStrategy DEFAULT_KEEP_ALIVE_STRATEGY = (response, context) -> {
|
||||
HeaderElementIterator it = new BasicHeaderElementIterator(response.headerIterator(HTTP.CONN_KEEP_ALIVE));
|
||||
int keepTime = DEFAULT_HTTP_KEEP_TIME * 1000;
|
||||
while (it.hasNext()) {
|
||||
HeaderElement headerElement = it.nextElement();
|
||||
String param = headerElement.getName();
|
||||
|
@ -53,34 +45,73 @@ public class HttpClientPoolUtil {
|
|||
if (value != null && param.equalsIgnoreCase("timeout")) {
|
||||
try {
|
||||
return Long.parseLong(value) * 1000;
|
||||
} catch (Exception e) {
|
||||
new Exception("format KeepAlive timeout exception, exception:" + e.toString()).printStackTrace();
|
||||
} catch (NumberFormatException ignore) {
|
||||
}
|
||||
}
|
||||
}
|
||||
return keepTime;
|
||||
return DEFAULT_HTTP_KEEP_TIME * 1000;
|
||||
};
|
||||
|
||||
/**
|
||||
* 执行http post请求
|
||||
* 默认采用Content-Type:application/json,Accept:application/json
|
||||
*
|
||||
* @param uri 请求地址
|
||||
* @param data 请求数据
|
||||
* @return responseBody
|
||||
*/
|
||||
public static String execute(String uri, String data, String token) {
|
||||
long startTime = System.currentTimeMillis();
|
||||
private static final HttpRequestRetryHandler retryHandler = (exception, executionCount, httpContext) -> {
|
||||
if (executionCount >= DEFAULT_MAX_RETRY_COUNT)
|
||||
// do not retry if over max retry count
|
||||
return false;
|
||||
if (exception instanceof InterruptedIOException)
|
||||
// timeout
|
||||
return false;
|
||||
if (exception instanceof UnknownHostException)
|
||||
// unknown host
|
||||
return false;
|
||||
if (exception instanceof SSLException)
|
||||
// SSL handshake exception
|
||||
return false;
|
||||
return true;
|
||||
};
|
||||
|
||||
private static CloseableHttpClient httpClient;
|
||||
|
||||
static {
|
||||
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();
|
||||
connectionManager.setMaxTotal(DEFAULT_MAX_TOTAL);
|
||||
connectionManager.setDefaultMaxPerRoute(DEFAULT_MAX_PER_ROUTE);
|
||||
httpClient = HttpClients.custom().setKeepAliveStrategy(DEFAULT_KEEP_ALIVE_STRATEGY).setConnectionManager(connectionManager).setRetryHandler(retryHandler).build();
|
||||
}
|
||||
|
||||
/*** execute GET request ***/
|
||||
public static String execute(String uri) throws SQLException {
|
||||
HttpEntity httpEntity = null;
|
||||
HttpEntityEnclosingRequestBase method = null;
|
||||
String responseBody = "";
|
||||
try {
|
||||
if (httpClient == null) {
|
||||
initPools();
|
||||
HttpRequestBase method = getRequest(uri, HttpGet.METHOD_NAME);
|
||||
HttpContext context = HttpClientContext.create();
|
||||
CloseableHttpResponse httpResponse = httpClient.execute(method, context);
|
||||
httpEntity = httpResponse.getEntity();
|
||||
if (httpEntity != null) {
|
||||
responseBody = EntityUtils.toString(httpEntity, StandardCharsets.UTF_8);
|
||||
}
|
||||
method = (HttpEntityEnclosingRequestBase) getRequest(uri, HttpPost.METHOD_NAME, DEFAULT_CONTENT_TYPE, 0);
|
||||
method.setHeader("Content-Type", "text/plain");
|
||||
method.setHeader("Connection", "keep-alive");
|
||||
} catch (ClientProtocolException e) {
|
||||
e.printStackTrace();
|
||||
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_RESTFul_Client_Protocol_Exception, e.getMessage());
|
||||
} catch (IOException exception) {
|
||||
exception.printStackTrace();
|
||||
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_RESTFul_Client_IOException, exception.getMessage());
|
||||
} finally {
|
||||
if (httpEntity != null) {
|
||||
EntityUtils.consumeQuietly(httpEntity);
|
||||
}
|
||||
}
|
||||
return responseBody;
|
||||
}
|
||||
|
||||
|
||||
/*** execute POST request ***/
|
||||
public static String execute(String uri, String data, String token) throws SQLException {
|
||||
HttpEntity httpEntity = null;
|
||||
String responseBody = "";
|
||||
try {
|
||||
HttpEntityEnclosingRequestBase method = (HttpEntityEnclosingRequestBase) getRequest(uri, HttpPost.METHOD_NAME);
|
||||
method.setHeader(HTTP.CONTENT_TYPE, "text/plain");
|
||||
method.setHeader(HTTP.CONN_DIRECTIVE, HTTP.CONN_KEEP_ALIVE);
|
||||
method.setHeader("Authorization", "Taosd " + token);
|
||||
|
||||
method.setEntity(new StringEntity(data, StandardCharsets.UTF_8));
|
||||
|
@ -88,46 +119,31 @@ public class HttpClientPoolUtil {
|
|||
CloseableHttpResponse httpResponse = httpClient.execute(method, context);
|
||||
httpEntity = httpResponse.getEntity();
|
||||
if (httpEntity != null) {
|
||||
responseBody = EntityUtils.toString(httpEntity, "UTF-8");
|
||||
responseBody = EntityUtils.toString(httpEntity, StandardCharsets.UTF_8);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
if (method != null) {
|
||||
method.abort();
|
||||
}
|
||||
new Exception("execute post request exception, url:" + uri + ", exception:" + e.toString() + ", cost time(ms):" + (System.currentTimeMillis() - startTime)).printStackTrace();
|
||||
} catch (ClientProtocolException e) {
|
||||
e.printStackTrace();
|
||||
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_RESTFul_Client_Protocol_Exception, e.getMessage());
|
||||
} catch (IOException exception) {
|
||||
exception.printStackTrace();
|
||||
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_RESTFul_Client_IOException, exception.getMessage());
|
||||
} finally {
|
||||
if (httpEntity != null) {
|
||||
try {
|
||||
EntityUtils.consumeQuietly(httpEntity);
|
||||
} catch (Exception e) {
|
||||
new Exception("close response exception, url:" + uri + ", exception:" + e.toString() + ", cost time(ms):" + (System.currentTimeMillis() - startTime)).printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
return responseBody;
|
||||
}
|
||||
|
||||
/**
|
||||
* * 创建请求
|
||||
*
|
||||
* @param uri 请求url
|
||||
* @param methodName 请求的方法类型
|
||||
* @param contentType contentType类型
|
||||
* @param timeout 超时时间
|
||||
* @return HttpRequestBase 返回类型
|
||||
* @author lisc
|
||||
*/
|
||||
private static HttpRequestBase getRequest(String uri, String methodName, String contentType, int timeout) {
|
||||
if (httpClient == null) {
|
||||
initPools();
|
||||
}
|
||||
/*** create http request ***/
|
||||
private static HttpRequestBase getRequest(String uri, String methodName) {
|
||||
HttpRequestBase method;
|
||||
if (timeout <= 0) {
|
||||
timeout = DEFAULT_TIME_OUT;
|
||||
}
|
||||
RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(timeout * 1000)
|
||||
.setConnectTimeout(timeout * 1000).setConnectionRequestTimeout(timeout * 1000)
|
||||
.setExpectContinueEnabled(false).build();
|
||||
RequestConfig requestConfig = RequestConfig.custom()
|
||||
.setSocketTimeout(DEFAULT_TIME_OUT * 1000)
|
||||
.setConnectTimeout(DEFAULT_TIME_OUT * 1000)
|
||||
.setConnectionRequestTimeout(DEFAULT_TIME_OUT * 1000)
|
||||
.setExpectContinueEnabled(false)
|
||||
.build();
|
||||
if (HttpPut.METHOD_NAME.equalsIgnoreCase(methodName)) {
|
||||
method = new HttpPut(uri);
|
||||
} else if (HttpPost.METHOD_NAME.equalsIgnoreCase(methodName)) {
|
||||
|
@ -137,52 +153,10 @@ public class HttpClientPoolUtil {
|
|||
} else {
|
||||
method = new HttpPost(uri);
|
||||
}
|
||||
|
||||
if (contentType == null || contentType.isEmpty() || contentType.replaceAll("\\s", "").isEmpty()) {
|
||||
contentType = DEFAULT_CONTENT_TYPE;
|
||||
}
|
||||
method.addHeader("Content-Type", contentType);
|
||||
method.addHeader("Accept", contentType);
|
||||
method.addHeader(HTTP.CONTENT_TYPE, DEFAULT_CONTENT_TYPE);
|
||||
method.addHeader("Accept", DEFAULT_CONTENT_TYPE);
|
||||
method.setConfig(requestConfig);
|
||||
return method;
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行GET 请求
|
||||
*
|
||||
* @param uri 网址
|
||||
* @return responseBody
|
||||
*/
|
||||
public static String execute(String uri) {
|
||||
long startTime = System.currentTimeMillis();
|
||||
HttpEntity httpEntity = null;
|
||||
HttpRequestBase method = null;
|
||||
String responseBody = "";
|
||||
try {
|
||||
if (httpClient == null) {
|
||||
initPools();
|
||||
}
|
||||
method = getRequest(uri, HttpGet.METHOD_NAME, DEFAULT_CONTENT_TYPE, 0);
|
||||
HttpContext context = HttpClientContext.create();
|
||||
CloseableHttpResponse httpResponse = httpClient.execute(method, context);
|
||||
httpEntity = httpResponse.getEntity();
|
||||
if (httpEntity != null) {
|
||||
responseBody = EntityUtils.toString(httpEntity, "UTF-8");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
if (method != null) {
|
||||
method.abort();
|
||||
}
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if (httpEntity != null) {
|
||||
try {
|
||||
EntityUtils.consumeQuietly(httpEntity);
|
||||
} catch (Exception e) {
|
||||
new Exception("close response exception, url:" + uri + ", exception:" + e.toString() + ",cost time(ms):" + (System.currentTimeMillis() - startTime)).printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
return responseBody;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue