This is Chapter 15. If you want to go back to the beginning, you can find it here: Chapter 1. Or link to Chapter 14.
Video 15: Importing SysAsyncTicket
To make your experience smooth, we set the main tags mentioned in the video to the right bar menu of this mini-player. Choose an interesting subtitle on the list and immediately get to the exact theme navigation item place in the video. Now you can pick any topic to be instructed on without watching the whole video.
Chapter 15: Part 1 - Assign a new registration number
In this chapter, we create some methods to assign a new registration number and import the SysAsyncTicket model pattern that is recognised by the MDrivenServer.
- The SysAsyncTicket pattern is a major facilitator when it comes to things that must be serialized, like assigning a new number from a common store. If the assignment is not serialized, we will always run the risk of giving the same number to 2 different cars (due to 2 users, the system does the assignment roughly at the same time).
462. Create a new method on the class Car called GetNewRegistrationNumber():String
463. We will write logic to create a new Registration number in the format ABC123. We want the logic to count upwards without giving the same number twice. To enable that, we need to remember how the last number was generated to increase it by 1 the next time. We will place this "memory" on SysSingleton in four attributes.
464. Create new attributes on SysSingleton:
- RegNumberLetter1Current:Integer?
- RegNumberLetter2Current:Integer?
- RegNumberLetter3Current:Integer?
- RegNumberNumberPartCurrent: Integer?
465. Now, watch the video until 20:00. Follow along with the video and write the same code or find it here. You should be able to understand why it works.
466. Follow the discussion on semicolons in the video.
- The semicolon (;) is used to separate expressions.
- In OCL (in all functional languages), we must return exactly 1 result (the result can be 1 list - that is, still 1 result).
- This means that when we want to create a method that does multiple things, we need a way to stack multiple expressions together and ignore all the results but the last result. That is what the semicolon does for us. So
expr1;expr2
will return a result ofexpr2, expr1;expr2;expr3
. A result ofexpr3
andexpr1;expr2;expr3;
is actually wrong - because we cannot end on a semicolon.
467. Assign default values and default DB-values “=65”.
- RegNumberLetter1Current=65
- RegNumberLetter2Current=65
- RegNumberLetter3Current=65
- Set the InitialValue for all three to “65” as well.
468. Assign InitialValue to the NumberPart: RegNumberNumberPartCurrent=1.
469. Ensure your MDrivenServer is running. Upload the model to the MdrivenServer. We expect to see that it evolves the database with the new attributes we added.
470. Press the play button and go into the debugger with persistence set to MDrivenServer.
471. Open a debugger search window for Cars, search, and drag the first car onto an Expressions green dot in the debugger (we do this to give "self" the value of the car in the debugger expression).
472. Switch the debugger expression to Action and execute self.GetNewRegistrationNumber
to see what happens.
473. Discover that the method does not behave as we expect. Start the expression with the "Step" function in the debugger.
474. Press Start to step through the expression. Use the Step into to get into the code of the method. Familiarize yourself with the OCL stepper - it will be used frequently to discover the true logic of what you have.
475. Watch the video up to 26 minutes to see that you understand the issue - then correct the method.
476. Once corrected, upload the model again. It is important that the Server is given the latest model, or it will continue to have errors from the old model.
477. If you still have the debugger up, remember to press "Re-Read Model" - this is important for the same reason as the above (Step 476).
478. Use a search window to find a car and drag in a self on the green dot to the expression - then execute (F5) the self.GetNewRegistrationNumber
again.
479. Verify that it now works better. Press F5 to execute and hold it down to loop execute. See what happens when the first letter reaches Z and continue to watch the second letter reach Z. Cancel the changes when you are done.
Chapter 15: Part 2 - The SysAsyncTicket (Starts at about 28 minutes into the Video)
480. In the State BrandNew for Car (in the State Diagram for Car), add an Entry action that assigns the RegistrationNumber property, a value from our method GetNewRegistrationNumber.
· Write self.RegistrationNumber:=self.GetNewRegistrationNumber
481. Save and upload the model to MDrivenServer. Use a browser to check your application. Create a new Car and see that it gets a new Registration Number.
482. Now open another browser as another Chrome user (b@b.se), or in incognito mode, and log in again. You now have two different server contexts. Place the browsers next to each other on the screen, both showing the Car Seeker.
- Note: the b user does not have the right to create a New Car. Log in as the a user (a@a.se) instead.
- Press New Car in both windows. Notice that they are given the same number - this is not right.
483. Think about this problem for a minute.
- It is a common problem in all information systems.
- We want the system to behave asynchronously in 99.9% of the cases so that 1 user is not blocked by another user doing lengthy operations.
- In cases like this, we will want a serialization of the number generation and assignment to ensure that a conflict can never happen - not even in theory.
484. Now go to the Wiki and find the merge model for SysAsyncTicket. Download and merge it into your model.
485. Ensure that your current packages have the SysSuperClass as the default superclass (meaning that all classes without an explicit superclass will inherit from SysSuperClass). This is good - we get access to the method DoAsync that the pattern added for us.
486. Change the Entry action of Car BrandNew state to self.ActuallyAssignNewNumber
and move the old code into this new method instead (you need to create the method on Car).
487. Again, change the Entry action to use self.DoAsync('ActuallyAssignNewNumber')
instead of calling it directly. This will move the execution to the Server, and the Server will serialize jobs with the same signature. This is the effect that we are after.
488. Upload the model and run the app again. Create a new car and save. Wait for the new registration number to come back from the Server.
489. Have the two different apps next to each other again. Verify that you cannot get the same number on two new cars no matter how hard you try.
490. Familiarize yourself with the MDrivenServer (http://localhost:5000) by logging into its admin UI a, password 123456, (or the port you have in the Cloud-connect dialog).
- Go to Running, then PeriodicActions. Observe the actions that check for SysAsyncTicket and delete old SysAsyncTickets.
- Go to Running, then Data in A0. Click on SysAsyncTicket. Press “Search”. Observe the data for Car.ActuallyAssignNewNumber. There are no reported issues.
- Go to Running, then WorkInfo. View the different events tracked in the Server.
491. Head back to the model and check the "Changed by - Cross Reference" on the RegistrationNumber attribute. We want to limit the manual ability to set this value by setting a read-only expression that's true everywhere this is shown in the UI (switching to IsStatic would also work).
- Click on “ViewModelColumn ProperCarView.RegistrationNumber R/W”
- Select RegistrationNumber and in the Readonly Expression box, write:
true
- Go back to the model and check the "Changed by - Cross Reference" on the RegistrationNumber attribute. You’ll find the value shows also on TheTemplateForCarTransferOwnershipDocumentReport. Click on it.
- In the ViewModel window, press on TheTemplateForCarTransferOwnershipDocumentReport and set the Readonly Expression to true to avoid further confusion.
492. Find and select the RegistrationNumber attribute in Car. Click on the Tagged Values dialog. We want to give this the tag value of Realtime=true
. (Read about Realtime here.)
- In the Tagged Values dialog, press “Refresh From Wiki”. Click on “<Create Empty TV>” and select Realtime. Close the dialog.
- Save and upload the model.
- Test to create a new car and notice that the RegistrationNumber comes back faster than before.