Add vpp user apis

fixes https://roadmap.entgra.net/issues/10162
mssqldbscriptfix
inoshperera 1 year ago
parent ab2e1297e5
commit 9ccf3a5fa5

@ -0,0 +1,37 @@
/*
* Copyright (c) 2018 - 2023, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package io.entgra.device.mgt.core.application.mgt.common.dto;
public class ProxyResponse {
private int code;
private String data;
private String executorResponse;
public int getCode() { return code; }
public void setCode(int code) { this.code = code; }
public String getData() { return data; }
public void setData(String data) { this.data = data; }
public String getExecutorResponse() { return executorResponse; }
public void setExecutorResponse(String executorResponse) { this.executorResponse = executorResponse; }
}

@ -0,0 +1,67 @@
/*
* Copyright (c) 2018 - 2023, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package io.entgra.device.mgt.core.application.mgt.common.dto;
public class VppItuneUserDTO {
String clientUserId;
String inviteCode;
String status;
String email;
String managedId;
public String getClientUserId() {
return clientUserId;
}
public void setClientUserId(String clientUserId) {
this.clientUserId = clientUserId;
}
public String getInviteCode() {
return inviteCode;
}
public void setInviteCode(String inviteCode) {
this.inviteCode = inviteCode;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getManagedId() {
return managedId;
}
public void setManagedId(String managedId) {
this.managedId = managedId;
}
}

@ -0,0 +1,76 @@
/*
* Copyright (c) 2018 - 2023, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package io.entgra.device.mgt.core.application.mgt.common.dto;
public class VppUserDTO extends VppItuneUserDTO {
int id;
String dmUsername;
int tenantId;
String createdTime;
String lastUpdatedTime;
String tmpPassword;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getDmUsername() {
return dmUsername;
}
public void setDmUsername(String dmUsername) {
this.dmUsername = dmUsername;
}
public int getTenantId() {
return tenantId;
}
public void setTenantId(int tenantId) {
this.tenantId = tenantId;
}
public String getCreatedTime() {
return createdTime;
}
public void setCreatedTime(String createdTime) {
this.createdTime = createdTime;
}
public String getLastUpdatedTime() {
return lastUpdatedTime;
}
public void setLastUpdatedTime(String lastUpdatedTime) {
this.lastUpdatedTime = lastUpdatedTime;
}
public String getTmpPassword() {
return tmpPassword;
}
public void setTmpPassword(String tmpPassword) {
this.tmpPassword = tmpPassword;
}
}

@ -0,0 +1,34 @@
/*
* Copyright (c) 2018 - 2023, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package io.entgra.device.mgt.core.application.mgt.common.services;
import io.entgra.device.mgt.core.application.mgt.common.dto.ProxyResponse;
import io.entgra.device.mgt.core.application.mgt.common.dto.VppUserDTO;
import io.entgra.device.mgt.core.application.mgt.common.exception.ApplicationManagementException;
import java.io.IOException;
public interface VPPApplicationManager {
VppUserDTO getUserByDMUsername() throws ApplicationManagementException;
VppUserDTO addUser(VppUserDTO userDTO) throws ApplicationManagementException;
ProxyResponse callVPPBackend(String url, String payload, String accessToken, String method) throws IOException;
}

@ -0,0 +1,40 @@
/*
* Copyright (c) 2018 - 2023, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package io.entgra.device.mgt.core.application.mgt.common.wrapper;
import io.entgra.device.mgt.core.application.mgt.common.dto.VppItuneUserDTO;
import java.util.ArrayList;
import java.util.List;
public class VppItuneUserRequestWrapper {
List<VppItuneUserDTO> user;
public VppItuneUserRequestWrapper() {
user = new ArrayList<>();
}
public List<VppItuneUserDTO> getUser() {
return user;
}
public void setUser(List<VppItuneUserDTO> user) {
this.user = user;
}
}

@ -0,0 +1,107 @@
/*
* Copyright (c) 2018 - 2023, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package io.entgra.device.mgt.core.application.mgt.core.impl;
import com.google.gson.Gson;
import io.entgra.device.mgt.core.application.mgt.common.dto.ProxyResponse;
import io.entgra.device.mgt.core.application.mgt.common.dto.VppItuneUserDTO;
import io.entgra.device.mgt.core.application.mgt.common.wrapper.VppItuneUserRequestWrapper;
import io.entgra.device.mgt.core.application.mgt.common.dto.VppUserDTO;
import io.entgra.device.mgt.core.application.mgt.common.exception.ApplicationManagementException;
import io.entgra.device.mgt.core.application.mgt.common.services.VPPApplicationManager;
import io.entgra.device.mgt.core.application.mgt.core.dao.ApplicationDAO;
import io.entgra.device.mgt.core.application.mgt.core.dao.SPApplicationDAO;
import io.entgra.device.mgt.core.application.mgt.core.dao.VisibilityDAO;
import io.entgra.device.mgt.core.application.mgt.core.dao.common.ApplicationManagementDAOFactory;
import io.entgra.device.mgt.core.application.mgt.core.internal.DataHolder;
import io.entgra.device.mgt.core.application.mgt.core.lifecycle.LifecycleStateManager;
import io.entgra.device.mgt.core.application.mgt.core.util.Constants;
import io.entgra.device.mgt.core.application.mgt.core.util.VppHttpUtil;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.HttpStatus;
import java.io.IOException;
public class VppApplicationManagerImpl implements VPPApplicationManager {
private static final String APP_API = "https://vpp.itunes.apple.com/mdm/v2";
private static final String ASSETS = APP_API + "/assets";
private static final String USER_CREATE = APP_API + "users/create";
private static final String TOKEN = "";
private static final Log log = LogFactory.getLog(VppApplicationManagerImpl.class);
private ApplicationDAO applicationDAO;
private SPApplicationDAO spApplicationDAO;
private VisibilityDAO visibilityDAO;
private final LifecycleStateManager lifecycleStateManager;
public VppApplicationManagerImpl() {
initDataAccessObjects();
lifecycleStateManager = DataHolder.getInstance().getLifecycleStateManager();
}
private void initDataAccessObjects() {
this.applicationDAO = ApplicationManagementDAOFactory.getApplicationDAO();
this.visibilityDAO = ApplicationManagementDAOFactory.getVisibilityDAO();
this.spApplicationDAO = ApplicationManagementDAOFactory.getSPApplicationDAO();
}
@Override
public VppUserDTO getUserByDMUsername() throws ApplicationManagementException {
// TODO: Return from DAO in a tenanted manner
return null;
}
@Override
public VppUserDTO addUser(VppUserDTO userDTO) throws ApplicationManagementException {
// Call the API to add
try {
VppItuneUserDTO ituneUserDTO = userDTO;
VppItuneUserRequestWrapper wrapper = new VppItuneUserRequestWrapper();
wrapper.getUser().add(ituneUserDTO);
Gson gson = new Gson();
String userPayload = gson.toJson(wrapper);
ProxyResponse proxyResponse = callVPPBackend(USER_CREATE, userPayload, TOKEN, Constants.POST);
if (proxyResponse.getCode() == HttpStatus.SC_OK || proxyResponse.getCode() == HttpStatus.SC_CREATED) {
// TODO: Save the user in the DAO
}
} catch (IOException e) {
String msg = "Error while callng VPP backend";
log.error(msg, e);
throw new ApplicationManagementException(msg, e);
}
return null;
}
@Override
public ProxyResponse callVPPBackend(String url,
String payload,
String accessToken,
String method) throws IOException {
return VppHttpUtil.execute(url, payload, accessToken, method);
}
}

@ -18,7 +18,9 @@
package io.entgra.device.mgt.core.application.mgt.core.internal;
import io.entgra.device.mgt.core.application.mgt.common.services.SPApplicationManager;
import io.entgra.device.mgt.core.application.mgt.common.services.VPPApplicationManager;
import io.entgra.device.mgt.core.application.mgt.core.impl.AppmDataHandlerImpl;
import io.entgra.device.mgt.core.application.mgt.core.impl.VppApplicationManagerImpl;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.osgi.framework.BundleContext;
@ -116,6 +118,12 @@ public class ApplicationManagementServiceComponent {
DataHolder.getInstance().setConfigManager(configManager);
bundleContext.registerService(AppmDataHandler.class.getName(), configManager, null);
// TODO: Get the new instance from extension like others
VppApplicationManagerImpl vppApplicationManager = new VppApplicationManagerImpl();
DataHolder.getInstance().setVppApplicationManager(vppApplicationManager);
bundleContext.registerService(VPPApplicationManager.class.getName(), vppApplicationManager, null);
ScheduledAppSubscriptionTaskManager taskManager = new ScheduledAppSubscriptionTaskManager();
taskManager.scheduleCleanupTask();

@ -23,6 +23,7 @@ import io.entgra.device.mgt.core.application.mgt.common.services.AppmDataHandler
import io.entgra.device.mgt.core.application.mgt.common.services.SPApplicationManager;
import io.entgra.device.mgt.core.application.mgt.common.services.ReviewManager;
import io.entgra.device.mgt.core.application.mgt.common.services.SubscriptionManager;
import io.entgra.device.mgt.core.application.mgt.common.services.VPPApplicationManager;
import io.entgra.device.mgt.core.application.mgt.core.lifecycle.LifecycleStateManager;
import io.entgra.device.mgt.core.device.mgt.core.service.DeviceManagementProviderService;
import org.wso2.carbon.ntask.core.service.TaskService;
@ -39,6 +40,8 @@ public class DataHolder {
private SPApplicationManager SPApplicationManager;
private VPPApplicationManager vppApplicationManager;
private ApplicationManager applicationManager;
private ReviewManager reviewManager;
@ -142,4 +145,12 @@ public class DataHolder {
public void setISApplicationManager(SPApplicationManager SPApplicationManager) {
this.SPApplicationManager = SPApplicationManager;
}
public VPPApplicationManager getVppApplicationManager() {
return vppApplicationManager;
}
public void setVppApplicationManager(VPPApplicationManager vppApplicationManager) {
this.vppApplicationManager = vppApplicationManager;
}
}

@ -100,6 +100,18 @@ public class Constants {
}
public static final Map<String, String> AGENT_FILE_NAMES = Collections.unmodifiableMap(AGENT_DATA);
public static final String BEARER = "Bearer ";
public static final String EXECUTOR_EXCEPTION_PREFIX = "ExecutorException-";
public static final String TOKEN_IS_EXPIRED = "ACCESS_TOKEN_IS_EXPIRED";
public static final int INTERNAL_ERROR_CODE = 500;
public static final String GET = "GET";
public static final String POST = "POST";
public static final String PUT = "PUT";
public static final String DELETE = "DELETE";
/**
* Database types supported by Application Management.

@ -0,0 +1,285 @@
/*
* Copyright (c) 2018 - 2023, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package io.entgra.device.mgt.core.application.mgt.core.util;
import com.google.gson.Gson;
import io.entgra.device.mgt.core.application.mgt.common.dto.ProxyResponse;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.Consts;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHeaders;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
public class VppHttpUtil {
private static final Log log = LogFactory.getLog(VppHttpUtil.class);
public static ProxyResponse execute(String url,
String payload,
String accessToken,
String method) throws IOException {
HttpRequestBase endpoint = null;
if (Constants.GET.equalsIgnoreCase(method) || Constants.DELETE.equalsIgnoreCase(method)) {
endpoint = new HttpGet(url);
addHeaders(endpoint, accessToken);
return VppHttpUtil.execute(endpoint);
} else if (Constants.POST.equalsIgnoreCase(method)) {
endpoint = new HttpPost(url);
} else if (Constants.PUT.equalsIgnoreCase(method)) {
endpoint = new HttpPut(url);
}
addHeaders(endpoint, accessToken);
if (payload != null) {
HttpEntity forwardRequestBody = new StringEntity(payload, ContentType.APPLICATION_JSON.toString(), "utf-8");
if (Constants.POST.equalsIgnoreCase(method)) {
((HttpPost) endpoint).setEntity(forwardRequestBody);
} else if (Constants.PUT.equalsIgnoreCase(method)) {
((HttpPut) endpoint).setEntity(forwardRequestBody);
}
}
if (log.isDebugEnabled()) {
log.info("Forwarding request to " + url);
}
return VppHttpUtil.execute(endpoint);
}
private static void addHeaders(HttpRequestBase endpoint, String accessToken) {
endpoint.setHeader(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON.toString());
endpoint.setHeader(HttpHeaders.ACCEPT, ContentType.APPLICATION_JSON.toString());
endpoint.setHeader(HttpHeaders.AUTHORIZATION, Constants.BEARER + accessToken);
}
/***
*
* @param httpRequest - httpMethod e.g:- HttpPost, HttpGet
* @return response as string
* @throws IOException IO exception returns if error occurs when executing the httpMethod
*/
private static ProxyResponse execute(HttpRequestBase httpRequest) throws IOException {
try (CloseableHttpClient client = getHttpClient()) {
HttpResponse response = client.execute(httpRequest);
ProxyResponse proxyResponse = new ProxyResponse();
if (response == null) {
log.error("Received null response for http request : " + httpRequest.getMethod() + " " + httpRequest
.getURI().toString());
proxyResponse.setCode(Constants.INTERNAL_ERROR_CODE);
proxyResponse.setExecutorResponse(Constants.EXECUTOR_EXCEPTION_PREFIX + getStatusKey(
Constants.INTERNAL_ERROR_CODE));
return proxyResponse;
} else {
int statusCode = response.getStatusLine().getStatusCode();
try (BufferedReader rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent()))) {
StringBuilder result = new StringBuilder();
String line;
while ((line = rd.readLine()) != null) {
result.append(line);
}
String jsonString = result.toString();
if (statusCode == HttpStatus.SC_OK || statusCode == HttpStatus.SC_CREATED) {
proxyResponse.setCode(statusCode);
proxyResponse.setData(jsonString);
proxyResponse.setExecutorResponse("SUCCESS");
return proxyResponse;
} else if (statusCode == HttpStatus.SC_UNAUTHORIZED) {
if (jsonString.contains("Access token expired") || jsonString
.contains("Invalid input. Access token validation failed")) {
proxyResponse.setCode(statusCode);
proxyResponse.setExecutorResponse(Constants.TOKEN_IS_EXPIRED);
return proxyResponse;
} else {
log.error(
"Received " + statusCode + " response for http request : " + httpRequest.getMethod()
+ " " + httpRequest.getURI().toString() + ". Error message: " + jsonString);
proxyResponse.setCode(statusCode);
proxyResponse.setData(jsonString);
proxyResponse.setExecutorResponse(
Constants.EXECUTOR_EXCEPTION_PREFIX + getStatusKey(statusCode));
return proxyResponse;
}
}
log.error("Received " + statusCode +
" response for http request : " + httpRequest.getMethod() + " " + httpRequest.getURI()
.toString() + ". Error message: " + jsonString);
proxyResponse.setCode(statusCode);
proxyResponse.setData(jsonString);
proxyResponse
.setExecutorResponse(Constants.EXECUTOR_EXCEPTION_PREFIX + getStatusKey(statusCode));
return proxyResponse;
}
}
}
}
/***
*
* @param statusCode Provide status code, e.g:- 400, 401, 500 etc
* @return relative status code key for given status code.
*/
public static String getStatusKey(int statusCode) {
String statusCodeKey;
switch (statusCode) {
case HttpStatus.SC_INTERNAL_SERVER_ERROR:
statusCodeKey = "internalServerError";
break;
case HttpStatus.SC_BAD_REQUEST:
statusCodeKey = "badRequest";
break;
case HttpStatus.SC_UNAUTHORIZED:
statusCodeKey = "unauthorized";
break;
case HttpStatus.SC_FORBIDDEN:
statusCodeKey = "forbidden";
break;
case HttpStatus.SC_NOT_FOUND:
statusCodeKey = "notFound";
break;
case HttpStatus.SC_METHOD_NOT_ALLOWED:
statusCodeKey = "methodNotAllowed";
break;
case HttpStatus.SC_NOT_ACCEPTABLE:
statusCodeKey = "notAcceptable";
break;
case HttpStatus.SC_UNSUPPORTED_MEDIA_TYPE:
statusCodeKey = "unsupportedMediaType";
break;
default:
statusCodeKey = "defaultPage";
break;
}
return statusCodeKey;
}
/***
* Handle error requests.
*
* @param resp {@link HttpServletResponse}
* @param proxyResponse {@link ProxyResponse}
* @throws IOException If error occurred when trying to send the error response.
*/
public static void handleError(HttpServletResponse resp, ProxyResponse proxyResponse) throws IOException {
Gson gson = new Gson();
if (proxyResponse == null) {
proxyResponse = new ProxyResponse();
proxyResponse.setCode(HttpStatus.SC_INTERNAL_SERVER_ERROR);
proxyResponse.setExecutorResponse(Constants.EXECUTOR_EXCEPTION_PREFIX + VppHttpUtil
.getStatusKey(Constants.INTERNAL_ERROR_CODE));
}
resp.setStatus(proxyResponse.getCode());
resp.setContentType(ContentType.APPLICATION_JSON.getMimeType());
resp.setCharacterEncoding(Consts.UTF_8.name());
proxyResponse.setExecutorResponse(null);
try (PrintWriter writer = resp.getWriter()) {
writer.write(gson.toJson(proxyResponse));
}
}
/**
* Handle error requests with custom error codes.
*
* @param resp {@link HttpServletResponse}
* @param errorCode HTTP error status code
* @throws IOException If error occurred when trying to send the error response.
*/
public static void handleError(HttpServletResponse resp, int errorCode)
throws IOException {
ProxyResponse proxyResponse = new ProxyResponse();
proxyResponse.setCode(errorCode);
proxyResponse.setExecutorResponse(
Constants.EXECUTOR_EXCEPTION_PREFIX + VppHttpUtil.getStatusKey(errorCode));
VppHttpUtil.handleError(resp, proxyResponse);
}
/***
*
* @param resp {@link HttpServletResponse}
* Return Success Response.
*/
public static void handleSuccess(HttpServletResponse resp, ProxyResponse proxyResponse) throws IOException {
if (proxyResponse == null) {
handleError(resp, null);
return;
}
resp.setStatus(proxyResponse.getCode());
resp.setContentType(ContentType.APPLICATION_JSON.getMimeType());
resp.setCharacterEncoding(Consts.UTF_8.name());
JSONObject response = new JSONObject();
String responseData = proxyResponse.getData();
if (!StringUtils.isEmpty(responseData)) {
try {
if (responseData.startsWith("{")) {
JSONObject responseDataJsonObj = new JSONObject(responseData);
response.put("data", responseDataJsonObj);
} else if (responseData.startsWith("[")) {
JSONArray responseDataJsonArr = new JSONArray(responseData);
response.put("data", responseDataJsonArr);
} else {
log.warn("Response data is not valid json string >> " + responseData);
response.put("data", responseData);
}
} catch (JSONException e) {
log.error("Response data is not passable");
response.put("data", responseData);
}
}
try (PrintWriter writer = resp.getWriter()) {
writer.write(response.toString());
}
}
/**
* Retrieve Http client based on hostname verification.
*
* @return {@link CloseableHttpClient} http client
*/
public static CloseableHttpClient getHttpClient() {
return HttpClients.custom().setMaxConnTotal(1).setMaxConnPerRoute(1).build();
}
}
Loading…
Cancel
Save