Max number of Smart Client instances

Questions, answers, tips and ideas on Servoy Client

Max number of Smart Client instances

Postby erikd » Fri Feb 25, 2011 7:56 am

Hi, is there a maximum number of Servoy Smart Client instances? I am trying to open 4 Servoy applications in my machine. When the 4th application goes to login screen, it's connection to the database server is disconnected. Log shows "com.servoy.j2db.ApplicationException: No more licenses available".
erikd
 
Posts: 445
Joined: Wed Aug 11, 2010 2:32 am

Re: Max number of Smart Client instances

Postby Jan Aleman » Fri Feb 25, 2011 9:25 am

Sounds like you are out of licenses.

I've personally once launched 120 Servoy Smart Clients at once. Works fine. Was on a box with 4 GB of ram if I recall correctly.
Jan Aleman
Servoy
Jan Aleman
 
Posts: 2083
Joined: Wed Apr 23, 2003 9:49 pm
Location: Planet Earth

Re: Max number of Smart Client instances

Postby wiseguy » Fri Feb 25, 2011 8:23 pm

It would be useful if one could run multiple clients from a single computer without using more than one license (e.g. use same form within a solution to compare record data). This could be a problem with a terminal server, but maybe Servoy could detect it was running on a terminal server and act accordingly?
Hugh Summerhays
Mainstream Data
wiseguy
 
Posts: 9
Joined: Thu May 15, 2008 6:46 pm
Location: SLC, UT, USA

Re: Max number of Smart Client instances

Postby Jan Aleman » Fri Feb 25, 2011 8:53 pm

wiseguy wrote:It would be useful if one could run multiple clients from a single computer without using more than one license (e.g. use same form within a solution to compare record data). This could be a problem with a terminal server, but maybe Servoy could detect it was running on a terminal server and act accordingly?

Have you tried Servoy's multi-window and multi-instance (create new form instance) functionality for that? What you describe works with that. Limitations would be: multi-transactions (that still needs multiple clients) and you need to 'think' about your globals as they are shared.
Jan Aleman
Servoy
Jan Aleman
 
Posts: 2083
Joined: Wed Apr 23, 2003 9:49 pm
Location: Planet Earth

Re: Max number of Smart Client instances

Postby maria » Mon Feb 28, 2011 12:28 am

Jan Aleman wrote:
wiseguy wrote:It would be useful if one could run multiple clients from a single computer without using more than one license (e.g. use same form within a solution to compare record data). This could be a problem with a terminal server, but maybe Servoy could detect it was running on a terminal server and act accordingly?

Have you tried Servoy's multi-window and multi-instance (create new form instance) functionality for that? What you describe works with that. Limitations would be: multi-transactions (that still needs multiple clients) and you need to 'think' about your globals as they are shared.

Hi Jan,

In our application we tried to use multiple windows in vain because of the application size.
One form in our main module, for example, would contain another 20 or more forms that might in turn inherit from other forms, and our clients would want to open something like 20 duplicates of that which will come to us having to clone/create new instances of about 400 forms. This is a lot of background work and this is just the main module.

What we were thinking about is whether it's possible to clone/copy a top-level form without having to clone/copy all forms that it contains.
Thus, we would only copy the top-level container and Servoy would take care of creating whatever other copies it needs to have.
Is this possible in Servoy 6 or are there tips and tricks that might lighten the developer work here?

Updated: This is the reason we're considering having multiple clients running on the same machine without using up multiple licenses: the multiple windows problem would be solved if many application instances on the same machine (logged in under the same user/account) could only use one Servoy license. Doesn't it sound fair?

Cheers,
Maria

P.S. The discussion we had a while ago http://www.servoy.com/forum/viewtopic.php?f=2&t=15050
maria
 
Posts: 424
Joined: Thu Apr 16, 2009 1:18 am
Location: Sydney

Re: Max number of Smart Client instances

Postby proware » Mon Feb 28, 2011 1:59 am

Hi Jan,

Hope you get this message.

We have walked into a serious roadblack and I hope you can help.

