diff --git a/DIST/RestServices_mx5_1.5.1.mpk b/DIST/RestServices_mx5_1.5.1.mpk new file mode 100644 index 0000000..e10ac30 Binary files /dev/null and b/DIST/RestServices_mx5_1.5.1.mpk differ diff --git a/README.md b/README.md index ed8f123..b2117b1 100644 --- a/README.md +++ b/README.md @@ -468,6 +468,11 @@ Generic method to make a HTTP request. `post`, `put`, `get`, `delete` are wrappe #### resetChangeTracking Resets any state information this app has about a remote collection that is being tracked. +#### setGlobalRequestSettings +Sets settings for all requests that are executed by RestServices module. +* `maxConcurrentRequest` - number of maximum concurrent requests executed. This will set concurrency level per host. Total concurrency level is double this setting. +* `timeout` - timeout specified in milliseconds. This will set timeout for both establishing connection and waiting between data chunks arrived from server. + #### unfollowChanges Stops tracking a remote collection, which was being followed as result of a `followChanges` call. diff --git a/RestServices.mpr b/RestServices.mpr index 7634dc7..0301a6a 100644 Binary files a/RestServices.mpr and b/RestServices.mpr differ diff --git a/javasource/restservices/RestServices.java b/javasource/restservices/RestServices.java index 753c7e5..8d999cb 100644 --- a/javasource/restservices/RestServices.java +++ b/javasource/restservices/RestServices.java @@ -20,7 +20,7 @@ public class RestServices { /** * Version of the RestServices module */ - public static final String VERSION = "1.4.2"; + public static final String VERSION = "1.5.1"; /** * Amount of objects that are processed by the module at the same time. diff --git a/javasource/restservices/actions/getWithParams.java b/javasource/restservices/actions/getWithParams.java index 37ff260..f2d6095 100644 --- a/javasource/restservices/actions/getWithParams.java +++ b/javasource/restservices/actions/getWithParams.java @@ -1,54 +1,54 @@ -// This file was generated by Mendix Business Modeler. -// -// WARNING: Only the following code will be retained when actions are regenerated: -// - the import list -// - the code between BEGIN USER CODE and END USER CODE -// - the code between BEGIN EXTRA CODE and END EXTRA CODE -// Other code you write will be lost the next time you deploy the project. -// Special characters, e.g., é, ö, à, etc. are supported in comments. - -package restservices.actions; - -import restservices.consume.RestConsumer; -import restservices.proxies.HttpMethod; -import com.mendix.systemwideinterfaces.core.IMendixObject; -import com.mendix.systemwideinterfaces.core.IContext; -import com.mendix.webui.CustomJavaAction; - -/** - * - */ -public class getWithParams extends CustomJavaAction -{ - private String resourceUrl; - private IMendixObject requestData; - private IMendixObject targetObject; - - public getWithParams(IContext context, String resourceUrl, IMendixObject requestData, IMendixObject targetObject) - { - super(context); - this.resourceUrl = resourceUrl; - this.requestData = requestData; - this.targetObject = targetObject; - } - - @Override - public IMendixObject executeAction() throws Exception - { - // BEGIN USER CODE - return RestConsumer.request(getContext(), HttpMethod.GET, resourceUrl, requestData, targetObject, false).getMendixObject(); - // END USER CODE - } - - /** - * Returns a string representation of this action - */ - @Override - public String toString() - { - return "getWithParams"; - } - - // BEGIN EXTRA CODE - // END EXTRA CODE -} +// This file was generated by Mendix Business Modeler. +// +// WARNING: Only the following code will be retained when actions are regenerated: +// - the import list +// - the code between BEGIN USER CODE and END USER CODE +// - the code between BEGIN EXTRA CODE and END EXTRA CODE +// Other code you write will be lost the next time you deploy the project. +// Special characters, e.g., é, ö, à, etc. are supported in comments. + +package restservices.actions; + +import restservices.consume.RestConsumer; +import restservices.proxies.HttpMethod; +import com.mendix.systemwideinterfaces.core.IMendixObject; +import com.mendix.systemwideinterfaces.core.IContext; +import com.mendix.webui.CustomJavaAction; + +/** + * + */ +public class getWithParams extends CustomJavaAction +{ + private String resourceUrl; + private IMendixObject requestData; + private IMendixObject targetObject; + + public getWithParams(IContext context, String resourceUrl, IMendixObject requestData, IMendixObject targetObject) + { + super(context); + this.resourceUrl = resourceUrl; + this.requestData = requestData; + this.targetObject = targetObject; + } + + @Override + public IMendixObject executeAction() throws Exception + { + // BEGIN USER CODE + return RestConsumer.request(getContext(), HttpMethod.GET, resourceUrl, requestData, targetObject, false).getMendixObject(); + // END USER CODE + } + + /** + * Returns a string representation of this action + */ + @Override + public String toString() + { + return "getWithParams"; + } + + // BEGIN EXTRA CODE + // END EXTRA CODE +} diff --git a/javasource/restservices/actions/postWithResult.java b/javasource/restservices/actions/postWithResult.java index 6eae2dc..3a5a02f 100644 --- a/javasource/restservices/actions/postWithResult.java +++ b/javasource/restservices/actions/postWithResult.java @@ -1,53 +1,53 @@ -// This file was generated by Mendix Business Modeler. -// -// WARNING: Only the following code will be retained when actions are regenerated: -// - the import list -// - the code between BEGIN USER CODE and END USER CODE -// - the code between BEGIN EXTRA CODE and END EXTRA CODE -// Other code you write will be lost the next time you deploy the project. -// Special characters, e.g., é, ö, à, etc. are supported in comments. - -package restservices.actions; - -import restservices.consume.RestConsumer; -import com.mendix.systemwideinterfaces.core.IMendixObject; -import com.mendix.systemwideinterfaces.core.IContext; -import com.mendix.webui.CustomJavaAction; - -/** - * - */ -public class postWithResult extends CustomJavaAction -{ - private String collectionUrl; - private IMendixObject dataObject; - private IMendixObject responseData; - - public postWithResult(IContext context, String collectionUrl, IMendixObject dataObject, IMendixObject responseData) - { - super(context); - this.collectionUrl = collectionUrl; - this.dataObject = dataObject; - this.responseData = responseData; - } - - @Override - public IMendixObject executeAction() throws Exception - { - // BEGIN USER CODE - return RestConsumer.postObject(getContext(), collectionUrl, dataObject, responseData).getMendixObject(); - // END USER CODE - } - - /** - * Returns a string representation of this action - */ - @Override - public String toString() - { - return "postWithResult"; - } - - // BEGIN EXTRA CODE - // END EXTRA CODE -} +// This file was generated by Mendix Business Modeler. +// +// WARNING: Only the following code will be retained when actions are regenerated: +// - the import list +// - the code between BEGIN USER CODE and END USER CODE +// - the code between BEGIN EXTRA CODE and END EXTRA CODE +// Other code you write will be lost the next time you deploy the project. +// Special characters, e.g., é, ö, à, etc. are supported in comments. + +package restservices.actions; + +import restservices.consume.RestConsumer; +import com.mendix.systemwideinterfaces.core.IMendixObject; +import com.mendix.systemwideinterfaces.core.IContext; +import com.mendix.webui.CustomJavaAction; + +/** + * + */ +public class postWithResult extends CustomJavaAction +{ + private String collectionUrl; + private IMendixObject dataObject; + private IMendixObject responseData; + + public postWithResult(IContext context, String collectionUrl, IMendixObject dataObject, IMendixObject responseData) + { + super(context); + this.collectionUrl = collectionUrl; + this.dataObject = dataObject; + this.responseData = responseData; + } + + @Override + public IMendixObject executeAction() throws Exception + { + // BEGIN USER CODE + return RestConsumer.postObject(getContext(), collectionUrl, dataObject, responseData).getMendixObject(); + // END USER CODE + } + + /** + * Returns a string representation of this action + */ + @Override + public String toString() + { + return "postWithResult"; + } + + // BEGIN EXTRA CODE + // END EXTRA CODE +} diff --git a/javasource/restservices/actions/setGlobalRequestSettings.java b/javasource/restservices/actions/setGlobalRequestSettings.java new file mode 100644 index 0000000..9bf8588 --- /dev/null +++ b/javasource/restservices/actions/setGlobalRequestSettings.java @@ -0,0 +1,51 @@ +// This file was generated by Mendix Business Modeler. +// +// WARNING: Only the following code will be retained when actions are regenerated: +// - the import list +// - the code between BEGIN USER CODE and END USER CODE +// - the code between BEGIN EXTRA CODE and END EXTRA CODE +// Other code you write will be lost the next time you deploy the project. +// Special characters, e.g., é, ö, à, etc. are supported in comments. + +package restservices.actions; + +import restservices.consume.RestConsumer; +import com.mendix.systemwideinterfaces.core.IContext; +import com.mendix.webui.CustomJavaAction; + +/** + * + */ +public class setGlobalRequestSettings extends CustomJavaAction +{ + private Long maxConcurrentRequests; + private Long timeout; + + public setGlobalRequestSettings(IContext context, Long maxConcurrentRequests, Long timeout) + { + super(context); + this.maxConcurrentRequests = maxConcurrentRequests; + this.timeout = timeout; + } + + @Override + public Boolean executeAction() throws Exception + { + // BEGIN USER CODE + RestConsumer.setGlobalRequestSettings(maxConcurrentRequests, timeout); + return true; + // END USER CODE + } + + /** + * Returns a string representation of this action + */ + @Override + public String toString() + { + return "setGlobalRequestSettings"; + } + + // BEGIN EXTRA CODE + // END EXTRA CODE +} diff --git a/javasource/restservices/consume/RestConsumer.java b/javasource/restservices/consume/RestConsumer.java index c3c7adb..621c845 100644 --- a/javasource/restservices/consume/RestConsumer.java +++ b/javasource/restservices/consume/RestConsumer.java @@ -14,15 +14,7 @@ import java.util.Set; import java.util.TreeMap; -import org.apache.commons.httpclient.Credentials; -import org.apache.commons.httpclient.Header; -import org.apache.commons.httpclient.HttpClient; -import org.apache.commons.httpclient.HttpException; -import org.apache.commons.httpclient.HttpMethodBase; -import org.apache.commons.httpclient.HttpStatus; -import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager; -import org.apache.commons.httpclient.NameValuePair; -import org.apache.commons.httpclient.UsernamePasswordCredentials; +import org.apache.commons.httpclient.*; import org.apache.commons.httpclient.auth.AuthScope; import org.apache.commons.httpclient.cookie.CookiePolicy; import org.apache.commons.httpclient.cookie.CookieSpec; @@ -75,8 +67,12 @@ public class RestConsumer { private static ThreadLocal lastConsumeError = new ThreadLocal(); private static MultiThreadedHttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager(); - static HttpClient client = new HttpClient(connectionManager); - + static HttpClient client = new HttpClient(connectionManager); + + static { + connectionManager.getParams().setMaxConnectionsPerHost(HostConfiguration.ANY_HOST_CONFIGURATION, 10); + } + public static class HttpResponseData{ private int status; private String body = null; @@ -180,7 +176,19 @@ private static Map prepareNextHeadersMap() { } return headers; } - + + public static synchronized void setGlobalRequestSettings(Long maxConcurrentRequests, Long timeout) { + if (timeout != null) { + client.getParams().setConnectionManagerTimeout(timeout); + client.getParams().setSoTimeout(timeout.intValue()); + } + + if (maxConcurrentRequests != null) { + connectionManager.getParams().setMaxConnectionsPerHost(HostConfiguration.ANY_HOST_CONFIGURATION, maxConcurrentRequests.intValue()); + connectionManager.getParams().setMaxTotalConnections(maxConcurrentRequests.intValue() * 2); + } + } + public static void addHeaderToNextRequest(String header, String value) { prepareNextHeadersMap().put(header, value); } diff --git a/javasource/system/UserActionsRegistrar.java b/javasource/system/UserActionsRegistrar.java index 9bac055..70c9e46 100644 --- a/javasource/system/UserActionsRegistrar.java +++ b/javasource/system/UserActionsRegistrar.java @@ -149,6 +149,7 @@ public void handleEvent(Event event) component.actionRegistry().registerUserAction(restservices.actions.resetChangeTracking.class); component.actionRegistry().registerUserAction(restservices.actions.serializeObjectToJson.class); component.actionRegistry().registerUserAction(restservices.actions.ServiceConsistencyCheck.class); + component.actionRegistry().registerUserAction(restservices.actions.setGlobalRequestSettings.class); component.actionRegistry().registerUserAction(restservices.actions.setResponseCookie.class); component.actionRegistry().registerUserAction(restservices.actions.setResponseHeader.class); component.actionRegistry().registerUserAction(restservices.actions.setResponseStatus.class); diff --git a/javasource/tests/TimeoutTests.java b/javasource/tests/TimeoutTests.java new file mode 100644 index 0000000..7902885 --- /dev/null +++ b/javasource/tests/TimeoutTests.java @@ -0,0 +1,29 @@ +package tests; + +import com.mendix.core.Core; +import org.junit.Assert; +import org.junit.Test; +import restservices.RestServices; +import restservices.consume.RestConsumeException; +import restservices.consume.RestConsumer; +import restservices.proxies.HttpMethod; +import restservices.publish.MicroflowService; + +public class TimeoutTests extends TestBase { + + @Test + public void testIdleTimeout() throws Exception { + RestConsumer.setGlobalRequestSettings(null, 1000L); + String url = RestServices.getAbsoluteUrl("ServiceWithLongOperation"); + + new MicroflowService("Tests.ServiceWithLongOperation", "*", HttpMethod.GET, "Service with 1 minute operation"); + + try { + RestConsumer.request(Core.createSystemContext(), HttpMethod.GET, url, null, null, false); + } catch (RestConsumeException rce) { + Assert.assertTrue(rce.getResponseData().getBody().startsWith("java.net.SocketTimeoutException")); + } finally { + RestConsumer.setGlobalRequestSettings(null, 0L); + } + } +}