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
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.
This should be changed, since it's quite critical. 🙂
Maybe there is a way to achieve this.
Thanks and best Regards
Moritz
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
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)
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
Thanks. XiaoPing, I have fixed the issue after I added the related Java jar files into the Application.