Saturday, May 28, 2016

Integration Cloud Service (ICS): Execution Agent proxy issue: NumberFormatException

Integration Cloud Service (ICS) offers an Execution Agent which you can download and install on-premises. This provides a local ICS instance. The Execution Agent is useful in several situations. When you have an ICS trial, it is valid only for a period of 30 days. After initial installation (which does require an ICS subscription), you can use the Execution Agent indefinitely. Secondly, you have full control over the Execution Agent since it is a local installation and not managed by Oracle such as the Oracle Cloud instances. This means you can for example log all requests and replies, install and test a custom Cloud Adapter or browse the Service Bus log files and deployments in case something goes wrong. Currently this is not possible in the Oracle Public Cloud without creating SR's. This blog post is based on the below version of ICS and might not be valid in future versions.


You can download the Execution Agent from the Agents page:


The installation requires Oracle Enterprise Linux 6 UC4 or above. Read the documentation here.

Execution Agent proxy error

When the Execution Agent is installed though, you will most likely encounter the following error sooner or later when accessing remote resources:


When you check the log files you can see the following error:

Caused By: java.lang.NumberFormatException: For input string: "''"          
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.lang.Integer.parseInt(Integer.java:481)
at java.lang.Integer.parseInt(Integer.java:527)
at oracle.cloud.adapter.api.util.NetworkUtil.createConnectionConfig(NetworkUtil.java:309)
at oracle.cloud.adapter.api.util.NetworkUtil.setupConnection(NetworkUtil.java:424)

As you can see from this stack trace, the error originates from NetworkUtil.java:309 when the java.lang.Integer.parseInt method is called. Using JD (Java Decompiler) the error can be traced back to the following line of code;

connConfig.setProxyAddress(new InetSocketAddress(proxyHost, Integer.parseInt(proxyPort)));

Thus the error is caused by an empty proxyPort. During the installation of the Execution Agent, I needed to answer several questions:

Enter your ICS subscription URL for authentication:
Enter ICS subscription Username:
Enter ICS subscription Password:
Enter HTTPS Proxy Server Host Name:
Enter HTTPS Proxy Server Port Number:

I just pressed enter when asked for proxy settings.

How to solve it

There are 2 easy ways to solve this. First disable the proxy and second start using a proxy. After the installation you can change the proxy settings by editing:

ICSOPInstall/ICSOP/data/user_projects/domains/compact_domain/bin/setICSDomainEnv.sh

This file contains the proxy settings:

#!/bin/sh
EXTRA_JAVA_PROPERTIES="${EXTRA_JAVA_PROPERTIES} -Dhttps.proxyHost= -Dhttps.proxyPort= -Dhttp.proxyHost= -Dhttp.proxyPort="
EXTRA_JAVA_PROPERTIES="${EXTRA_JAVA_PROPERTIES} -Dweblogic.security.SSL.minimumProtocolVersion=TLSv1.0"
EXTRA_JAVA_PROPERTIES="${EXTRA_JAVA_PROPERTIES} -DExecutionContext=ICS_ON_PREMISE"
export EXTRA_JAVA_PROPERTIES

Fix 1: Disable the proxy

These proxy settings were interpreted as empty strings which of course cannot be parsed to integers. In the NetworkUtil code, you can see in the NetworkUtil class code that if the proxyHost or proxyPort is not null, that the proxy will be used which causes this error. An empty string is of course not null. When I comment the below line in setICSDomainEnv.sh, the proxy settings are null though.

#EXTRA_JAVA_PROPERTIES="${EXTRA_JAVA_PROPERTIES} -Dhttps.proxyHost= -Dhttps.proxyPort= -Dhttp.proxyHost= -Dhttp.proxyPort="

The result of this is that ICS will not use a proxy server anymore.

Fix 2: Install a proxy server

Sometimes it can be difficult to debug ICS. See also my post here. It can help to have an external proxy server which can log all the incoming and outgoing requests. This way you can see exactly what ICS is sending, including all the headers and the exact response. You can use for example Squid or the JDeveloper HTTP analyser.

Squid

Installing a proxy server on Oracle Enterprise Linux is easy: 'sudo yum install squid' and you are done. By default this proxy server only accepts connections from localhost and runs on port 3128. So now you can supply localhost as proxy server and port 3128 as proxy port. This way ICS will not complain about missing proxy ports and you can use Squid for some additional logging on requests and replies.


JDeveloper HTTP Analyser

An alternative (which does require a bit more memory and diskspace) is to use the JDeveloper HTTP analyzer for this. If you are running a VM and JDeveloper is installed outside of the VM, you could encounter errors like

Caused by: javax.net.ssl.SSLKeyException: Hostname verification failed: HostnameVerifier=weblogic.security.utils.SSLWLSHostnameVerifier, hostname=vmserver.
at weblogic.security.SSL.jsseadapter.JaSSLEngine.doPostHandshake(JaSSLEngine.java:677)
at weblogic.security.SSL.jsseadapter.JaSSLEngine.doAction(JaSSLEngine.java:748)
at weblogic.security.SSL.jsseadapter.JaSSLEngine.unwrap(JaSSLEngine.java:132)
at weblogic.socket.JSSEFilterImpl.unwrap(JSSEFilterImpl.java:603)
at weblogic.socket.JSSEFilterImpl.unwrapAndHandleResults(JSSEFilterImpl.java:507)
at weblogic.socket.JSSEFilterImpl.doHandshake(JSSEFilterImpl.java:96)
at weblogic.socket.JSSEFilterImpl.doHandshake(JSSEFilterImpl.java:75)
at weblogic.socket.JSSESocket.startHandshake(JSSESocket.java:219) 

When you have JDeveloper and the HTTP Analyser installed inside the same VM as the Execution Agent, you will not encounter this issue.