Timing – and knowing / determing which events cause the Init() to be called

It’s been a while since my last post; pretty shocking I know!

In fairness, some of the things that I have been mucking around with have been related to what I was going to present at Inforum, and well, I didn’t want to spoil the uh…surprise… (that’s my excuse and I’ll stick to it).

Inforum btw was quite interesting, I got a general positive vibe from the Lawson…err…Infor staff that I spoke to. And it looks like some exciting technologies are being developed.

But that isn’t what I am really here to type about today. Timing…

If you’ve ever gone down the route of working with multiple panels or read all my posts then you’ll no doubt have encountered some frustration around scripts not working quite how you’d expect, I usually tend to notice these differences when deploying a script vs running them in the mforms jscript editor.

Each time I have encountered odd behaviour, I have thought to myself, wouldn’t it be nice to know the sequence of events – when events fire and all that other good stuff. And I will think to myself…I should write a script which will just log the entry and exit of some functions – subscribe to some events and see how they work which may make things a little clearer in my mind. Of-course, being in IT, my life is about promoting laziness – making life easier so people have to do less work 😉

So with Inforum coming up and some people bull…err…encouraging me to do a presentation I thought to myself…well, time to write that script. I of-course procrastinated further…

I have considered writing a summary with conclusions… The main reason I haven’t is I am wary of changes in behaviour as versions change, so I’d far rather providing a very basic framework that people can use to observe what happens with their version and in their environment and hopefully provide some guidance based upon that which I have seen.

What I did was I created a script which uses the System.IO.File.AppendAllText() function to write data to a text file. I write a line to this file on the entry of the Init() method and immediately before the exit of the Init() method.

        public function Init(element: Object, args: Object, controller : Object, debug : Object)
        {
            System.IO.File.AppendAllText(gstrOutputPath, DateTime.Now.ToString(gstrDateTimeFormat) + " Init() entry - element = " + element + " Args = " + args + Environment.NewLine);
            var content : Object = controller.RenderEngine.Content;

            gController = controller;

            // TODO Add your code here
            glvListView = controller.RenderEngine.ListControl.ListView;
            // glvListView.Tag.IsPooled = false;

            gController.add_RequestCompleted(OnRequestCompleted);
            gController.add_Requested(OnRequested);            

            
            glvListView.add_Unloaded(OnLVUnloaded);

            System.IO.File.AppendAllText(gstrOutputPath, DateTime.Now.ToString(gstrDateTimeFormat) + " Init() exiting" + Environment.NewLine);
        }

 

I also subscribe to a Listview and subscribe to its unload event. Likewise, I will write a line to my output file when I enter the unload event and just before I exit. I put this in so I could see when the ListView itself was being destroyed in the context of the various actions that we can do in Smart Office. I believe that this behaviour can be influenced using the <listview>.Tag.IsPooled property (beyond the scope of this post at the moment).

        public function OnLVUnloaded(sender: Object, e: RoutedEventArgs)
        {
            System.IO.File.AppendAllText(gstrOutputPath, DateTime.Now.ToString(gstrDateTimeFormat) + " OnLVUnloaded() entry" + Environment.NewLine);
            
            glvListView.remove_Unloaded(OnLVUnloaded);

            gController.remove_Requested(OnRequested);            
            // gController.remove_RequestCompleted(OnRequestCompleted);

            System.IO.File.AppendAllText(gstrOutputPath, DateTime.Now.ToString(gstrDateTimeFormat) + " OnLVUnloaded() exit" + Environment.NewLine);
        }

 

Then probably the most important parts…I subscribe to the RequestCompleted and the Requested events, and will write out some bits of information which I felt might be helpful.

        public function OnRequestCompleted(sender: Object, e: RequestEventArgs)
        {
            System.IO.File.AppendAllText(gstrOutputPath, DateTime.Now.ToString(gstrDateTimeFormat) + " OnRequestCompleted() entry" + Environment.NewLine);
            System.IO.File.AppendAllText(gstrOutputPath, DateTime.Now.ToString(gstrDateTimeFormat) + " OnRequestCompleted() - Event Type: " + e.CommandType + Environment.NewLine);
            System.IO.File.AppendAllText(gstrOutputPath, DateTime.Now.ToString(gstrDateTimeFormat) + " OnRequestCompleted() - Event Value: " + e.CommandValue + Environment.NewLine);
            System.IO.File.AppendAllText(gstrOutputPath, DateTime.Now.ToString(gstrDateTimeFormat) + " OnRequestCompleted() exit" + Environment.NewLine);
        }

        public function OnRequested(sender: Object, e: RequestEventArgs)
        {
            System.IO.File.AppendAllText(gstrOutputPath, DateTime.Now.ToString(gstrDateTimeFormat) + " OnRequested() entry" + Environment.NewLine);
            System.IO.File.AppendAllText(gstrOutputPath, DateTime.Now.ToString(gstrDateTimeFormat) + " OnRequested() - Event Type: " + e.CommandType + Environment.NewLine);
            System.IO.File.AppendAllText(gstrOutputPath, DateTime.Now.ToString(gstrDateTimeFormat) + " OnRequested() - Event Value: " + e.CommandValue + Environment.NewLine);
            System.IO.File.AppendAllText(gstrOutputPath, DateTime.Now.ToString(gstrDateTimeFormat) + " OnRequested() exit" + Environment.NewLine);
            gController.remove_Requested(OnRequested);        
            // gController.remove_RequestCompleted(OnRequestCompleted);            
        }

