Skip to Content
Author's profile photo Former Member

MI LAD: Tool for deploying MI app without using MI WebConsole


The Mobile Development Kit (MDK) offers several functionalities that help MI   application developers easen their tasks. One thing that is not supported   however by MDK is the temporary deployment of the application-under-work into   the installed MI client. Mobile application development process thus *requires* a running middleware to which developers can temporarily   register and upload their dummy application archive (which includes the   metadata xml for SmartSync applications), assign them to their MI client thru an   MI WebConsole, and deploy it.

Personally, this is somewhat undesirable. I don’t think that synchronization with the middleware is already a *must* on the very first phase of realizing a client application. Can’t I temporarily deploy my application into my MI client WITHOUT having a Web Console? What if I don’t have a network connection and was asked to create to simple Generic Sync application thru the phone? Can’t I develop and run a test on my application without the help of a WebConsole?

I’m pretty confident that most client-side MI application developers do have this question in mind. And my answer to this question is, *YES*, we can temporarily deploy our application-under-work into our MI client and run a test on it. In this way, we could initially check on the application’s UI, create local data, and be able to check on the business logic as well without having the need of getting our data from the middleware. When our application is ready for the system integration (synchronization) test, this is then the phase when we need the middleware.

Target MI Version

This tool uses MI public APIs as well as some of the implementation classes to simulate the deployment process in the client. The tool was tested with MI 2.5 SP14 & SP15 client. If there are no changes in the implementation classes on the later SP versions, the code might work as well, but I would suggest you to test it and please give feedback so that I can update this article also.

The Mobile Component Descriptor

I had described regarding the +Mobile Component Descriptor +in my   previous blog: How to access MCD info from the MI client registry. I would suggest you read this article before proceeding   with this article if you like to understand how this information is used by MI. </p>

Deployment Procedure

In the actual component deployment process, the client retrieves the registry   info from the MI server during the synchronization. The MI client compares the   local registry with that from the MI server. If there are components not   available in the client, the framework will try to install the components by   creating the corresponding MCD entry and then downloading the necessary   installation archives like +war +or jar files basing on the MCD   attributes on the archives location.</p>

MI Local Application Deployer (LAD)

I would like to introduce a simple tool that I had been using… I’ll name it as MI LAD.

The MI local application deployer described in this article simulates the handling of the said information and will try to install the application which exists in the local PC, i.e. your archive e.g. war file is located in your computer. The code also include an event to remove an application, however the application files and data are left and should be manually removed after the MI is shutdown.

I have chosen the use of JSP to make things simple. The JSP code is listed in Listing 1 at the end of this article. The code is pretty straight-forward and I guess the reader will easily understand it.

Installation Procedure

Logon to MI and access http://localhost:4444/LAD webappsme folder. A directory will be created with the name LAD having only one JSP page under it named index.jsp. The   file’s location however is a free web hosting site and I cannot guarantee if it   will stay for so long. Anyway you have the procedures above… You can get the   file from this link.

[ |]

MI LAD Screenshot

The code is pretty simple and I will avoid discussing it in details. The source is also available in JSP file, thus it would be very easy for you to study and experiment on it. In this section, I will just show you how it looks and how to use it.

The Front Page

The Figure 1 shows you the main screen of the MI LAD. The upper table lists the deployed components of the client device. The form on the lower portion serves as the entry dialog for the MCD information of our application to be deployed to our MI.


*Figure 1. The MI Local Application Deployer (MI LAD) *

MI LAD: Application Deployment

In this section I will show you how to deploy a SmartSync application WAR file which is in my local PC. Now, using MI LAD, I will try to deploy it into my MI installation, which is the same MI which runs MI LAD.

Now,   access MI LAD by entering http://localhost:4444/LAD in the address   box of your browser. The same page just like what is shown in Figure 1 will   appear.

    1. As shown in Figure 4, specify the MCD info and location of the WAR archive. In this example, the application to be deployed is a SmartSync application and the meRepMeta.xml is included in the archive.


*Figure 4. The MI LAD form with MCD info entries*


After   entering all the necessary information, press on add button. The result   will be displayed as shown in the Figure 5.


*Figure 5. The deployment result screen*


    1. Restart MI. And now checking on the data directory, we can see that our application’s metadata was successfully serialized as shown in the Figure 6. (Take note that the deployed application was a SmartSync application)


