StreamBase Server Ready Notification and Java Client Build Example

StreamBase Server Ready Notification and Java Client Build Example

book

Article ID: KB0079639

calendar_today

Updated On:

Products Versions
TIBCO Streaming 10

Description

How can I get notification that the server is running and the application is ready for input and output?

Issue/Introduction

Create a Java Client for detecting when a StreamBase server instance is ready

Resolution

A client application may attempt to connect before the server is ready, or after the server is ready but before the applications are ready for input and output, or sometime after the applications are ready. Ideally the client connects as soon as the applications are ready.

This guide shows how a StreamBase Java API Client ("java client") can wait for a StreamBase application to be ready. The example client described here is usable standalone in shell scripts to delay the script until an application container in the server is ready for client connections. Instructions for building the client from source-code are provided for TIBCO StreamBase and TIBCO Streaming version 10.x StreamBase Studio environments.

StreamBase Runtime startup events:
1. Install the node which starts node management services.
2. Start the node which starts the Java Virtual Machine running the StreamBase engine.

StreamBase Engine startup activities:
1. Convert EventFlow modules to bytecode .class files.
2. Load all modules and run all adapter initialization methods.
3. Open the server port for client access.

In StreamBase 10.4, the console notification that the server is ready looks like this:
2018-12-03 20:29:41.017000+0000 [176:Thread- ThreadPool - 1] INFO  com.streambase.sb.sbd.net.StreamBaseHTTPServer: sbd at 1197ed215205:10000; pid=176; version=10.4.0_e8c1cd91cb86ef9bc5f543e75582ef26f4ea36ca; Listening

Even after a server accepts client connections, containers may continue to initialize. The required container may not be immediately available. This "SBReady" client example confirms the target container is reported by the server after the client connection is made, which is a good indication the application running in that container is ready for connections.

SBReady source, sbready.java:
//
// Copyright (c) 2010-2019 TIBCO Software Inc. All rights reserved.
//
// SBReady waits for that target server and container to be running and then terminates.
// Console output may be configured using a logback.xml file.
//
// Usage: java -Dlogback.configurationFile=./logback.xml -jar sbready.jar sb://localhost:10001 default
// Output example:
// 2018-12-06 16:03:46 [INFO] SBReady - args -- uri:'sb://127.0.0.1:10001' container:'default'
// 2018-12-06 16:03:47 [INFO] SBReady - StreamBase container 'default' ready at sb://127.0.0.1:10001
//
package com.tibco.sb.support;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.streambase.sb.StreamBaseException;
import com.streambase.sb.client.StreamBaseClient;

public class SBReady {
    
    // The time to wait before retrying to connect to StreamBase, milliseconds
    private final static long TEST_RETRY_INTERVAL = 500;

    public SBReady() {
    }
    
    public static void main(String[] args) {
    	
    	Logger logger = LoggerFactory.getLogger(SBReady.class);
    	
        String uri = null;   
        String container = null;
        
        if (args.length == 2) {
            uri = args[0];
	        container = args[1];
        }
        if (uri==null || container==null) {
        	logger.info("Usage: sbready {sburi} {container}");
        	logger.info("  sburi: sb://host[:port]");
        	logger.info("  container: default, system, ...");
        	System.exit(1);
        }

    	// emit start time and args
        logger.info("SBready: uri='"+uri+"' container='"+container+"'");
    	
    	StreamBaseClient client = null;
    	boolean found = false;

    	// loop until the container exists at the target uri 
    	while (!found) {
    		
    		// if not connected, try to connect
    		if (client==null) {
                try {
                    // if no exception, then success
                    client = new StreamBaseClient(uri);
                } catch (StreamBaseException e1) {
                	client=null;
                }    		
    		}
    		
    		// if connected, check for existence of target container
    		if (client!=null) {
                try {
    	            for (String cont : client.listEntities(com.streambase.sb.EntityType.CONTAINER)) {
    	            	if(cont.matches(container)) { 
    	            		found = true;
   	            		}
    	            }
    	            if (found) {
	    	            client.close();
	    	            break;
    	            }
                } catch (StreamBaseException e) {
                	client = null;
                }
    		}

    		// delay if not found
    		if (!found) {
	            try {
	                Thread.sleep(SBReady.TEST_RETRY_INTERVAL);
	            } catch (InterruptedException interruptedException) {
	                // This can be ignored.
	            }    		
    		}
	    }

    	// emit success and exit
        logger.info("StreamBase container '"+container+"' ready at " + uri);
    }

}
Logging configuration, logback.xml:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%date{yyyy-MM-dd HH:mm:ss} [%level] %logger{0} - %msg%n</pattern>
        </encoder>
    </appender>
    <root level="INFO">
        <appender-ref ref="console" />
    </root>
</configuration>

 

Maven project setup to build a StreamBase Java Client in Studio

These are the general setup steps to build a StreamBase Java API Client application in TIBCO StreamBase Studio, with the above SBReady client as an example.

In SB Studio: 
1. Use menu: File > New > Other... > Maven > Maven Project. Click Next.
2. In the "New Maven Project" dialog, select "Create a simple project (skip archetype selection)". Click Next.
3. Provide Group Id, Artifact Id, Name, and Description (example):
    Group Id: com.tibco.sb.support
    Artifact Id: sbready
    Name: sbready
    Description: SB Ready Client
