Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Starting bbcomm in Java v3 Bloomberg API

When I use the Java Bloomber V3 API it usually works. However, sometimes, especially after a reboot, bbcomm.exe is not running in the background. I can start it manually by running blp.exe, but I wondered if there was a way of doing this via the API?

I'm still waiting on Help-Help ...

like image 909
Nick Fortescue Avatar asked Dec 10 '09 12:12

Nick Fortescue


2 Answers

After talking to the help desk, it turns out that on 64 bit Windows, running under a 64bit JVM bbcomm is not automatically started. This does not happen under 32bit Java - under 32 bit bbcomm automatically runs.

So my solutions are either to wait for the problem to be fixed by Bloomberg (now I understand it) or to check this specific case.

To check the specific case:

  • if running under a 64 bit windows (System property os.arch)
  • and if running under a 64bit JVM (System property java.vm.name)
  • then try and start a session
  • If this fails, assume bbcomm.exe is not running. Try to run bbcomm.exe using Runtime.exec()

I haven't tested the above yet. It may have exactly the same issues as Bloomberg have with 64bit VMs.

like image 53
Nick Fortescue Avatar answered Oct 13 '22 13:10

Nick Fortescue


After spending some time with Help Help, it seems that bbcomm gets started either when you use the Excel API or run the API demo. But it does not get started automatically when called from the Java API. Possible ways to start it are:

  • adding an entry in the registry to automatically start bbcomm on startup: in HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run add a String value called bbcomm with value C:\blp\API\bbcomm.exe - but that opens a command window which remains visible, so not really an option (and if you close that window it terminates the bbcomm process)
  • create a batch file START /MIN C:\blp\API\bbcomm.exe and replace the entry in the registry with that (not tested) to call bbcomm silently
  • manually launch bbcomm from your java code as already suggested. As a reference, I post below the code that I'm using.
private final static Logger logger = LoggerFactory.getLogger(BloombergUtils.class);
private final static String BBCOMM_PROCESS  = "bbcomm.exe";
private final static String BBCOMM_FOLDER  = "C:/blp/API";

/**
 * 
 * @return true if the bbcomm process is running
 */
public static boolean isBloombergProcessRunning() {
    return ShellUtils.isProcessRunning(BBCOMM_PROCESS);
}

/**
 * Starts the bbcomm process, which is required to connect to the Bloomberg data feed
 * @return true if bbcomm was started successfully, false otherwise
 */
public static boolean startBloombergProcessIfNecessary() {
    if (isBloombergProcessRunning()) {
        logger.info(BBCOMM_PROCESS + " is started");
        return true;
    }

    Callable<Boolean> startBloombergProcess = getStartingCallable();
    return getResultWithTimeout(startBloombergProcess, 1, TimeUnit.SECONDS);
}

private static Callable<Boolean> getStartingCallable() {
    return new Callable<Boolean>() {
        @Override
        public Boolean call() throws Exception {
            logger.info("Starting " + BBCOMM_PROCESS + " manually");
            ProcessBuilder pb = new ProcessBuilder(BBCOMM_PROCESS);
            pb.directory(new File(BBCOMM_FOLDER));
            pb.redirectErrorStream(true);
            Process p = pb.start();
            BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
            String line;
            while ((line = reader.readLine()) != null) {
                if (line.toLowerCase().contains("started")) {
                    logger.info(BBCOMM_PROCESS + " is started");
                    return true;
                }
            }
            return false;
        }
    };

}

private static boolean getResultWithTimeout(Callable<Boolean> startBloombergProcess, int timeout, TimeUnit timeUnit) {
    ExecutorService executor = Executors.newSingleThreadExecutor(new ThreadFactory() {

        @Override
        public Thread newThread(Runnable r) {
            Thread t = new Thread(r, "Bloomberg - bbcomm starter thread");
            t.setDaemon(true);
            return t;
        }
    });
    Future<Boolean> future = executor.submit(startBloombergProcess);

    try {
        return future.get(timeout, timeUnit);
    } catch (InterruptedException ignore) {
        Thread.currentThread().interrupt();
        return false;
    } catch (ExecutionException | TimeoutException e) {
        logger.error("Could not start bbcomm", e);
        return false;
    } finally {
        executor.shutdownNow();
        try {
            if (!executor.awaitTermination(100, TimeUnit.MILLISECONDS)) {
                logger.warn("bbcomm starter thread still running");
            }
        } catch (InterruptedException ex) {
            Thread.currentThread().interrupt();
        }
    }
}

ShellUtils.java

public class ShellUtils {

    private final static Logger logger = LoggerFactory.getLogger(ShellUtils.class);

    /**
     * @return a list of processes currently running
     * @throws RuntimeException if the request sent to the OS to get the list of running processes fails
     */
    public static List<String> getRunningProcesses() {
        List<String> processes = new ArrayList<>();

        try {
            Process p = Runtime.getRuntime().exec(System.getenv("windir") + "\\system32\\" + "tasklist.exe");
            BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));
            String line;
            int i = 0;
            while ((line = input.readLine()) != null) {
                if (!line.isEmpty()) {
                    String process = line.split(" ")[0];
                    if (process.contains("exe")) {
                        processes.add(process);
                    }
                }
            }
        } catch (IOException e) {
            throw new RuntimeException("Could not retrieve the list of running processes from the OS");
        }

        return processes;
    }

    /**
     * 
     * @param processName the name of the process, for example "explorer.exe"
     * @return true if the process is currently running
     * @throws RuntimeException if the request sent to the OS to get the list of running processes fails
     */
    public static boolean isProcessRunning(String processName) {
        List<String> processes = getRunningProcesses();
        return processes.contains(processName);
    }
}
like image 24
assylias Avatar answered Oct 13 '22 14:10

assylias