Professional Documents
Culture Documents
4.3 - Local Storage Exercise How-To
4.3 - Local Storage Exercise How-To
Table of Contents
Outline 1
How to 2
Creating Local Storage Entities 2
Fetch Data from Local Storage on Screens 9
Movies Screen 9
People Screen 16
MovieDetail Screen 17
PersonDetail Screen 32
AddCastAndCrew Screen 33
Outline
In this exercise, we will change the OSMDb Mobile application to include Local Storage. This
exercise is divided in two different sections.
First, we will create the Local Storage data model, by creating the Local Storage Entities that we
will need. Our Local Storage data model will include:
Then, we will need to go to the five different Screens of the application and change the data
sources to use Local Storage, except for the average rating of a movie, in the MovieDetail
1
Screen. This means that in every other scenario, the Screens should be changed to include the
Local Storage as data source of the widgets and also in other relevant scenarios such as Input
Parameters and Local Variables.
At the end of this exercise, the application will not be working properly, since it is not fully
tailored to work offline, as well as it will not have any data, since the Local Storage Entities were
not populated with data yet.
How to
In this section, we’ll describe, step by step, the exercise 4.3 - Local Storage Exercise.
1. Create the LocalMovie Entity, with the exact same structure as the respective Database
Entity. All the attributes of the Movie Entity are used in our application, namely to display
the details of a movie, so it is important that the Local Storage Entity has a similar
structure.
b. Under Entities, right-click on the Local Storage section and select the option Add
Entity from Database...
2
d. In the next dialog, select all the attributes from the Movie Entity and click A
DD.
Service Studio will warn you that we should avoid mirroring the server data
model and prefer a lightweight local storage, which is a very important advice,
3
since the data synchronization procedure can become a heavy operation if all
data is replicated locally. However, in our scenario, we are talking about an Entity
with not a lot of attributes, and all the attributes are needed to display the
relevant information about the movie.
e. The Local Storage Entity will be automatically generated with the name
LocalMovie. Set its P
ublic property to Yes, keeping the Expose Read Only
property to Yes.
4
5
d. In the automatically created LocalMovieGenre Entity, set its Public property to Yes
and keep the E
xposed Read Only as Yes.
6
7
Movies Screen
Let’s start by the Movies Screen and replace all the Database Aggregates by Local Storage ones,
fixing all the errors that appear. Do not forget to also adjust the sorting functionality to use the
Local Storage Entities.
1. In the OSMDb_Mobile module, reference the Entities added in the previous section.
8
a. Open the OSMDb_Mobile module, switch to the Interface tab and open the
Movies Screen.
9
d. Open the Filters s ection of the Aggregate and add the following conditions:
10
f. Delete the G
etMovies Aggregate and rename the GetLocalMovies A
ggregate to
GetMovies. Service Studio should report several errors, which is normal, since we
deleted an important data source from the Screen. Let’s fix them.
g. In the TrueChange section, on the bottom left of Service Studio, expand indicating
the errors.
h. Double-clicking on the first error takes us to the Movies Screen, in particular to
the List of movies, and the Expression editor opens with the first error.
i. This Expression is used to display the title of the movie in the List, but the error
indicates that the expression cannot identify the element Movie. That happens
11
NOTE: More errors would appear if we did not change the name of the Aggregate
to be the same as the one that was deleted. If that would be the case, we would
need for instance, to also change the Source property of the List, to bind it to the
new Aggregate, as well as in other widgets on the Screen. Changing the name to
match the name of the original Aggregate deals with all those mappings
automatically for us.
GetMovies.List.Current.LocalMovie.Title
k. Repeat this process for the remaining errors, by replacing the occurrences of
Movie by LocalMovie, since all the issues have the same cause.
a. Create the G
etLocalMovieGenres Aggregate using the LocalMovieGenre Entity as
Source.
12
b. Delete the G
etMovieGenres Aggregate and rename the new Aggregate as
GetMovieGenres.
LocalMovieGenre.Id
d. Now that the issue is fixed, a new error appears, this time on the Variable
property of the Dropdown
This happens because the Dropdown is using a Client Variable, MovieGenreId, of
type MovieGenre Identifier. But now, since we’re using the Local Storage Entity,
the Variable field expects a L
ocalMovieGenre Identifier.
13
4. We do not have any more errors in Service Studio, but there is still something else we
need to fix. The sorting by title and year still uses the Database Entity, however since the
sorting is defined with a text, for instance “ {Movie}.[Title]”, Service Studio does not
recognize it as an error.
14
People Screen
In the People Screen, we have a Database Aggregate to fetch all the people stored in the Person
Database Entity. Following the same strategy used in the Movies Screen, let’s replace the
Database Aggregate by a Local Storage Aggregate, to fetch the people from the LocalPerson
Entity. As above, this will cause some errors that we need to fix along the way, and do not
forget to also adjust the sorting criteria.
15
1. Create a Local Storage Aggregate with the LocalPerson Entity as Source and set a
Dynamic Sort using the ListSort Local Variable.
2. Delete the G
etPeople Aggregate and rename the new Aggregate as GetPeople.
3. There are 6 errors that need to be fixed. Double-clicking on the first one leads us to the
List widget in the People Screen, to display all people in the database. As it happened in
the Movies Screen, the error is caused by having the Expressions still referring to a
Person record, instead of LocalPerson. Fix the first error by changing the Expression
value to
GetPeople.List.Current.LocalPerson.Name
4. Adjust the Sort by Name and Sort by Surname Links to use the LocalPerson Entity,
instead of the Person Database Entity.
MovieDetail Screen
The third Screen we will work on is the MovieDetail Screen. This one is probably the most
complex, since it has multiple Aggregates to work on. Don’t forget that we are not going to
change the GetAverageRating Aggregate, since the average rating will only be available when
the app is online. Let’s start by the GetMovieById Aggregate.
16
a. Open the MovieDetail Screen and create a new Local Storage Aggregate, with the
LocalMovie E
ntity as Source and the following Filter
LocalMovie.Id = MovieId
b. Delete the G
etMovieById Aggregate and rename the new Aggregate as
GetMovieById. This will lead to 11 errors.
c. Double-clicking on the first error leads to the SaveOnClick Action, which has the
logic to create / update a new movie in the database, as well as the Form
validations. The error appears exactly in the validations logic, but has a similar
cause to most of the errors we fixed so far. Replace the Movie reference by
LocalMovie, keeping the rest of the Condition as it was.
d. Apply the same logic to the second If of the logic flow in the SaveOnClick Action.
17
e. Continuing on the SaveOnClick Action flow, the next error appears in the
MovieCreateOrUpdate Action call, because we are passing to the server a Movie
record. Now, since the Screen will use a LocalMovie instead, we also need to
change it from Movie to LocalMovie.
18
This happens because, despite all our changes, the Server Action still expects a
Movie record, which makes sense since it is a Server Action and it does not have
access to Local Storage.
So, OutSystems maps the attributes of the Movie Entity to the attributes of the
record of the LocalMovie Entity automatically. This way, we can use the
LocalMovie record in our Screen and easily transform it to a Movie record when
calling the Server Action.
This mapping can be changed at any time and can always be done manually
between other Entities. As long as the attributes have the same data type, the
matching will be possible.
19
g. Fix three more errors by applying the same logic to the following input fields for
movie title, year and plot summary.
20
h. Apply the same logic to the dropdown. However, here the error does not
disappear.
If we look at the List property of the Dropdown, it is set to the output List of the
GetMovieGenres Aggregate, which is still a Database Aggregate. So, when we
change the Variable property to consider a LocalMovieGenre Identifier, the error
changes to a type mismatch error, since the Variable is still expecting a
MovieGenre Identifier data type. We will fix this later when we work on the
GetMovieGenres Aggregate.
i. Fix the remaining errors in the input fields for the gross takings and availability in
DVD, using the same strategy.
a. Create the new Local Storage Aggregate with the LocalMovieGenre as Source.
Delete the G
etMovieGenres Aggregate and rename the new one to
GetMovieGenres.
21
The List property does not have an error anymore. The error now is in the
Options Value property, which is still using the MovieGenre.Id, instead of the
LocalMovieGenre.Id.
22
LocalPersonMovieRole.MovieId = MovieId
c. Delete the G
etProductionTalent Aggregate and rename the new one to
GetProductionTalent. This will cause two errors.
d. Double-clicking on the first error leads us to the Production Talent List, which is
still referring to Person and PersonRole records. Change it to LocalPerson and
LocalPersonRole respectively.
LocalPersonMovieRole.MovieId = MovieId
23
Following the same logic as above, we are adapting the Filters of the GetCastCrew
Aggregate to adapt to the Local Storage nature of this new Aggregate.
h. Delete the G
etCastCrew Aggregate and rename the new one to G
etCastCrew. This
will cause two errors. Fix them using the same strategy as above.
a. Delete the G
etUserMovieRatingsByMovieId Aggregate. This will cause four
errors.
24
GetMovieById.List.Current.LocalMovie.RatingId
Do not forget that the LocalMovie Entity has an attribute for the RatingId, so it is
fetched already on the GetMovieById Aggregate.
d. The next errors appear in the Assign right below the Server Action call.
Here, we were using the output of the Aggregate to save in memory the current
Id of the Rating and the rating itself, so that the Screen would re-render to display
the new rating given by the user. So, we need to change the Assign to use the
RatingId a
nd Rating a
ttributes fetched by the GetMovieById Aggregate.
25
GetMovieById.List.Current.LocalMovie.RatingId =
UserMovieRatingCreateOrUpdate.UserMovieRatingId
GetMovieById.List.Current.LocalMovie.Rating = SelectedStar
f. The last error takes us to the actual Block that is displaying the stars in the
MovieDetail Screen. Replace the existing Expression by
GetMovieById.List.Current.LocalMovie.Rating
NOTE: There could be some other tweaks done to the logic, but at this time we
are just focusing on displaying the data on Screens using Local Storage. We will
get back to this in future exercises.
a. In the OSMDb_Core_Mobile module, create a new Client Action and call it
LocalMovieCreateOrUpdate. Set the Action as P
ublic.
26
b. Add one Input Parameter and three Output Parameters to the Action. The Input
Parameter should be called LocalMovie, with Data Type set to LocalMovie. The
Output Parameters should be called L ocalMovieId, Success and M
essage, with D
ata
Types set to L ocalMovie Identifier, Boolean and Text respectively.
c. Drag a Run Client Action node and drop it on the Action flow. Choose the
CreateOrUpdateLocalMovie Entity Action.
e. Drag an Assign n
ode and drop it below the CreateOrUpdateLocalMovie Action.
Set the Assignments to be:
LocalMovieId = CreateOrUpdateLocalMovie.Id
Success = True
27
We will not do any verification in this Action, so the Action will be successful.
Nevertheless, the logic can then be adjusted to include any verification you find
relevant.
f. Publish the module.
g. After publishing, switch to the OSMDb_Mobile module and add a dependency to
the recently created LocalMovieCreateOrUpdate Client Action.
h. In the MovieDetail Screen, open the SaveOnClick Action. Drag a Run Client
Action node and drop it on the True branch of the MovieCreateOrUpdate.Success
If.
28
29
30
PersonDetail Screen
We will now move on to the P
ersonDetail Screen, where we will apply the same strategy of
replacing the Database Aggregates by Local Storage Aggregates, and saving the data also in
Local Storage.
LocalPerson.Id = PersonId
2. Delete the G
etPersonById Aggregate and rename the new Aggregate as G
etPersonById.
3. Fix all the errors that appear by replacing references to the Person Entity by
LocalPerson.
31
AddCastAndCrew Screen
Finally, we just have the AddCastAndCrew Screen left, which has three Aggregates.
1. Let’s replace all of them by similar Local Storage Aggregates and fix all the errors.
2. This Screen has a particular case of a Local Variable with Data Type set to
PersonMovieRole. Change its n
ame to L ocalPersonMovieRole and its D
ata Type also to
LocalPersonMovieRole.
5. Open the application on the device to test it. At this point you should see no movies on
the Movies Screen. That does not mean we did something wrong. It’s just that we do not
have yet the local storage with data. We will solve this issue in the next exercise, when
we implement the synchronization procedure.
6. If by any chance you test your application without network connection, you will get an
error. This is normal at this point and it will also be addressed later in the Offline
exercise.
32