/ Development  

WARNING; The shocking truth about the 'toOne' entity relation

Hi there AppWorks fans,

Welcome to a new installment of AppWorks tips.

This post is triggered from a great conversation I had about the ‘Relation’ BB of our beloved platform. In this conversation, one relation got extra attention…That’s the ‘toOne’ relation to another entity. Why? Well, that’s what we will find out in this quick post.


Let get right into it…

We start simple…Boot your machine, login to your favorite spot, and create yourself a basic entity with just a simple property ‘Name’. Generate all the default stuff, make it nice and cozy, and add a first ‘toOne’ relation BB which relates to the platform out of the box identity ‘User’ entity:

to_one_001

You see that I’ve also enabled the ‘Web service’ BB with the ‘Read’ operation. With this BB we also need to create a new service container of type ‘Application Server Connector’; I hope you know the drill from the ‘System Resource Manager’ artifact…Comment me otherwise!

I also update the ‘Create’ form with a dropdown component for a user relation selection:

to_one_002

Have a save, a publication, and create your first entity instance in runtime with a user selected in the dropdown…A simple task to do!
Open the entity instance and get a copy of the ‘Item.Id’; You can get it from the top URL in your browser; Something like 080027008c65a1ee892a5a9f1fe6b772.1 Leave the runtime as is and get back to the designer. Open the ‘Web Service Interface’ explorer and get your hands dirty on the ‘Read’ operation for your entity; In my example Readcase! Inject the request with a copy of your ‘ItemId’ and get a response like this (cleaned from all schema details!):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<data>
<ReadcaseResponse>
<case>
<case-id>
<Id>1</Id>
<ItemId>080027008c65a1ee892a5a9f1fe6b772.1</ItemId>
</case-id>
<case_name>test001</case_name>
<Title>
<Value>case-1</Value>
</Title>
<to_one_user>
<Identity-id>
<Id>5</Id>
<ItemId>F8B156E1037111E6E9CB0FBF3334FBBF.5</ItemId>
</Identity-id>
</to_one_user>
</case>
</ReadcaseResponse>
</data>

You can clearly see our main entity and a ‘to_one_user’ element related to the corresponding ‘ItemId’; This is my account awtest (where I assess with account awdev!)…Looks all fine and great…Right? Well, now move your ass back into runtime, open that same entity instance with the developer tools <F12> of your browser open! Do some filtering on the network tab and have this view:

to_one_003

This is an HTTP GET request on this URL (including those URL parameters):

1
2
3
4
http://192.168.56.107:8080/home/appworks_tips/app/entityRestService
/Items(080027008c65a1ee892a5a9f1fe6b772.1)
?include=All,Usage,Relation.ToOne.TargetGhostItem
&language=en-US

Here is a copy of the JSON data to be amazed on what is exposed here! Why amazed? Well, have a closer look…Especially on the ‘to_one_user’ relation; AND under there a relation to ‘toPerson’!! AND the relations directly show the extra metadata! Not like we’ve just seen on our ‘Read’ operation. Is this smart? Well, the JSON file is only 333Kb, but still…If you don’t consume the data, why exposing it? I tried it without the ?include URL parameter and this drastically decreased the JSON size! So, why adding it? #SUPPORT

This is the first easy example to show you to be wise on a ‘toOne’ relation, but let’s move on…We can do better! 😁


A ‘toOne’ relation to “itself”!?

Yes, now we’re talking…Let’s create indeed a new entity itself (with just one simple property of choice), add a ‘toOne’ relation to “itself”, and build the surrounding stuff to make something usefully in runtime! 🤠 The ‘Create’ form gets extra attention where we add the ‘to_one_itself’ relation as a dropdown component. Have also a look on the recurring structure in the left:

to_one_004

Interesting…Now, expose again the ‘Webservice’ BB with the READ operation and have it managed by the ‘Application Server Connector’ service container (which is automagically applied by the system if you already have the container up and running!). Publish, create an instance, and built that relation in runtime. After this, do the READ service call on the entity instance and check the output…

to_one_005

Conclusion!?!? Well, what do you expect? An endless recurring flow of data? 🤥

This is my conclusion (which we already experienced!)…It just shows the ‘Identity.Id’ and not all the other metadata; You need to make a second call ‘Read’ call to get related data, but for our example it’s the same ‘ItemId’:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<data>
<ReaditselfResponse>
<itself>
<itself-id>
<Id>1</Id>
<ItemId>080027008c65a1ee8890c0c40ea01a69.1</ItemId>
</itself-id>
<it_name>test001</it_name>
<Title>
<Value>itself-1</Value>
</Title>
<to_one_itself>
<itself-id>
<Id>1</Id>
<ItemId>080027008c65a1ee8890c0c40ea01a69.1</ItemId>
</itself-id>
</to_one_itself>
</itself>
</ReaditselfResponse>
</data>