Our current TSM software is designed specifically to enable the user to open as many copies of a form as they like. From discussions with MAria and the forum, it appears that this is not a realistic proposition with Servoy due to the need to have unique form names for each form.

the coding becomes much too complex to rename each form and the many sub forms contained within ad then have common code handle calling different form names for each copy.

There must be a simpler way.

So as a workaround, we have instantiated a new copy of our TSM application within a windows session. Each copy shares the same Session ID so that we can keep track of our TSM licencing and not use up another licence.

However as you know, Servoy still uses up another licence for each copy launched.

Is there a way of telling Servoy that this is not a new application being launched but should share the licence with the session already in use?

If not, what workaround should we use? Ideally I would have one copy of the application running with multiple windows but if this is not feasible, multiple apps will work. But just consider that each user could open 4 or 5 copies (or substantially) more so that they can juggle many jobs at once on screen.

Your thoughts will be appreciated.
proware
 
Posts: 18
Joined: Wed Oct 01, 2008 5:54 am

Re: Max number of Smart Client instances

Postby wiseguy » Mon Feb 28, 2011 9:36 pm

Jan Aleman wrote:Have you tried Servoy's multi-window and multi-instance (create new form instance) functionality for that?


Thanks Jan. I am thinking I can create a base form with a newWindow function to handle this. The code below is a start to that. Is deleting a tab and readding it currently the best way to reference a new instance of a form within a tab? Once I get this all worked out, perhaps I will submit it to be part of the ServoyCommons on servoyforge.net

Update: Removed code to streamline this thread - see newer code below.
Last edited by wiseguy on Thu Mar 17, 2011 5:59 pm, edited 1 time in total.
Hugh Summerhays
Mainstream Data
wiseguy
 
Posts: 9
Joined: Thu May 15, 2008 6:46 pm
Location: SLC, UT, USA

Re: Max number of Smart Client instances

Postby jcompagner » Tue Mar 01, 2011 11:29 am

deep cloning/new instances of forms even in tabpanels
is not part of servoy 6, but it is in our case system to do after 6.

Then if you select that tabs have "instance" forms and you create a new instance of the parent form all the others go with it

The only thing is that then you can program against the tab panel forms like:

forms.mytabpanelform.controller.xxxx

you have to do in the parent form itself:

elements.tabpanel.mytabpanelform.controller.xxxx
Johan Compagner
Servoy
User avatar
jcompagner
 
Posts: 8828
Joined: Tue May 27, 2003 7:26 pm
Location: The Internet

Re: Max number of Smart Client instances

Postby hsummerhays » Tue Mar 08, 2011 7:52 pm

Here is some form code to allow cloning using a newWindow method. It will clone forms on all tab panels, but only one layer deep. I have toyed around with some code that is more solutionModel centric and will post it if I have a chance to clean it up and make it work as nice as this code. It will eliminate the need for the tabs variable - see documention on tabs variable in the code below to see how it is used.

Code: Select all
/**
* Tracks the number to add on to the form name when a new instance is created.
* Remains zero in all but the first form instance.
*
* @type Number
*
* @properties={typeid:35,uuid:"6454390C-71D2-436D-8B19-618EAB2EE46E",variableType:4}
*/
var formInstance = 0;

/**
* Stores the original form name that the current instance is based on.
* This value is reset for a new form instance in the newWindow method.
*
* @type String
*
* @properties={typeid:35,uuid:"27C1DA59-8F13-4234-809C-BB35E3AD1F59",variableType:-4}
*/
var origFormName = this._formname_;

/**
* Stores all of the named tabs and their related form names so that
* their objects can be referenced consistently regardless of the form instance
* (e.g. forms[this.tabs["myTab"]].elements.myObject.enabled = true).
*
* @type Object
*
* @properties={typeid:35,uuid:"0694F1D2-0F34-47AA-AB80-FB105CD44790",variableType:-4}
*/
var tabs = new Object();

