diff --git a/java/src/main/java/com/genexus/internet/CustomPoolingHttpClientConnectionManager.java b/java/src/main/java/com/genexus/internet/CustomPoolingHttpClientConnectionManager.java index 12db5cc30..cbd56d579 100644 --- a/java/src/main/java/com/genexus/internet/CustomPoolingHttpClientConnectionManager.java +++ b/java/src/main/java/com/genexus/internet/CustomPoolingHttpClientConnectionManager.java @@ -11,35 +11,15 @@ import java.util.ArrayList; import java.util.HashSet; import java.util.List; +import java.util.Set; import java.util.concurrent.ExecutionException; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; public class CustomPoolingHttpClientConnectionManager extends PoolingHttpClientConnectionManager { private final List observers = new ArrayList<>(); - private final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(); - - HashSet activeRoutes = new HashSet<>(this.getRoutes()); - public CustomPoolingHttpClientConnectionManager(Registry socketFactoryRegistry){ super(socketFactoryRegistry); - initializePeriodicPoolCheck(); - } - - private void initializePeriodicPoolCheck() { - Runnable task = () -> periodicPoolCheck(); - scheduler.scheduleAtFixedRate(task, 0, 30, TimeUnit.SECONDS); - } - - private void periodicPoolCheck() { - if (activeRoutes.size() > this.getRoutes().size()){ - activeRoutes.removeAll(this.getRoutes()); - for (HttpRoute route : activeRoutes) - notifyConnectionDestroyed(route); - } - activeRoutes = new HashSet<>(this.getRoutes()); } public void addObserver(IConnectionObserver observer) { @@ -60,16 +40,51 @@ public boolean cancel() { public HttpClientConnection get(long timeout, TimeUnit tunit) throws InterruptedException, ExecutionException, ConnectionPoolTimeoutException { HttpClientConnection connection = originalRequest.get(timeout, tunit); - if (connection != null && !connection.isOpen()){ + if (connection != null && !connection.isOpen()) notifyConnectionCreated(route); - activeRoutes.add(route); - } return connection; } }; } + @Override + public void closeExpiredConnections() { + Set beforeClosing = new HashSet<>(); + Set afterClosing = new HashSet<>(); + + super.enumAvailable(entry -> { + if (entry.isExpired(System.currentTimeMillis())) { + beforeClosing.add(entry.getRoute()); + } + }); + super.closeExpiredConnections(); + super.enumAvailable(entry -> afterClosing.add(entry.getRoute())); + beforeClosing.removeAll(afterClosing); + + for (HttpRoute route : beforeClosing) + notifyConnectionDestroyed(route); + } + + @Override + public void closeIdleConnections(long idletime, TimeUnit tunit) { + Set beforeClosing = new HashSet<>(); + Set afterClosing = new HashSet<>(); + long idleTimeoutMillis = tunit.toMillis(idletime); + + super.enumAvailable(entry -> { + if (entry.getUpdated() + idleTimeoutMillis < System.currentTimeMillis()) { + beforeClosing.add(entry.getRoute()); + } + }); + super.closeIdleConnections(idletime, tunit); + super.enumAvailable(entry -> afterClosing.add(entry.getRoute())); + beforeClosing.removeAll(afterClosing); + + for (HttpRoute route : beforeClosing) + notifyConnectionDestroyed(route); + } + private void notifyConnectionCreated(HttpRoute route) { for (IConnectionObserver observer : observers) observer.onConnectionCreated(route); diff --git a/java/src/main/java/com/genexus/internet/HttpClientJavaLib.java b/java/src/main/java/com/genexus/internet/HttpClientJavaLib.java index a0b08bc85..0974c0ceb 100644 --- a/java/src/main/java/com/genexus/internet/HttpClientJavaLib.java +++ b/java/src/main/java/com/genexus/internet/HttpClientJavaLib.java @@ -2,7 +2,6 @@ import java.io.*; import java.net.InetAddress; -import java.net.URI; import java.net.URISyntaxException; import java.net.UnknownHostException; import java.nio.charset.StandardCharsets; @@ -12,6 +11,7 @@ import java.security.UnrecoverableKeyException; import java.security.cert.CertificateException; import java.util.*; +import java.net.URI; import javax.net.ssl.SSLContext; import org.apache.http.*; import org.apache.http.HttpResponse; @@ -99,16 +99,6 @@ public void onConnectionDestroyed(HttpRoute route) { HTTPConnectionJMX.DestroyHTTPConnectionJMX(route); } - @Override - protected void finalize() { - this.closeOpenedStreams(); - if (Application.isJMXEnabled()){ - for (HttpRoute route : connManager.getRoutes()) - HTTPConnectionJMX.DestroyHTTPConnectionJMX(route); - HTTPPoolJMX.DestroyHTTPPoolJMX(connManager); - } - } - private ConnectionKeepAliveStrategy generateKeepAliveStrategy() { return new ConnectionKeepAliveStrategy() { @Override @@ -155,6 +145,7 @@ public void setTimeout(int timeout) private static IniFile clientCfg = new ModelContext(ModelContext.getModelContextPackageClass()).getPreferences().getIniFile(); private static final String SET_COOKIE = "Set-Cookie"; private static final String COOKIE = "Cookie"; + private java.util.Vector streamsToClose; private void closeOpenedStreams() @@ -312,7 +303,7 @@ private CookieStore setAllStoredCookies() { CookieStore cookiesToSend = new BasicCookieStore(); if (!ModelContext.getModelContext().isNullHttpContext()) { // Caso de ejecucion de varias instancia de HttpClientJavaLib, por lo que se obtienen cookies desde sesion web del browser - String selfWebCookie = ((HttpContextWeb) ModelContext.getModelContext().getHttpContext()).getCookie("Set-Cookie"); + String selfWebCookie = ((HttpContextWeb) ModelContext.getModelContext().getHttpContext()).getCookie(SET_COOKIE); if (!selfWebCookie.isEmpty()) this.addHeader(COOKIE, selfWebCookie.replace("+",";")); @@ -765,4 +756,10 @@ public void cleanup() { resetErrorsAndConnParams(); } + @Override + protected void finalize() + { + this.closeOpenedStreams(); + } + } \ No newline at end of file diff --git a/java/src/main/java/com/genexus/management/HTTPPoolJMX.java b/java/src/main/java/com/genexus/management/HTTPPoolJMX.java index fbf4afb2b..c7f57122c 100644 --- a/java/src/main/java/com/genexus/management/HTTPPoolJMX.java +++ b/java/src/main/java/com/genexus/management/HTTPPoolJMX.java @@ -28,17 +28,8 @@ static public void CreateHTTPPoolJMX(PoolingHttpClientConnectionManager httpConn } } - static public void DestroyHTTPPoolJMX(PoolingHttpClientConnectionManager httpConnectionPool) { - try { - MBeanUtils.destroyMBean(httpConnectionPool); - } - catch(Exception e) { - log.error("Cannot register HTTP connection pool MBean.", e); - } - } - public int getNumberOfConnectionsInUse(){ - return connectionPool.getTotalStats().getLeased(); + return connectionPool.getTotalStats().getAvailable(); } public int getNumberOfRequestsWaiting(){ diff --git a/java/src/main/java/com/genexus/management/MBeanUtils.java b/java/src/main/java/com/genexus/management/MBeanUtils.java index c3baae29a..0521d0f7f 100644 --- a/java/src/main/java/com/genexus/management/MBeanUtils.java +++ b/java/src/main/java/com/genexus/management/MBeanUtils.java @@ -23,9 +23,10 @@ public class MBeanUtils { private static MBeanServer mbs = null; - private static Vector registeredObjects = new Vector<>(); + private static Vector registeredObjects = new Vector(); - public MBeanUtils() {} + public MBeanUtils() { + } private static MBeanServer getMBeanServer() { @@ -280,28 +281,6 @@ public static void destroyMBean(HttpRoute httpRoute) { System.out.println(e); } } - - public static void destroyMBean(PoolingHttpClientConnectionManager httpConnectionPool) { - MBeanServer mbs = getMBeanServer(); - if (mbs == null) - return; - - try { - ObjectName name = new ObjectName("com.genexus.management:type=GeneXusApplicationServer.HTTPPool,ApplicationName=Http connection pool"); - registeredObjects.removeElement(name); - - mbs.unregisterMBean(name); - } - catch(javax.management.MalformedObjectNameException e) { - System.out.println(e); - } - catch(javax.management.InstanceNotFoundException e) { - System.out.println(e); - } - catch(javax.management.MBeanRegistrationException e) { - System.out.println(e); - } - } public static void destroyMBeanCache() {