FYI: It’s even possible to create a second ‘toOne’ relation and make it bidirectional:

to_one_006

The result of such situation for a service call looks like this (watertight..Only Id’s!):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<data>
<ReaditselfResponse>
<itself>
<itself-id>
<Id>1</Id>
<ItemId>080027008c65a1ee892a852ef31cb772.1</ItemId>
</itself-id>
<it_name>test001</it_name>
<Title>
<Value>itself-1</Value>
</Title>
<to_one_itself>
<itself-id>
<Id>1</Id>
<ItemId>080027008c65a1ee892a852ef31cb772.1</ItemId>
</itself-id>
</to_one_itself>
<to_one_itself_bi>
<itself-id>
<Id>1</Id>
<ItemId>080027008c65a1ee892a852ef31cb772.1</ItemId>
</itself-id>
</to_one_itself_bi>
</itself>
</ReaditselfResponse>
</data>

Now, let’s have a view in runtime on our developer tools for this bidirectional example…The entity instance still loads, so no endless JSON recurring is going on; Also, the URL parameters are still the same on the HTTP GET request. This is the output (cleaned with meta-, and dictionary-info):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
{
"item": {
"Identity": {
"Id": "1",
"ItemId": "080027008c65a1ee892a852ef31cb772.1",
"Level": 1,
"EntityType": "080027008c65a1ee892a852ef31cb772",
"ItemStatus": 1,
"IsTemporaryCopy": false
},
"Properties": {
"it_name": "test001"
},
"Title": {
"Title": "itself-1"
},
"to_one_itself": {
"Identity": {
"Id": "1",
"ItemId": "080027008c65a1ee892a852ef31cb772.1",
"Level": 1,
"EntityType": "080027008c65a1ee892a852ef31cb772",
"ItemStatus": 1,
"IsTemporaryCopy": false
},
"Properties": {
"it_name": "test001"
},
"Title": {
"Title": "itself-1"
},
"to_one_itself": {
"ItemId": "080027008c65a1ee892a852ef31cb772.1"
},
"to_one_itself_bi": {
"ItemId": "080027008c65a1ee892a852ef31cb772.1"
},
"$meta": {
...
}
},
"to_one_itself_bi": {
"ItemId": "080027008c65a1ee892a852ef31cb772.1"
},
"$meta": {
...
}
},
"dictionary": {
...
}
}

So, it only goes one level deep for this specific example…Good to know!


Ohw boy…What an audience! You people always ask the correct questions! 🤓

How does this all look like with a ‘hasChild’ relation!?

Well, the ‘Read’ operation is not showing ‘hasChild’ relations as you need to expose an explicit ‘Get’ service operation! The JSON data in runtime shows it all; Each related ‘hasChild’ instance passes by in the JSON data!…So, be cautious with this one as well!! For me, an unexpected result as I thought it would respond like a ‘toMany’ relation…See next question!

How does this all look like with a ‘toMany’ relation!?

Well, the ‘Read’ operation is also not showing ‘toMany’ relations as you need to expose (again) an explicit ‘Get’ service operation! The JSON data in runtime however is NOT showing my ‘toMany’ relations; Exactly as expected…1-0 for the ‘toMany’ relation BB? Have a comment!

What happens when I make a ‘toOne’ relation from my first ‘case’ entity (having the ‘toOne’ user in place) to my ‘itself’ entity!?

Great, as I currently have a lot more relations available on my ‘itself’ entity as well! So, I have this as a final test:

  • ‘Case’ - to_one_user (‘toOne’ relation)
  • ‘Case’ - to_one_itself (‘toOne’ relation)
  • ‘Itself’ - to_one_itself (‘toOne’ relation)
  • ‘Itself’ - to_one_itself_bi (‘toOne’ bidirectional relation)
  • ‘Itself’ - sub_type (‘hasChild’ relation)
  • ‘Itself’ - to_many_todo (‘toMany’ relation)

The outcome/result/response in JSON (in runtime):

  1. Direct information on the ‘to_one_user’ relation; As expected!
  2. Direct information on the ‘to_one_itself’ relation, but it stops on the deeper ‘toOne’ relations (as we concluded before!)…Also for the bidirectional relation!
  3. Interesting conclusion is the missing ‘hasChild’ relation; So, it only exposes the JSON directly on its parent, but not in a second level relation as we see in this example; That can make us less cautious! 😇
  4. The ‘toMany’ relation is still not shown in the output; Also, as expected!

Well, I think we can give it a busted “DONE” where we learned all about different types of relations and what the output is in runtime for your end-users. Keep data as small as possible from a runtime perspective where the ‘toOne’ relation is one to reconsider again before you blindly implement it. Have a perfect ‘toMany’ relation 😱 weekend…I see you in a new post; Next week.

Don’t forget to subscribe to get updates on the activities happening on this site. Have you noticed the quiz where you find out if you are also “The AppWorks guy”?