/**
* Creates a new instance of the current form in a new window.
*
* @properties={typeid:24,uuid:"B38A5440-11CD-48C8-A6CB-714277E45B7D"}
*/
function newWindow()
{
    // Use original form to keep track of next form instance number.
    var instance = ++forms[this.origFormName].formInstance;
       
    // Clone the current form.
    var curFormName = this._formname_;
    var form = solutionModel.getForm(curFormName);
    var newFormName = this.origFormName + instance.toString();      // Get name for new instance.
    /**
     * @type JSForm
     */
    var newForm = solutionModel.cloneForm(newFormName, form);

    // Reference original form for future instance number retrieval.
    forms[newFormName].origFormName = this.origFormName;
   
    // Make a clone of a tab and add to cloned form.
    for (var elementName in forms[curFormName].elements)
    {
        var element = forms[curFormName].elements[elementName];
        if (element.getElementType() == "TABPANEL")
        {
            for(var tabIndex = 1; tabIndex <= element.getMaxTabIndex(); tabIndex++)
            {
                var tabFormName = element.getTabFormNameAt(tabIndex);
                var tabForm = solutionModel.getForm(tabFormName);
                tabFormName += instance;   // Get name for new instance
                solutionModel.cloneForm(tabFormName, tabForm);
                var tabName = element.getTabNameAt(tabIndex);
                var tabText = element.getTabTextAt(tabIndex);
                var tabRelationName = element.getTabRelationNameAt(tabIndex);
                forms[newFormName].elements[elementName].removeTabAt(tabIndex);  // Remove the original instance of the tab since it will still be used by the original form.
                forms[newFormName].elements[elementName].addTab(forms[tabFormName],tabName,tabText,null,null,null,null,tabRelationName,tabIndex - 1);
               
                // Update form name in "tabs" object to point to new instance of tab form.
                if (tabName != null)
                {   
                    forms[newFormName].tabs[tabName] = tabFormName;
                }
            }
        }
    }
   
    // Show the new form, making the new window name match the new form name.
    forms[newFormName].controller.show(newFormName);
    forms[newFormName].elements.tabPanel1.tabIndex = 1;
   
    // TODO: Figure out why the new form doesn't stay open when this instance is closed.
}

/**
* Callback method when form is (re)loaded.
*
* @param {JSEvent} event the event that triggered the action
*
* @properties={typeid:24,uuid:"CC1CCD5A-2711-46F4-822D-079A399C8F2A"}
*/
function onLoad(event)
{
    // Load named tabs into "tabs" form variable.
    for (var elementName in elements)
    {
        var element = elements[elementName];
        if (element.getElementType() == "TABPANEL")
        {
            for(var tabIndex = 1; tabIndex <= element.getMaxTabIndex(); tabIndex++)
            {
                var tabName = element.getTabNameAt(tabIndex);
               
                // Add instance reference for tab.
                if (tabName != null)
                {
                    var tabFormName = element.getTabFormNameAt(tabIndex);
                    this.tabs[tabName] = tabFormName;
                }
            }
        }
    }
}
Last edited by hsummerhays on Thu Mar 10, 2011 12:20 am, edited 1 time in total.
Hugh Summerhays
Mainstream Data
hsummerhays
 
Posts: 29
Joined: Tue Mar 01, 2011 6:12 pm
Location: SLC, UT, USA

Re: Max number of Smart Client instances

Postby hsummerhays » Thu Mar 10, 2011 12:15 am

I finished working on the solutionModel centric code. If you use this code in a superform (or just directly in a form), you can properly access elements in a tab's form regardless of the instance. Be sure to call the onLoad method from the form's onLoad event. To create a new instance, simply call the newWindow method. As before, it will only clone tab panel forms one layer deep.

update: Be sure to base the namedFoundSet property of the form or superform to "separate".

update 17-Mar-2011: Updated code now that I am getting more familiar with Servoy and with JavaScript ;). Also, made it easier to access the elements on tab forms.

Here is an example of how you will access the elements on tab forms:

Code: Select all
getTabElement("myTabPanel", "myTab", "myElementOnTabForm").enabled = true;


And here is the form or superform code:

