Skip to Content
Author's profile photo Xiaoping Zheng

SDK: Using program to change BO server command line parameter

Currently if you want to change the BO server parameter, such as adding “-trace”, you have to log on to CMC, open the Properties dialog and do the change there. In some cases, the users will limit the usage of CMC. It means sometimes they will want a way do to this changing without CMC. To achieve this, we can use BO SDK to create a program and use the program to change the command line.

Below is a simple java sample code. The logic is quite simple. First reading the input to get the user info to log on the system. And run a CMS query to get the infoobject of the Server. Then, using the interface IConfiguredContainer and IExecProps to read and write the command line parameter.

  • In this sample, the input from the command line is as the below format:
    -cms <cms> -username <username> -password <password> -serverid <serverid> -authentication <authentication>
    Parameter authentication is optional. If no input it will use secEnterprise. Parameter serverid is the SI_ID of the server which you want to perform the change.
package bosdk;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;

import com.businessobjects.sdk.plugin.desktop.common.IConfiguredContainer;
import com.businessobjects.sdk.plugin.desktop.common.IExecProps;
import com.crystaldecisions.sdk.framework.CrystalEnterprise;
import com.crystaldecisions.sdk.framework.IEnterpriseSession;
import com.crystaldecisions.sdk.framework.ISessionMgr;
import com.crystaldecisions.sdk.occa.infostore.IInfoStore;
import com.crystaldecisions.sdk.plugin.desktop.server.ExpectedRunState;
import com.crystaldecisions.sdk.plugin.desktop.server.IServer;

public class ChangeServerCommandLine {

	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static void main(String[] args) {

		// Process the input parameter
		Map<String, String> m_args = null;
		if (args.length > 0) {
			m_args = new HashMap();
			parseArgs(args, m_args);
		} else {
			System.err.println(
					"Arguments not passed. Usage:-cms <cms> -username <username> -password <password> -serverid <serverid> and -authentication <authentication> Note: authentication argument is optional");

			System.exit(0);
		}
		String cms = (String) m_args.get("cms");
		String username = (String) m_args.get("username");
		String password = (String) m_args.get("password");
		String serverid = (String) m_args.get("serverid");

		if ((username == null) || (password == null) || (cms == null) || (serverid == null) || (username.length() == 0)
				|| (password.length() == 0) || (cms.length() == 0) || (serverid.length() == 0)) {
			System.err.println(
					"Arguments not passed. Usage:-cms <cms> -username <username> -password <password> -serverid <serverid> and -authentication <authentication> Note: authentication argument is optional");

			System.exit(0);
		}
		String authentication = (String) m_args.get("authentication");
		if ((authentication == null) || (authentication.length() <= 0)) {
			authentication = "secEnterprise";
		}

		IEnterpriseSession enterpriseSession = null;
		ISessionMgr enterpriseSessionMgr;
		try {
			// Login and get the server infoobject
			enterpriseSessionMgr = CrystalEnterprise.getSessionMgr();
			enterpriseSession = enterpriseSessionMgr.logon(username, password, cms, authentication);
			IInfoStore infostore = (IInfoStore) enterpriseSession.getService("InfoStore");
			String serverQuery = "select * from CI_SYSTEMOBJECTS where SI_ID = " + serverid;
			IServer server = (IServer) infostore.query(serverQuery).get(0);

			// Get the server command parameter
			IConfiguredContainer cfgContainer = server.getContainer();
			IExecProps execProps = cfgContainer.getExecProps();

			// Print Current Server name and command line info
			System.out.println("Server you want to change is: " + server.getTitle());
			System.out.println("Command line before change: " + execProps.getArgs());

			// Prompt user to input the new command line
			System.out.println("Please input the new command line: ");

			InputStreamReader is = new InputStreamReader(System.in);
			BufferedReader br = new BufferedReader(is);
			String command = br.readLine();

			// Change the command line
			execProps.setArgs(command);

			// Prompt user to input if server will be restarted now
			System.out.println("Please tell us whether you want to restart the server: (yes or no)");

			is = new InputStreamReader(System.in);
			br = new BufferedReader(is);
			String restart = br.readLine();

			// if yes, restart server
			if (restart.toLowerCase().equals("yes")) {
				server.setExpectedRunState(ExpectedRunState.RESTART);
			}

			// Save the change and print the process is done.
			server.save();
			System.out.println("Change is done! New command line after change: " + execProps.getArgs());

		} catch (Exception e) {
			System.out.println(e.getMessage());
		}
	}

