Retrieving Multiple Related Objects in custom business logic

  1. I am having trouble retrieving several related objects in my custom business logic and first, differentiating between the List of maps in the handleResponse callback(what keys are assigned what values), and second adding the contents of the individual maps to an already existing map in the return statement of the custom event
  2. is putting my field variables in the outer class allowed e.g objectId?
    Here is what am trying to do



@BackendlessEvent( "MyCustomEvent" )
public class MyCustomEventEventHandler extends com.backendless.servercode.extension.CustomEventHandler
{
 private String objectId = com.backendless.servercode.InvocationContext.getUserId(); // to put here?
 
 @Override
 public Map handleEvent( RunnerContext context, Map eventArgs )
 {
 
 LoadRelationsQueryBuilder<Map<String, Object>> loadRelationsQueryBuilder = LoadRelationsQueryBuilder.ofMap();
 loadRelationsQueryBuilder.setRelationName("relatedTableA");
 loadRelationsQueryBuilder.setRelationName("relatedTableB");
 
 String objectId = com.backendless.servercode.InvocationContext.getUserId(); // or here?



 Backendless.Data.of(BackendlessUser.class).loadRelations(objectId, loadRelationsQueryBuilder,
new AsyncCallback<List<Map<String, Object>>>() {
 @Override
 public void handleResponse(List<Map<String, Object>> maps) {
// i guess two maps are returned here, one for relatedTableA and another for relatedTableB
 }



 @Override
 public void handleFault(BackendlessFault backendlessFault) {



 }
 });
 
 {...} // method yeilds Object1
 
 {...} method yeilds Object2
 
 // an already populated map from two hidden methods
 HashMap<String, Object> hashMap = new HashMap<String, Object>();
 hashMap.put("obj1", Object1);
 hashMap.put("obj2", Object2);



 return hashMap;
 }
  1. I didn’t quite understand that point. Please rephrase as a question.

  2. No, what you do there is not allowed. The call to get user Id must be inside of handleEvent method.

Hello Mark,

Consider the code below. My Users table has a 1:1 relationship column “profileImageUrl” pointing to the ProfileImageUrl Table.

@BackendlessEvent( "MyEvent" )
public class MyEventHandler extends com.backendless.servercode.extension.CustomEventHandler
{
 
 @Async
 @Override
 public Map handleEvent( RunnerContext context, Map eventArgs )
 {
 // add your code here
 String parentObjectId = com.backendless.servercode.InvocationContext.getUserId();


 LoadRelationsQueryBuilder<Map<String, Object>> queryBuilderProfileImage;
 queryBuilderProfileImage = LoadRelationsQueryBuilder.ofMap();
 queryBuilderProfileImage.setRelationName("profileImageUrl");


 Backendless.Data.of("Users").loadRelations(parentObjectId, queryBuilderProfileImage,
 new AsyncCallback<List<Map<String, Object>>>() {
 @Override
 public void handleResponse(List<Map<String, Object>> profileImageUrlMaps) {
 Map profileImageUrlMap = profileImageUrlMaps.get(0);
 }
 @Override
 public void handleFault(BackendlessFault backendlessFault) {
 }
 });		 		 
}

profileImageUrlMaps in handleResponse is therefore just a 1 element arraylist, hence the use of

Map profileImageUrlMap = profileImageUrlMaps.get(0) 

to get the single map i require from the table.

Am supposed to put that map in my return map like so

HashMap<String, Object> result = new HashMap<String, Object>();
result.putAll(profileImageUrlMap);
return result;

Somehow i can’t get profileImageUrlMap out of

Map profileImageUrlMap = profileImageUrlMaps.get(0); 

inside handleResponse,

i have tried declaring a variable

Map profileImageUrlMap: 

then assigning

profileImageUrlMap = profileImageUrlMaps.get(0) 

but it’s not working.

either it’s asking me to remove a redundant assignement or transform profileImageUrlMap into a one element array.

What is the best way to go about this.

sync is giving me the object straight away like so

 @Async
 @Override
 public Map handleEvent( RunnerContext context, Map eventArgs )
 {
 // add your code here
 String parentObjectId = com.backendless.servercode.InvocationContext.getUserId();


 LoadRelationsQueryBuilder<ProfileImageUrl> loadRelationsQueryBuilderProfileImage;
 loadRelationsQueryBuilderProfileImage = LoadRelationsQueryBuilder.of(ProfileImageUrl.class);
 loadRelationsQueryBuilderProfileImage.setRelationName("profileImageUrl");

 List<ProfileImageUrl> profileImageUrls = Backendless.Data.of(BackendlessUser.class).loadRelations(parentObjectId,
 loadRelationsQueryBuilderProfileImage);

 ProfileImageUrl profileImageUrlObj = profileImageUrls.get(0);

Which i can then asign a key in my result Map easily like so:

HashMap<String, Object> result = new HashMap<String, Object>();
result.put("profileImageUrl", profileImageUrlObj);
return result;

return result;

George,

If you use Backendless 3.x, you cannot invoke async methods in business logic.

However, if you use Backendless 4.0, you can, but it will make it more difficult to get asynchronous response in one thread and then return map from the main thread to the client. It will require some additional thread synchronization and you do not need that complexity. So, my suggestion is just use sync api.

Cheers,
Mark

By the way, i have copied the ProfileImageUrl class from my project and pased it inside the models folder in the custom event handler files i generated and downloaded from console, inorder to do the implementation using CUSTOM CLASS as opposed to JAVA MAP, i hope that is allowed.

So sync api in backendless 4.0, if i got you right?

@Async
  @Override
  public Map handleEvent( RunnerContext context, Map eventArgs )
  {
    // add your code here
      String parentObjectId = com.backendless.servercode.InvocationContext.getUserId();


      LoadRelationsQueryBuilder<ProfileImageUrl> loadRelationsQueryBuilderProfileImage;
      loadRelationsQueryBuilderProfileImage = LoadRelationsQueryBuilder.of(ProfileImageUrl.class);
      loadRelationsQueryBuilderProfileImage.setRelationName("profileImageUrl");


      List<ProfileImageUrl> profileImageUrls = Backendless.Data.of(BackendlessUser.class).loadRelations(parentObjectId,
              loadRelationsQueryBuilderProfileImage);
      ProfileImageUrl profileImageUrlObj = profileImageUrls.get(0);
  
Which i can then asign a key in my result Map easily like so:


HashMap<String, Object> result = new HashMap<String, Object>();
result.put("profileImageUrl", profileImageUrlObj);


return result;

What is the @Async annotation doing at the top of handleEvent?, as generated. Can i remove it?

@Async does not apply to custom events. You should remove it from there.