*Figure 6. The shared data folder which contains the metadata *


    1. And our application was successfully copied into the webapps directory as shown in Figure 7.


*Figure 7. The application archive copied in the webapps folder *


    1. After we restart the MI client, we now have the link to our application in the MI main page (Figure 8) as well as in the MI info (Figure 9).


*Figure 8. The MI page with the locally deployed application link*



*Figure 9. The MI Info page with the locally deployed application MCD entry.*


    1. Let’s try running our application and create some data (Figure 10).


*Figure 10. Creating a data in the deployed application*


    1. After we create some data, (in the example, I created 10 header entries) we can now see some data added into the data directory of our application as shown in Figure 11.



*Figure 11. The separate data folder with the inserted header data *

Now, what do you think? Wasn’t it simple?

MI LAD: Application Removal

To remove the deployed application, select on the *DEL *link under the Action column of the MCD table as shown in Figure 5. This operation will only remove the application from the MI client registry. The data folders and the application files remain in the client and should be manually removed when the MI is shut down. During runtime, MI references to these files and could not be removed by our MI LAD. In the future, I will try adding some SmartSync codes that will remove all the data thru the persistence API call. The application file under the webapps directory may be removed as well if necessary.

When you try to synchronize your MI client having the locally deployed component info, it will be removed by the framework when it tries to compare the registry in the client and in the middleware. If you want to execute the sychronization test with your middleware, then you have to register your application and deploy it thru the MI WebConsole. Your application must be assigned with a valid conversation ID that is generated by the server for it to synchronize with the middleware properly.


I had described here a very simple tool for locally deploying an application archive. I do hope that this tool will help you in developing your client application offline without a need of an MI WebConsole. In such way, one can develop the client application in parallel with the server-side developments.

The code of MI LAD uses the implementation classes of MI. And it might not work in the future releases of MI if the implementation classes are changed. Since the code is in JSP, it will be very easy for you to do the necessary code update if ever there will be changes in the invoked implementation classes.

Lastly, sorry for the UI. I just made it as simple as possible to avoid complicated codes and putting them into just one file for portability reasons. I leave it all to you to make the UI of your choice and extend the code as desired.

Author’s Note

The original post of this article could be found at . My SAP MI related tools/articles and blogs are posted at and respectively. Though from time to time, I will do some repost of articles that I found benificial to fellow MIers here at SDN.

And by the way, I would like to thanks Craig for granting my request for SDN weblogger and for moving my old blogs to my new SDN ID. 🙂   </p>


The JSP code of the tool is described below. I put the all the functions in the lower portion of the file. If you want to use a servlet rather than the JSP, you can do it as well. Be sure also that you’re using JDK instead of a JRE.

The MI Local Application Deployer

<hr align=”left” width=”100%” noshade=”noshade” />
<span class=”style1″><%@ page language=”java” contentType=”text/html;   charset=Shift_JIS”%><br/>
<%@ page import=”*”   %><br/>
<%@ page import=”*” %><br/>
<%@ page   import=”*”%><br/>
<%@ page   import=”*”%><br/>
<%@ page   import=”*”%><br/>
<%@ page   import=”*”%></span>
<p class=”style1″><%! <br />

  final String  APPNAME = “appName”;

  final   String  APPVERS = “appVersion”;

  final String  APPDESC =   “appDescription”;

  final String  APPNMSP = “appNamespace”;

  final String    APPLOCT = “appLocation”;

  final String  APPBKUP = “appBackup”;

  final   String  APPTYPE = “appType”;

final String  EVNTSTR = “event”;

  final String  EVNTADD =   “ADD”;

  final String  EVNTDEL = “DEL”;<br />
<p class=”style1″><!DOCTYPE HTML PUBLIC “-//W3C//DTD HTML 4.01   Transitional//EN”><br/>
  <%<br />