Code: Select all
/**
* @type String
*
* @properties={typeid:35,uuid:"4EACB2B2-9B6F-4471-BE06-0A4BAECC0A57"}
*/
var _origFormName = '';

/**
* @type Number
*
* @properties={typeid:35,uuid:"6454390C-71D2-436D-8B19-618EAB2EE46E",variableType:4}
*/
var _formInstance = 0;

/**
* Creates a new instance of the current form in a new window.
* @return {Boolean} True if successful.
*
* @properties={typeid:24,uuid:"B38A5440-11CD-48C8-A6CB-714277E45B7D"}
*/
function newWindow()
{
    // Use original form to keep track of next form instance number.
    /**@type Number*/
    var instance = ++forms[_origFormName]._formInstance;
   
    // Clone the current form.
    /**@type String*/
    var newFormName = _origFormName + instance.toLocaleString();      // Get name for new instance.
    /**@type JSForm*/
    var origForm = solutionModel.getForm(_origFormName);
    /**@type JSForm*/
    var newForm = solutionModel.cloneForm(newFormName, origForm);
   
    // Declare remaining variables
    /**@type JSTabPanel[]*/
    var tabPanels = newForm.getTabPanels();
    /**@type JSTab[]*/
    var tabs;
    /**@type String*/
    var newTabFormName;
    /**@type JSForm*/
    var newTabForm;
   
    // Create a new instance for all tab forms.
    for (var tabPanelNum = 0; tabPanelNum < tabPanels.length; tabPanelNum++)
    {
        tabs = tabPanels[tabPanelNum].getTabs();
        for (var tabNum = 0; tabNum < tabs.length; tabNum++)
        {
            newTabFormName = tabs[tabNum].containsForm.name + instance;   // Get name for new instance
            newTabForm = solutionModel.cloneForm(newTabFormName, tabs[tabNum].containsForm);
            tabs[tabNum].containsForm = newTabForm;
        }
    }
   
    // Show the new form, making the new window name match the new form name.
    forms[newFormName].controller.show(newFormName);
   
    // TODO: Figure out why the new form doesn't stay open when this instance is closed.
   
    return true;
}

/**
* Callback method when form is (re)loaded.
*
* @param {JSEvent} event the event that triggered the action
* @return {Boolean} True if successful.
*
* @properties={typeid:24,uuid:"269F4D95-3838-45FB-848A-71820A46AE9D"}
*/
function onLoad(event)
{
    // Get solutionModel instance of the form.
    /**@type JSForm*/
    var form = solutionModel.getForm(controller.getName());
   
    // Setup solutionModel compatible variable if needed.
    if (form.getFormVariable("_origFormName") === null)
    {
        form.newFormVariable("_origFormName", JSVariable.TEXT).defaultValue = '"' + controller.getName() + '"';
        controller.recreateUI();
        this._origFormName = controller.getName();    // Set value since defaultValue doesn't take effect until new instances.
    }
   
    // return _super.onLoad(event);
    return true;
}

/**
* @param {String} tabPanelName The tab panel that contains the tab.
* @param {String} tabName The tab that contains the element.
* @param {String} elementName The name of the element to retrieve.
* @return {JSComponent} The element or undefined if element is not found.
*
* @properties={typeid:24,uuid:"D6B28F5D-2832-4C1D-8293-91CF965EC673"}
*/
function getTabElement(tabPanelName, tabName, elementName)
{
    /** @type JSTabPanel */
    var tabPanel;
    /** @type JSTab */
    var tab;
    /** @type JSForm */
    var tabForm;
    /** @type JSComponent */
    var element;
   
    tabPanel = solutionModel.getForm(controller.getName()).getTabPanel(tabPanelName);
    if (tabPanel)
    {
        tab = tabPanel.getTab(tabName);
        if (tab)
        {
            tabForm = tab.containsForm;
            if (tabForm)
            {
                element = forms[tabForm.name].elements[elementName];
                if (element)
                {
                    return element;
                }
            }
        }
    }
   
    return undefined;
}
Last edited by hsummerhays on Thu Mar 17, 2011 7:30 pm, edited 1 time in total.
hsummerhays
 