	private static void parseArgs(String[] args, Map<String, String> m_args) {
		for (int i = 0; i < args.length; i++) {
			if (args[i].startsWith("-")) {
				String arg = trimArg(args[i]);
				if (arg.length() != 0) {
					i++;
					String value = "";
					if (i < args.length) {
						value = args[i];
						if (value.startsWith("-")) {
							value = "";
							i--;
						}
					}
					m_args.put(arg, value);
				}
			}
		}
	}

	private static String trimArg(String arg) {
		if (arg == null) {
			return arg;
		}
		int i = 0;
		for (i = 0; i < arg.length(); i++) {
			if (arg.charAt(i) != '-') {
				break;
			}
		}
		String trimmedArg = arg.substring(i);
		return trimmedArg;
	}

}

To run this code, you will also need to include the basic jar files, such as: cecore.jar, celib.jar. cesdk.jar, cesession.jar and etc. All the jar files can be found in the BO installation folder as the following path in a windows installation:
<bo installation>\SAP BusinessObjects Enterprise XI 4.0\java\lib

Assigned Tags

      5 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Moritz Hoedel
      Moritz Hoedel

      Hi Xiaoping Zheng,

      Also thanks for sharing this script.
      I can imagine that this is provided "as-is", but for this I would have some ideas, too.

      • There should be a confirmation prompt (e.g. Y/N) if you actually want to change the server's command line parameter. There is one for the server restart, but not for the actual change.
      • If you don't enter a new string, the corresponding server's command line parameter will be empty afterwards (the server configuration is corrupted).
        This should be changed, since it's quite critical. 🙂
      • Maybe some text-/xml-based backup could be integrated, to avoid unwanted loss of config data. It's at least already printed on the screen, but having a file would be better imo.
      • I can understand that the -serverid parameter is not based on the actual PID, but the SI_ID of the server, since it's BI4 SDK, but It would be helpful anyway if this could be done via PID and not using SI_ID (e.g. since this is displayed at a first glance in the CMC's Servers view).
        Maybe there is a way to achieve this.

      Thanks and best Regards
      Moritz

      Author's profile photo Xiaoping Zheng
      Xiaoping Zheng
      Blog Post Author

      Hi Moritz,

      Thanks for your comment.
      Actually the sample code I shared is just one example for references. Of course some more complex logic or judgement can be added with the user's actual needs.
      For your 4th point, if you want to use PID to filter the server, you can change the code which filter the server infoobjects

      String serverQuery = "select * from CI_SYSTEMOBJECTS where SI_ID = " + serverid;

      to

      String serverQuery = "select * from CI_SYSTEMOBJECTS where SI_PID = " + server_pid;

       

      However, PID will be always changing after server gets restarted. SI_ID won't only if you delete and recreate that server. That's why my example used SI_ID.

      Regards,
      Xiaoping

      Author's profile photo Ben Wong
      Ben Wong

      Hi, Xiaoping Zheng,

      Thanks for sharing this script. I got the problem to run this script. Is any jar file missing or the other issue?

      Exception in thread "main" java.lang.NullPointerException: while trying to invoke the method java.lang.ClassLoader.getResourceAsStream(java.lang.String) of a null object returned from java.lang.Class.getClassLoader()
      at com.crystaldecisions.celib.classloader.ClassLoaderHelper$2.getResourceAsStream(ClassLoaderHelper.java:102)
      at com.crystaldecisions.celib.classloader.ClassLoaderHelper.getResourceAsStream(ClassLoaderHelper.java:149)
      at com.crystaldecisions.sdk.framework.internal.SessionMgr.initializeSystemProperties(SessionMgr.java:477)
      at com.crystaldecisions.sdk.framework.internal.SessionMgr.<init>(SessionMgr.java:469)
      at com.crystaldecisions.sdk.framework.internal.CEFactory.makeSessionMgr(CEFactory.java:94)
      at com.crystaldecisions.sdk.framework.CrystalEnterprise.getSessionMgr(CrystalEnterprise.java:121)
      at test.test.main(test.java:56)

      Author's profile photo Xiaoping Zheng
      Xiaoping Zheng
      Blog Post Author

      Hi Ben Wong,

      I don't think my code above involved some ConnectionServer classes and functions which is observed in the stack trace. To be honest I am not sure why you face this error. Can you perform a debug to let me know from which line of the code the error occurs? And how you execute the program and what is your input?

      Regards, Xiaoping

      Author's profile photo Ben Wong
      Ben Wong

      Thanks. XiaoPing, I have fixed the issue after I added the related Java jar files into the Application.