User currentUser =   UserManager.getInstance().getCurrentUser();  <br/>
String msg =   processEvent(request);  <br/>
  <style   type=”text/css”><br/>
  a {  font-family: “Tahoma”, “Verdana”; font-size:   xx-small; font-weight: bold; color: #FF9900; text-decoration: none}<br/>
  .jgtext   {  font-family: “Arial”, “Helvetica”, “sans-serif”; font-size: xx-small; color:   #666666; text-decoration: none}<br/>
  .jgheader {  font-family: “Tahoma”,   “Verdana”; font-size: xx-small; font-weight: bold; color: #006600;   text-decoration: none}<br/>
  .jgtext2 { font-family: “Arial”, “Helvetica”,   “sans-serif”; font-size: xx-small; color: #333333; text-decoration: none   }<br/>
  .jgheader2 { font-family: “Arial”, “Helvetica”, “sans-serif”; font-size:   xx-small; color: #333333; text-decoration: none ; font-weight:   bolder}<br/>
  .jgtext2bold {<br/>
font-family:   “Arial”, “Helvetica”,   “sans-serif”;<br/>
font-size: xx-small;  <br/>
color: #333333;  <br/>
text-decoration:   none;  <br/>
font-weight: bold;  <br/>


  .expand <br />
<p class=”style1″><% if(currentUser==null){  %><br/>
  <meta   http-equiv=”refresh” content=”3;   URL=http://localhost:4444″><br/>
  <meta   http-equiv=”Content-Type” content=”text/html;   charset=Shift_JIS”><br/>
  <title>MI Local Application Deployer (LAD)   </title><br/>
<p class=”style1″><body></p>
<p class=”style1″><table width=”100%” border=”0″ cellspacing=”0″   cellpadding=”0″><br/>
  <tr class=”jgheader2″ ><br/>
  <td colspan=”6″   ><br/>
  <% if(currentUser!=null){  %><br/>
Deployed Applications   for   <%=currentUser.getUniqueName()%><br/>
  <% }else{%><br/>
Please LOGON. Redirecting to ME page in 3 seconds…  <br/>
  <% }   %><br/>
  <tr  class=”jgheader2″   bgcolor=”aquamarine”><br/>
  <td >Namespace</td><br/>
  <td   >Name</td><br/>
  <td >Version</td><br/>
  <td   >Description</td><br/>
  <td >Id</td><br/>
  <td   >Type</td><br/>
  <td >Action</td>    <br/>
  <%<br />
if(currentUser!=null){  <br/>
MobileSolutionDescriptor[] msds =   ConversationIdHandler.getInstance().getAllMobileSolutionDescriptorsForUser(currentUser);  <br/>
for(int i=0; i  <msds.length; i++){<br />
%  ><br/>
  <tr  class=”jgtext2″    bgcolor=<%out.print((i%2 == 1)  “‘lavender'” : “‘white'”);%>><br/>
  <td ><%=msds[i].getNamespace()%></td><br/>
  <td   ><%=msds[i].getName()%></td><br/>
  <td   ><%=msds[i].getVersion()%></td><br/>
  <td   ><%=msds[i].getDescription()%></td><br/>
  <td   ><%=msds[i].getId()%></td><br/>
  <td   ><%=msds[i].getType().toString()%></td><br/>
  <td   ><%if(!”Framework”.equals(msds[i].getType().toString())){%>[DEL | <%=createDelLink(msds[i].getName(),msds[i].getVersion())%>]<%}%></td><br/>
  <%<br />
}  <br/>
}  <br/>
%  ><br/>
  <tr><td   colspan=”7″ bgcolor=”aquamarine”   height=”1pt”></td></tr><br/>
  <form   name=”tForm” id=”tForm” action=” ” method=”post”><br/>
  <table width=”100%”   border=”0″ cellspacing=”0″ cellpadding=”0″><br/>
  <tr ><br/>
  <td   colspan=”2″ class=”jgheader2″>Deploy Application:</td><br/>
  <tr ><br/>
  <td colspan=”2″ class=”jgheader2″   bgcolor=”lavender” height=”10pt”></td><br/>
  <tr   align=”left”  class=”jgtext2″ bgcolor=”lavender”><br/>
  <td align=”right”   >Namespace:</td><td ><input size=”20″ name=”<%=_APPNMSP_   %>” <%=_APPNMSP_ %> type=”text” maxlength=”30″/></td><br/>
  <tr align=”left”  class=”jgtext2″   bgcolor=”lavender”><br/>
  <td align=”right” >Name*:</td><td   ><input size=”20″ name=”<%=_APPNAME_ %>” id=”<%=_APPNAME_ %>”   type=”text” maxlength=”30″/></td><br/>
  <tr   align=”left”  class=”jgtext2″ bgcolor=”lavender”><br/>
  <td   align=”right”>Version*:</td><td ><input size=”10″   name=”<%=_APPVERS_ %>” id=”<%=_APPVERS_ %>” type=”text”   maxlength=”5″/></td><br/>
  <tr align=”left”    class=”jgtext2″ bgcolor=”lavender”><br/>
  <td   align=”right”>Description:</td><td ><input size=”50″   name=”<%=_APPDESC_ %>” id=”<%=_APPDESC_ %>” type=”text”   maxlength=”50″/></td> <br/>
  <tr align=”left”    class=”jgtext2″ bgcolor=”lavender”><br/>
  <td   align=”right”>Type:</td><td><br/>
  <select   name=”<%=_APPTYPE_ %>” id=”<%=_APPTYPE_ %>”><br/>
  <option   value=”APPLICATION” selected=”selected”>Application</option><br/>
  <option value=”FRAMEWORK”>Framework</option><br/>
  <option   value=”ADDON”>Add-On</option><br/>
  <option   value=”JVM”>JVM</option><br/>
  <option   value=”SSL”>SSL</option><br/>
  <option value=”DRIVER”>Driver   Add-On</option><br/>
  <tr align=”left”  class=”jgtext2″   bgcolor=”lavender”><br/>
  <td align=”right”>Archive*:</td><td   ><input name=”<%=_APPLOCT_ %>” id=”<%=_APPLOCT_ %>”   type=”hidden” /><br/>
  <input name=”appArchive” id=”appArchive”   size=”40″  type=”file” class=”jgtext2″   onchange=”window.document.tForm.appLocation.value=this.value”/><br/>
  </td>  <br/>
  <tr align=”left”  class=”jgtext2″   bgcolor=”lavender”><br/>
  <td   align=”right”>LeaveOriginal:</td><td ><input   name=”<%=_APPBKUP_ %>” id=”<%=_APPBKUP_ %>” type=”checkbox”   checked=”checked”/></td>  <br/>
  <tr ><br/>
  <td colspan=”2″ class=”jgheader2″ bgcolor=”lavender”   height=”10pt”></td><br/>
  <tr align=”left”    class=”jgtext2″ bgcolor=”lavender”> <br/>
  <td   ></td><td><input type=”submit” value=”add”   class=”jgtext2bold”/><br/>
  <input type=”reset” value=”clear”   class=”jgtext2bold”/><br/>
  <tr   ><br/>
  <td colspan=”2″ class=”jgheader2″ bgcolor=”lavender”   height=”10pt”></td><br/>
 <tr   class=”jgtext2″><br/>
  <td colspan=”6″><%=msg%></td><br/>
  <input type=”hidden” name=”event”   value=”ADD”/><br/>
<p class=”style1″></body><br/>
<p class=”style1″> <! — Functions –><br/>
  <%!   <br />
  String   processEvent(HttpServletRequest request){<br/>
String msg =   “”;<br/>
String event   = request.getParameter(_EVNTSTR_);  <br/>
if(event!=null){  <br/>
//required   parameter for both add and delete  <br/>
String appName =   request.getParameter(_APPNAME_);  <br/>
String appVersion =   request.getParameter(_APPVERS_);  <br/>

msg = APPNAME +   ” = ” + appName +   “
” +  APPVERS + ” = ” + appVersion+”
” ;


return APPNAME +   ” should not have a   character space. -> ” +   appName;


return APPVERS +   ” should not   have a character space. -> ” + appVersion;



String appDescription = request.getParameter(_APPDESC_);

String appNamespace = request.getParameter(_APPNMSP_);

String appLocation = request.getParameter(_APPLOCT_);

boolean appBackup = request.getParameter(_APPBKUP_)!=null;

String appType = request.getParameter(_APPTYPE_);


if(!checkParameters(appName, appVersion, appLocation)){

msg = “Name, Version and ArchiveLocation are mandatory!“;



return “” + appLocation + ” is INVALID!“;

if(appDescription == null ) appDescription = appName;

if(appNamespace == null) appNamespace = “”;


String newLocation = copyArchive(appName,appLocation.trim());


return “Failed to copy the archived!”;

appLocation = newLocation;




  msg += APPNMSP + ” = ” +   appNamespace + “
” +

  APPDESC + ” = ” + appDescription +   “
” +       

  APPLOCT + ” = ” + appLocation + “
” +

  APPBKUP + ” = ” + appBackup + “
” +

  APPTYPE + ” = ” + appType + “




msg += “Component successfully installed. Restart MI…“;

}catch(Exception e){


return e.getMessage();




}else if(_EVNTDEL_.equals(event)){



msg += “Component successfully removed. Restart MI…“;

}catch(Exception e){


return e.getMessage();



msg = event + ” is not unknown!”;




return msg;


String createDelLink(String name, String version){

  return   ” event=DEL&”APPNAME“=”name“&”APPVERS“=”+version;


void removeComponent(String appName, String appVersion) throws Exception{

ApplicationManager mgr = ApplicationManager.getInstance();

MobileSolutionDescriptor msd = mgr.getMobileSolutionDescriptor(appName, appVersion);

if(msd==null) return;





void removeConvId(MobileSolutionDescriptor msd) throws InstallationException{

ConversationIdHandler hdr = ConversationIdHandler.getInstance();

ConversationId sepId = hdr.getConversationId(msd,UserManager.getInstance().getCurrentUser());


ConversationId shrId = hdr.getConversationId(msd,UserManagerImpl.getSharedUser());



//install the component

void installComponent(String appNS, String appName, String appVersion,

String appDesc, String appType, String appLocation)

throws Exception{


//create an MSD

MobileSolutionDescriptor msd = new MobileSolutionDescriptor(appNS,appName,appVersion);

//set the description


//set the property type: APPLICATION etc…

msd.setPropertyValue( “TYPE”,appType);

//set the runtime propery. only JSP is supported

msd.setPropertyValue( “RUNTIME”,”JSP”);

//set the customizing entry for localpath

msd.setCustomizingValue( “LOCALPATH”,appLocation);

//invoke the setApplicationType method to assign the properties.


//set this property to true





//install the application

msd.getType().install( “[file:/// | file://]” + appLocation,msd);

//set visible to true or false if you don’t want it to be visible


//set this to false


//set this to true






//assign a conversationId to the MSD

void assignConvId(MobileSolutionDescriptor msd) {




//assign a conversationId to the MSD

void assignConvId(MobileSolutionDescriptor msd, boolean isSeparated) {

try {

String id = isSeparated   generateConvId( “SEP”) : generateConvId(“SHR”);

User usr = isSeparated   UserManager.getInstance().getCurrentUser(): UserManagerImpl.getSharedUser();

ConversationId convId = new ConversationId(id, msd, usr, false);



catch (InstallationException e) {




//ConversationId string generator

String generateConvId(String PRE){

StringBuffer idBuffer = new StringBuffer(24);

idBuffer.append( “LOCAL”);


String v = String.valueOf(System.currentTimeMillis());


return idBuffer.toString();


//check the specified parameter for a space char

boolean hasSpaceChar(String param){

return param.indexOf(‘ ‘) > -1;


//check the mandatory parameters

boolean checkParameters(String appName, String appVer, String appLocation){

return appName!=null && appName.length() > 0 &&

appVer!=null && appVer.length() > 0 &&

appLocation!=null && appLocation.length() > 0;


//check the file existence

boolean checkLocation(String appLocation){

if(appLocation==null) return false;

File f = new File(appLocation);

return f.exists() && f.isFile();


//copy archive utility

String copyArchive(String appName, String appLocation){

int pIdx = appLocation.indexOf(‘.’);

String appExt = appLocation.substring(pIdx);

File of = new File(appLocation);

File nf = new File(this.getServletContext().getRealPath( “”), appName + appExt);



}catch(IOException e){

return null;


return nf.getAbsolutePath();


void fileCopy(File fromFile, File toFile) throws IOException{

FileInputStream from = null;  // Stream to read from source

FileOutputStream to = null;   // Stream to write to destination

try {

from = new FileInputStream(fromFile); 

to = new FileOutputStream(toFile);

byte[] buffer = new byte[4096];

int bytes_read;

while((bytes_read = != -1)

to.write(buffer, 0, bytes_read);


finally {

if (from != null) try { from.close(); } catch (IOException e) { ; }

if (to != null) try { to.close(); } catch (IOException e) { ; }





Assigned Tags

      1 Comment
      You must be Logged on to comment or reply to a post.
      Author's profile photo Former Member
      Former Member
      Great! It works. Saves me indeed a lot of time. I must say your weblogs helped me a lot with my adventures on MI.