Posts: 29
Joined: Tue Mar 01, 2011 6:12 pm
Location: SLC, UT, USA

Re: Max number of Smart Client instances

Postby ROCLASI » Thu Mar 10, 2011 9:24 am

hsummerhays wrote:update: Be sure to base the namedFoundSet property of the form or superform to "separate". :end update

The thing is when you use a seperate foundset then all your forms that use the same table are delinked. So selecting a record in one foundset won't select it automatically in the other. Ditto for searches, etc.
You would have to handle all that yourself instead of Servoy doing that for you which is a major pain.

Of course there is such a thing called 'named foundsets'. It allows you to have sets of shared foundsets. A feature that was sort of promised a while ago and prep work was done for in 5.x.
Paul/Johan/Jan B., any timeline on that feature? It would make having multiple instances of your solution in the same client manageable.
Robert Ivens
SAN Developer / Servoy Valued Professional / Servoy Certified Developer

ROCLASI Software Solutions / JBS Group, Partner
Mastodon: @roclasi
--
ServoyForge - Building Open Source Software.
PostgreSQL - The world's most advanced open source database.
User avatar
ROCLASI
Servoy Expert
 
Posts: 5438
Joined: Thu Oct 02, 2003 9:49 am
Location: Netherlands/Belgium

Re: Max number of Smart Client instances

Postby rossent » Sat Mar 12, 2011 2:17 pm

Hi all,

We are currently using an approach similar to the ones described here where the design-time forms are used only as a "blueprint" and at runtime we create clones of them with all the related complexity of referencing, searches, etc.

Our experience is this:
The approach technically works, but there is a huge impact on memory footprint. If this is somewhat feasible for smart clients, it totally does not work for web clients where a reasonable load is expected - on the web we actually have cases where the application server itself crashes due to out-of-memory conditions (of course, the server auto-restarts, but all client sessions connected to it are toasted) Also due to the memory pressure, forms instances are being auto-unloaded a lot more aggressively than what you might expect so even on the smart client, storing and restoring form instance state is a must (using the onLoad and onUnload form events). In addition, before Servoy 6, regardless how many windows you have open, there really is only a single "batch of work" context when it comes to data changes. If you are working with the AutoSave mode turned off, calling databaseManager.commitTransaction or databaseManager.rollbackTransaction sends/reverts ALL data changes - even the ones where you have not explicitly called databaseManager.saveData(<records to save>). So beware of that! In Servoy 6 the transactional methods now have an optional argument whether to affect all in-memory changed data or not. Performance-wise, things are also quite different when you start using run-time generated forms. Servoy is optimized to work with the design-time created "links" between the forms. Especially in the web client, you will notice a significant difference in that aspect (the application server needs to do a lot more "lookups" when working with the forms dynamically created through the solutionModel - and this applies not only during the process of actually creating the forms, but while using them and handling all AJAX callbacks to the server). In my opinion, this approach is usable if it is applied only to a few specific forms, but if you plan to use it as a general approach for every UI context in your application, then you should consider very carefully the memory footprint of each client-session and the performance penalty which you will have to pay.
Rossen Totev
Argos Software
rossent
 
Posts: 288
Joined: Wed Dec 31, 2008 2:03 pm

Re: Max number of Smart Client instances

Postby jcompagner » Tue Mar 15, 2011 1:25 pm

what do you mean with "links between forms" and "a lot more lookups" ?

they only thing is that if you create or change a form through the solution model, that form instance is specific to the webclient,
That is almost no memory what so ever, you will not notice that, The thing that does take more memory is that also the templates of that form are all specific to the client, So also that needs to be stored per client basis
So yes that takes some more memory. But when that is created there is no more lookups or different kind of links between them as design time forms.
Johan Compagner
Servoy
User avatar
jcompagner
 
Posts: 8828
Joined: Tue May 27, 2003 7:26 pm
Location: The Internet


Return to Servoy Client

Who is online

Users browsing this forum: No registered users and 7 guests