I want to see what happens when

  • We initially start a program
  • Press F5
  • Scroll down
  • Open Related
  • Previous from an Open Related
  • Display an entry
  • Previous from display an entry
  • Close a panel

I also wanted to illustrate what happens when we are bad and don’t follow the instructions in the LSO Developers Guide and we neglect to clean up and unsubscribe from events when the Requested() event is called – it is by doing this that I get a get a feel for why Lawson want you to unsubscribe and also just what I can expect if I do dodgy scripting. Actually – I think it is quite important if only so you can assess the risk of not following a recommendation precisely, but I’ll pontificate this point another day.

I’m running this script against LSO9, and the comments that I make are purely from observation, full script will be at the bottom of this post for you to test and should run in any panel that has a ListView.

Opening a Panel

So, the Initial opening of a panel

20120329 12:49:25:595 Init() entry – element = undefined Args =

20120329 12:49:25:607 Init() exiting

20120329 12:49:25:610 OnRequestCompleted() entry

20120329 12:49:25:610 OnRequestCompleted() – Event Type: RUN

20120329 12:49:25:611 OnRequestCompleted() – Event Value: mms001

20120329 12:49:25:611 OnRequestCompleted() exit

We can see from the information in the file that the InitI() gets called, and once it exits it looks like the RequestCompleted() event is fired. Quite helpfully we can see that this was a event type of RUN and had a value of MMS001. There is no Requested() event trapped by us because our script and the event subscription in the Init() method doesn’t get bound to the panel until after the Requested() event has exited!

Pressing F5 on a Panel

This is something that caught me out on a couple of occasions, pressing F5 on a panel causes the Init() to be called again. So in effect your script should (if you have cleaned up properly) be unloaded and disassociated, and then reassociated.

20120329 12:50:37:521 OnRequested() entry

20120329 12:50:37:522 OnRequested() – Event Type: KEY

20120329 12:50:37:523 OnRequested() – Event Value: F5

20120329 12:50:37:523 OnRequested() exit

20120329 12:50:37:887 Init() entry – element = undefined Args =

20120329 12:50:37:888 Init() exiting

20120329 12:50:37:888 OnRequestCompleted() entry

20120329 12:50:37:888 OnRequestCompleted() – Event Type: KEY

20120329 12:50:37:889 OnRequestCompleted() – Event Value: F5

20120329 12:50:37:889 OnRequestCompleted() exit

20120329 12:50:38:001 OnLVUnloaded() entry

20120329 12:50:38:003 OnLVUnloaded() exit

This is a lot more interesting than the panel opening – we can see the Requested() event occur, We can see the type of value of the event, and then the exit.

THEN Init() gets called, then the RequestCompleted…all makes sense – but then we see that the ListViews Unloaded() event is fired! So the general takeaway from this is that an F5 is effectively going to be treated as a complete destroy and recreation of at least the GUI elements.

Scrolling Down the ListView

As mentioned in the past, Smart Office retrieves a number of records at once and as you scroll down further it will request some more records from the BE. But I was curious about what other things may be happening…

20120329 12:52:00:137 OnRequested() entry

20120329 12:52:00:137 OnRequested() – Event Type: PAGE

20120329 12:52:00:138 OnRequested() – Event Value: DOWN

20120329 12:52:00:138 OnRequested() exit

It doesn’t really look very exciting at all. But hold on, no RequestCompleted()…

So lets not clean up our events.

20120329 14:18:06:547 OnRequested() entry

20120329 14:18:06:548 OnRequested() – Event Type: PAGE

20120329 14:18:06:548 OnRequested() – Event Value: DOWN

20120329 14:18:06:548 OnRequested() exit

20120329 14:18:06:560 OnRequestCompleted() entry

20120329 14:18:06:560 OnRequestCompleted() – Event Type: PAGE

20120329 14:18:06:561 OnRequestCompleted() – Event Value: DOWN

20120329 14:18:06:561 OnRequestCompleted() exit

This looks a little more interesting.

Open Related

The action of taking us to a completely new layout on our panel – we can make some good guesses about what will happen…

20120329 14:34:16:858 OnRequestCompleted() entry

20120329 14:34:16:858 OnRequestCompleted() – Event Type: LSTOPT

20120329 14:34:16:858 OnRequestCompleted() – Event Value: 11

20120329 14:34:16:859 OnRequestCompleted() exit

20120329 14:34:16:958 OnLVUnloaded() entry

20120329 14:34:16:958 OnLVUnloaded() exit

Previous after Open Related

20120329 14:35:55:490 Init() entry – element = undefined Args =

20120329 14:35:55:491 Init() exiting

20120329 14:35:55:492 OnRequestCompleted() entry

