Performing large data operations with JMX APIs

The Teracloud Streams JMX API uses an HTTPS implementation for transferring large data values between the client where the application runs and the server where the JMX service runs. For example, this implementation is used for client retrieval of processing element (PE) metrics and for uploading an application when a job is submitted.

To complete these operations, you must call the JMX API method to retrieve an HTTPS URI, validate the server certificate to determine whether the Teracloud Streams server is trusted, and make the HTTP call to send or receive the data.

Note If the value of the jmx.sslOption configuration property is none, an HTTP URI is returned and a non-encrypted connection is used to transfer the data.

Procedure

  1. Call the JMX API method to retrieve an HTTPS URI.

    Several JMX API methods return an HTTPS URI for a return value. For example, the InstanceMXBean.deployApplication() and JobMXBean.snapshot() methods return an HTTPS URI. This HTTPS URI is the URI to which the HTTP call must be made.

  2. Validate the Teracloud Streams certificate to determine whether the Teracloud Streams server is trusted.

    Teracloud Streams identifies itself to clients by using a self-signed certificate. Your application must validate the certificate that it receives when it establishes the HTTPS connection to the Teracloud Streams server. It can perform this validation by comparing the certificate that it received to a known certificate in a client truststore. You can use the streamtool exportkeystore -k jmxhttp command to generate a client truststore that contains the Teracloud Streams certificate. You can then use this truststore for the comparison. In addition, because the Teracloud Streams certificate is not specific to a single server, you must also provide a host name verifier to trust the certificate.

  3. Make the HTTP call to send or receive the data.

    The documentation for the JMX API methods that return an HTTPS URI includes information about which HTTP call must be made to complete the operation. This call must be made within 2 minutes of retrieving the URI. Otherwise, the URI times out and is no longer valid. This URI is only valid for a single call. Subsequent calls fail.

Example

The following Java™ code example uses the Teracloud Streams JMX API to retrieve product log entries.
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashMap;

import java.net.URL;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLSession;

import javax.management.JMX;
import javax.management.MBeanServerConnection;
import javax.management.ObjectName;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;

import com.ibm.streams.management.domain.DomainMXBean;
import com.ibm.streams.management.ObjectNameBuilder;

// javac -cp com.ibm.streams.management.jmxmp.jar:com.ibm.streams.management.mx.jar Client.java
// java -cp .:com.ibm.streams.management.jmxmp.jar:com.ibm.streams.management.mx.jar:jmxremote_optional.jar:glassfish-corba-omgapi-[version].jar:commons-cli-[version].jar 
//   Client service:jmx:jmxmp://server:9975 domainA user password TLSv1.3
// Note: It is important to include com.ibm.streams.management.jmxmp.jar in the class path before jmxremote_optional.jar
public class Client {
  public static void main(String [] args) {
    try { 
      String jmxUrl = args[0];  // use streamtool getjmxconnect to find
      String domainName = args[1];
      String user = args[2];    // use streamtool setacl to assign required permissions
      String password = args[3];
      String protocol = args[4]; // use streamtool getproperty jmx.sslOption to find
            
      HashMap<String, Object> env = new HashMap<String,Object>();
      String [] creds = {user, password};
      env.put("jmx.remote.credentials", creds);
      env.put("jmx.remote.protocol.provider.pkgs", "com.ibm.streams.management");
      env.put("jmx.remote.tls.enabled.protocols", protocol);
 
      JMXConnector jmxc = JMXConnectorFactory.connect(new JMXServiceURL(jmxUrl), env);
      MBeanServerConnection mbsc = jmxc.getMBeanServerConnection();

      ObjectName objName = ObjectNameBuilder.domain(domainName);
      DomainMXBean domain = JMX.newMXBeanProxy(mbsc, objName, DomainMXBean.class, true);
      String uri = domain.retrieveProductLog(null);

      // supply truststore to compare with certificate sent by server
      System.setProperty("javax.net.ssl.trustStore", ".\\streams_keystore.p12");  // use streamtool exportkeystore -k jmxhttp -p tspassword to retrieve
      System.setProperty("javax.net.ssl.trustStorePassword", "tspassword");  // password value specified on streamtool exportkeystore
 
      // if certificate matched for the domain, trust the server from which it was sent
      HostnameVerifier hv = new HostnameVerifier() {
        public boolean verify(String urlHostName, SSLSession session) {
          return true;
        }
      };
      HttpsURLConnection.setDefaultHostnameVerifier(hv);

      URL url = new URL(uri);
      HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
      conn.setRequestMethod("GET");
      conn.connect();
      InputStream  response = conn.getInputStream();

      BufferedReader reader = new BufferedReader(new InputStreamReader(response));
      String line;
      while ((line = reader.readLine()) != null) {
        System.out.println(line);
      }
      reader.close();
      response.close();
      conn.disconnect();
    }
    catch (Exception e) {
      e.printStackTrace();     
    }
 }
}