4. The default Packaging is 'jar' which is correct for this project. Click Finish.
5. In the Project Explorer, right-click folder sbready > src/main/java, choose New > Class.
6. Set:
  Source folder: sbready/src/main/java
  Package: com.tibco.sb.support (or your organization)
  Name: SBReady
7. In "Which method stubs...", set "public static void main(String[] args)". Click Finish.
8. Replace SBReady.jar file contents with the source above. Save. There will be errors.
9. Open the project pom.xml file.
10. On the "pom.xml" tab, add <dependencies> after </description>:

    <dependencies>
    	<dependency>
    		<groupId>com.tibco.ep.sb</groupId>
    		<artifactId>client-core</artifactId>
    		<version>10.4.0</version>
    	</dependency>
    	<dependency>
    		<groupId>ch.qos.logback</groupId>
    		<artifactId>logback-classic</artifactId>
    		<version>1.2.3</version>
    	</dependency>
    </dependencies>

This will add these libraries as dependencies and the errors in SBReady.java should go away:

client-core-10.4.0.jar
client-deps-10.4.0.jar
fastjson-1.2.8.jar
icu4j-58.2.jar
logback-classic-1.2.3.jar
logback-core-1.2.3.jar
slf4j-api-1.7.21.jar
It is the responsibility of the deployment engineer to copy these libraries from the Maven repository into a classpath location on the end-user's system. Similarly, the logback.xml file will need to be placed on the end-user system as well.

If the client is built now in Studio using Run as > Maven build..., Goals: "clean package", this will result in the file target/SBReady3-0.0.1-SNAPSHOT.jar which may be renamed "sbready.jar".

To deploy, on the end-user's system create a new "sbready" directory and a sub-directory named "libs". Place the files as so:
sbready/:
  sbready.jar
  logback.xml
sbready/libs/:
  (the above listed java libraries)


This may then be run using command line:
  java -Dlogback.configurationFile=logback.xml -cp .\sbready.jar;.\libs\* com.tibco.sb.support.SBReady sb://127.0.0.1:10001 default

For ease of use, create a shell-script or batch-file for this command.

Example output using logback.xml
2018-12-12 11:41:39 [INFO] SBReady - SBready: uri='sb://127.0.0.1:10001' container='default'
2018-12-12 11:43:05 [INFO] SBReady - StreamBase container 'default' ready at sb://127.0.0.1:10001


Example output without custom logging:
11:38:52.126 [main] INFO com.sb.support.SBReady - SBReady: uri='sb://127.0.0.1:10001' container='default'
11:39:31.103 [main] DEBUG com.streambase.sb.client.StreamBaseClient - StreamBase client finished normally
11:39:31.106 [main] INFO com.sb.support.SBReady - StreamBase container 'default' ready at sb://127.0.0.1:10001

Optional Build Steps to Create a Runnable "Fat" JAR

Deployment may be simplified by creating a runnable "fat" jar which contains all necessary dependencies. This allows for only two files to be copied to the end-user's system, sbready.jar and logback.xml.

1. Add the maven assembly plugin <build> after </dependencies>:

    <build>
    	<plugins>
    		<plugin>
			    <artifactId>maven-assembly-plugin</artifactId>
			    <configuration>
			        <archive>
			            <manifest>
			                <mainClass>com.sb.support.SBReady3</mainClass>
			            </manifest>
			        </archive>
			        <descriptorRefs>
			            <descriptorRef>jar-with-dependencies</descriptorRef>
			        </descriptorRefs>
			    </configuration>
			</plugin>
		</plugins>
	</build>
2. Use: Run as > Maven build..., Goals = "package assembly:single"
(or command line: mvn clean package assembly:single )

This produces two jars:
target/ 
  SBReady-0.0.1-SNAPSHOT.jar
  SBReady-0.0.1-SNAPSHOT-jar-with-dependencies.jar


The jar files are from "package" (as above) and an additional larger jar built by the "assembly:single" goal which will be used for deployment instead.
3. Copy and rename the larger library "sbready.jar".

To deploy, on the end-user's system create a new "sbready" directory and place the files as so:
sbready/:
  sbready.jar
  logback.xml


This may then be run using command line:
  java -Dlogback.configurationFile=.\logback.xml -jar sbready.jar sb://127.0.0.1:10001 default

Example output:
2018-12-10 11:43:23 [INFO] SBReady - SBReady: uri='sb://127.0.0.1:10001' container='default'
2018-12-10 11:43:47 [INFO] SBReady - StreamBase container 'default' ready at sb://127.0.0.1:10001


For ease of use, create a shell-script or batch-file for this command.

About "fat" jars, since they have all dependencies included, they are large, do not require a classpath, and cannot have individual libraries upgraded in-place. For a standalone client this may be appropriate. For most deployments more typically, instead of using a fat-jar, use a regular jar with all dependencies referenced on the classpath as in the first deployment example.

 

Attachments

StreamBase Server Ready Notification and Java Client Build Example get_app
StreamBase Server Ready Notification and Java Client Build Example get_app