Description of problem: Under NAT environment, assume a browser and a BPMS server are located in different network segments. for example) Server IP: 192.168.46.11 NAT-ed IP: 10.168.56.11 A browser (from a different network segment) accesses to business-central via NAT-ed IP (http://10.168.56.11:8080/business-central). Then press 'Process & Task Dashboard' from menu. ConnectException is thrown in server side. ==== 08:14:28,458 ERROR [stderr] (http-/192.168.46.11:8080-6) java.net.ConnectException: Connection timed out 08:14:28,459 ERROR [stderr] (http-/192.168.46.11:8080-6) at java.net.PlainSocketImpl.socketConnect(Native Method) 08:14:28,460 ERROR [stderr] (http-/192.168.46.11:8080-6) at java.net.PlainSocketImpl.doConnect(PlainSocketImpl.java:351) 08:14:28,460 ERROR [stderr] (http-/192.168.46.11:8080-6) at java.net.PlainSocketImpl.connectToAddress(PlainSocketImpl.java:213) 08:14:28,460 ERROR [stderr] (http-/192.168.46.11:8080-6) at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:200) 08:14:28,461 ERROR [stderr] (http-/192.168.46.11:8080-6) at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:366) 08:14:28,461 ERROR [stderr] (http-/192.168.46.11:8080-6) at java.net.Socket.connect(Socket.java:529) 08:14:28,461 ERROR [stderr] (http-/192.168.46.11:8080-6) at java.net.Socket.connect(Socket.java:478) 08:14:28,461 ERROR [stderr] (http-/192.168.46.11:8080-6) at sun.net.NetworkClient.doConnect(NetworkClient.java:163) 08:14:28,462 ERROR [stderr] (http-/192.168.46.11:8080-6) at sun.net.www.http.HttpClient.openServer(HttpClient.java:411) 08:14:28,462 ERROR [stderr] (http-/192.168.46.11:8080-6) at sun.net.www.http.HttpClient.openServer(HttpClient.java:525) 08:14:28,462 ERROR [stderr] (http-/192.168.46.11:8080-6) at sun.net.www.http.HttpClient.<init>(HttpClient.java:208) 08:14:28,463 ERROR [stderr] (http-/192.168.46.11:8080-6) at sun.net.www.http.HttpClient.New(HttpClient.java:291) 08:14:28,463 ERROR [stderr] (http-/192.168.46.11:8080-6) at sun.net.www.http.HttpClient.New(HttpClient.java:310) 08:14:28,463 ERROR [stderr] (http-/192.168.46.11:8080-6) at sun.net.www.protocol.http.HttpURLConnection.getNewHttpClient(HttpURLConnection.java:987) 08:14:28,463 ERROR [stderr] (http-/192.168.46.11:8080-6) at sun.net.www.protocol.http.HttpURLConnection.plainConnect(HttpURLConnection.java:923) 08:14:28,464 ERROR [stderr] (http-/192.168.46.11:8080-6) at sun.net.www.protocol.http.HttpURLConnection.connect(HttpURLConnection.java:841) 08:14:28,464 ERROR [stderr] (http-/192.168.46.11:8080-6) at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1195) 08:14:28,464 ERROR [stderr] (http-/192.168.46.11:8080-6) at java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:379) 08:14:28,465 ERROR [stderr] (http-/192.168.46.11:8080-6) at org.jbpm.dashboard.renderer.service.impl.DashboardRendererServiceImpl.getAppStatus(DashboardRendererServiceImpl.java:22) ... ==== A problem here is that DashboardPanelPresenter passes the NAT-ed IP (10.168.56.11) to server side and DashboardRendererServiceImpl.getAppStatus() accesses to http://10.168.56.11:8080/dashbuilder/workspace/jbpm-dashboard from the BPMS server. It throws the ConnectException because 10.168.56.11 is not accessible from the segment where BPMS is located. https://github.com/droolsjbpm/jbpm-console-ng/blob/master/jbpm-console-ng-dashboard/jbpm-console-ng-dashboard-client/src/main/java/org/jbpm/dashboard/renderer/client/panel/DashboardPanelPresenter.java#L40 # Direct access from browser to http://10.168.56.11:8080/dashbuilder/workspace/jbpm-dashboard works fine. Steps to Reproduce: 1. Under NAT environment, 2. Access to business-central via NAT-ed IP (http://10.168.56.11:8080/business-central) with A browser from a different network segment. 3. Press 'Process & Task Dashboard' from menu. Actual results: Dashbuilder page is not loaded. Server throws ConnectException. Expected results: Dashbuilder page is loaded.
Fixed on both master & 6.1.x and also backported to 6.0.x for the roll-up patch to be available. It requires further testing on customer side as I was only able to test it on my laptop. Github commit (master): https://github.com/droolsjbpm/jbpm-console-ng/commit/d7ae4f1a9ab08318432e904cee5ee86a1832f36c Github commit (6.0.x): https://github.com/droolsjbpm/jbpm-console-ng/commit/bebdf032442aa151e05cefe02cb80198d25e9311 Github commit (6.1.x): https://github.com/droolsjbpm/jbpm-console-ng/commit/530d4401ee68a19d5daad05dc5cafb555a76db10
Hi David, Before passing this to QA, I have one question. In the commit, you add InetAddress.getLocalHost().getHostAddress() for checking. It's okay in some cases but I think that the expected host/IP is the one where the application server is actually listening. Imagine that you have 2 NICs and localhost is resolved to A but BPMS is listening to B. In case of JBoss, we can grab it by System.getProperty("jboss.bind.address"). // Add jboss.bind.address try { String host = new URL(anUrl).getHost(); String bindAddress = System.getProperty("jboss.bind.address"); if (bindAddress != null && !host.equals(bindAddress)) { results.add(anUrl.replace(host, bindAddress)); } } catch (Exception e) { e.printStackTrace(); } But "jboss.bind.address" is not exactly reliable because users may have modified a configuration file (e.g. standalone.xml) not to depend on the property. Also it's not available in other containers. As a conservative (available in all java containers) rescue, how about introducing a new system property (e.g. "dashbuilder.bind.address") and let users explicitly set the IP so that DashboardRendererServiceImpl can use it later. WDYT? Toshiya
Or HttpServletRequest.getLocalAddr() is better?
Hi Toshiya, I've been thinking about how to make this more flexible in order to cope & meet the different use cases we might have. I think the more flexible approach would be to provide a system property as it's a container independent mechanism that adapts to any HW architecture. I don't like "HttpServletRequest.getLocalAddr()" as we were assuming both business-central and dashbuilder runs on the same server IP, which could not be the case. So what I'm about to do is to add the following modifications to the current implementation: // Get the dashbuilder address (defaults to localhost). String bindAddress = System.getProperty("dashbuilder.bind.address"); if (StringUtils.isBlank(bindAddress)) { bindAddress = InetAddress.getLocalHost().getHostAddress(); }
Last changes pushed. Github commit (master): https://github.com/droolsjbpm/jbpm-console-ng/commit/f1546db5cfd8ccde7e821a5b5bc94dcc9e35a532 Github commit (6.0.x): https://github.com/droolsjbpm/jbpm-console-ng/commit/89cc325f6d8555a42eb84899fc3f6c9f5b00710a Github commit (6.1.x): https://github.com/droolsjbpm/jbpm-console-ng/commit/5ec3102f7a72cd466bfee8b2809daf1183649d1b
Hi David, Thank you for the fix. Sorry to bother you again, but could you add "dashbuilder.bind.port" as well? It's common that there is a front-end server which expose a different port (with or without NAT). IMHO, the other idea is a direct access test from browser side which may be more straightforward. I'm not sure if testing from server side is important though.
Added "dashbuilder.bind.port" Github commit (master): https://github.com/droolsjbpm/jbpm-console-ng/commit/a9fb16b374d605d60e5d31a2efe792e76850c1be Github commit (6.0.x): https://github.com/droolsjbpm/jbpm-console-ng/commit/f2c52717e904c6875b00258203c3ead306b86304 Github commit (6.1.x): https://github.com/droolsjbpm/jbpm-console-ng/commit/70d1beabb9ff4da892e409ccd513846f54815855
Toshiya, would the customer be able to lend us a hand with verification of the fix? We don't have the proper environment at hand. Thanks!
According to the previous Toshiya's comment about missing ConnectionTimeout in DashboardRendererServiceImpl.pingUrl(), setting back to ASSIGNED.
Please remove also the main method from DashboardRendererServiceImpl class. https://github.com/droolsjbpm/jbpm-console-ng/blob/6.0.x/jbpm-console-ng-dashboard/jbpm-console-ng-dashboard-backend/src/main/java/org/jbpm/dashboard/renderer/service/impl/DashboardRendererServiceImpl.java#L81
> I noticed that DashboardRendererServiceImpl.pingUrl() doesn't have set ConnectionTimeout so it may wait forever (depends on JDK default) before trying the URL which was composed by dashbuilder.bind.address & dashbuilder.bind.port. So the points are: 1) set ConnectionTimeout 2) ping the URL which was composed by dashbuilder.bind.address & dashbuilder.bind.port first (if not, users will always wait for the first URL timeout)
Fixed. Now only a single URL ping is executed. Also, a default connection timeout of 1 second has been set (can be modified via the system property: dashbuilder.bind.timeout) Github commit (master): https://github.com/droolsjbpm/jbpm-console-ng/commit/706052e46b08304c1199b285c8ad6c5f8e910f92 Github commit (6.0.x): https://github.com/droolsjbpm/jbpm-console-ng/commit/21034370bd222f7a356a4821cb6939572a379b91 Github commit (6.1.x): https://github.com/droolsjbpm/jbpm-console-ng/commit/f19ad7ab485b94fc55c8bec7072e7e89fdd354e6
Thanks David! Just in case, here are other additional commits which were done by David for the fix in comment#24. Github commit (master): https://github.com/droolsjbpm/jbpm-console-ng/commit/9b81fe8d81aa232804778f7a6f6b6be3904bc05a Github commit (6.0.x): https://github.com/droolsjbpm/jbpm-console-ng/commit/dcca1b97962ba744bf2327cb9497f224a5d3db5b Github commit (6.1.x): https://github.com/droolsjbpm/jbpm-console-ng/commit/368f58d668a359844e2b731aa0430b7dfa25abc7 So if the productization team will cherry-pick the commits from 6.0.x branch, need to pick dcca1b97962ba744bf2327cb9497f224a5d3db5b and 21034370bd222f7a356a4821cb6939572a379b91.
I managed to reproduce the issue locally with 6.0.2.GA. Once the rebuild of 6.0.3 arrives, I will verify the issue is fixed there.
Verified that the provided properties dashbuilder.bind.address and dashbuilder.bind.port as expected. I have been able to access the screen "Dashboards -> Process & Task Dashboard" in the simulated NAT environment.