20120329 14:35:55:492 OnRequestCompleted() – Event Type: KEY

20120329 14:35:55:492 OnRequestCompleted() – Event Value: F12

20120329 14:35:55:493 OnRequestCompleted() exit

Closing a Panel

And we can’t forget about the closing of a panel.

20120329 14:36:51:143 OnRequested() entry

20120329 14:36:51:144 OnRequested() – Event Type: KEY

20120329 14:36:51:145 OnRequested() – Event Value: F03

20120329 14:36:51:145 OnRequested() exit

20120329 14:36:51:535 OnRequestCompleted() entry

20120329 14:36:51:535 OnRequestCompleted() – Event Type: KEY

20120329 14:36:51:536 OnRequestCompleted() – Event Value: F03

20120329 14:36:51:536 OnRequestCompleted() exit

20120329 14:36:51:538 OnLVUnloaded() entry

20120329 14:36:51:538 OnLVUnloaded() exit

So hopefully this gives you an idea, or at least a framework to muck around to provide clues on what may be going wrong with a script.

And the full code…enjoy…

import System;
import System.Windows;
import System.Windows.Controls;
import MForms;

package MForms.JScript
{
    class HowItWorks_V002
    {
        var gstrOutputPath : String = "C:\\Temp\\HowItWorks.txt";
        var gstrDateTimeFormat : String = "yyyyMMdd HH:mm:ss:fff";

        var gController;
        var glvListView;

        public function Init(element: Object, args: Object, controller : Object, debug : Object)
        {
            System.IO.File.AppendAllText(gstrOutputPath, DateTime.Now.ToString(gstrDateTimeFormat) + " Init() entry - element = " + element + " Args = " + args + Environment.NewLine);
            var content : Object = controller.RenderEngine.Content;

            gController = controller;

            // TODO Add your code here
            glvListView = controller.RenderEngine.ListControl.ListView;
            // glvListView.Tag.IsPooled = false;

            gController.add_RequestCompleted(OnRequestCompleted);
            gController.add_Requested(OnRequested);            

            
            glvListView.add_Unloaded(OnLVUnloaded);

            System.IO.File.AppendAllText(gstrOutputPath, DateTime.Now.ToString(gstrDateTimeFormat) + " Init() exiting" + Environment.NewLine);
        }

        public function OnLVUnloaded(sender: Object, e: RoutedEventArgs)
        {
            System.IO.File.AppendAllText(gstrOutputPath, DateTime.Now.ToString(gstrDateTimeFormat) + " OnLVUnloaded() entry" + Environment.NewLine);
            
            glvListView.remove_Unloaded(OnLVUnloaded);

            gController.remove_Requested(OnRequested);            
            // gController.remove_RequestCompleted(OnRequestCompleted);

            System.IO.File.AppendAllText(gstrOutputPath, DateTime.Now.ToString(gstrDateTimeFormat) + " OnLVUnloaded() exit" + Environment.NewLine);
        }

        public function OnRequestCompleted(sender: Object, e: RequestEventArgs)
        {
            System.IO.File.AppendAllText(gstrOutputPath, DateTime.Now.ToString(gstrDateTimeFormat) + " OnRequestCompleted() entry" + Environment.NewLine);
            System.IO.File.AppendAllText(gstrOutputPath, DateTime.Now.ToString(gstrDateTimeFormat) + " OnRequestCompleted() - Event Type: " + e.CommandType + Environment.NewLine);
            System.IO.File.AppendAllText(gstrOutputPath, DateTime.Now.ToString(gstrDateTimeFormat) + " OnRequestCompleted() - Event Value: " + e.CommandValue + Environment.NewLine);
            System.IO.File.AppendAllText(gstrOutputPath, DateTime.Now.ToString(gstrDateTimeFormat) + " OnRequestCompleted() exit" + Environment.NewLine);
        }

        public function OnRequested(sender: Object, e: RequestEventArgs)
        {
            System.IO.File.AppendAllText(gstrOutputPath, DateTime.Now.ToString(gstrDateTimeFormat) + " OnRequested() entry" + Environment.NewLine);
            System.IO.File.AppendAllText(gstrOutputPath, DateTime.Now.ToString(gstrDateTimeFormat) + " OnRequested() - Event Type: " + e.CommandType + Environment.NewLine);
            System.IO.File.AppendAllText(gstrOutputPath, DateTime.Now.ToString(gstrDateTimeFormat) + " OnRequested() - Event Value: " + e.CommandValue + Environment.NewLine);
            System.IO.File.AppendAllText(gstrOutputPath, DateTime.Now.ToString(gstrDateTimeFormat) + " OnRequested() exit" + Environment.NewLine);
            gController.remove_Requested(OnRequested);        
            // gController.remove_RequestCompleted(OnRequestCompleted);            
        }

    }
}

This entry was posted in Development, M3 / MoveX. Bookmark the permalink.

1 Response to Timing – and knowing / determing which events cause the Init() to be called

  1. Eyal says:

    Hello
    How can I contact you ?

    I would like to get your quote for developing a small smartoffice script

    Thanks
    Eyal

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s