Java Question How use b4xMap in java?

behnam_tr

Active Member
Licensed User
Longtime User
I want to send a list containing map from b4j to Java and use it (Preferably use b4xmap)
Sample code on the b4x side

B4X: Copy
    Dim bodylist As List
    bodylist.Initialize
   
    Dim bodymap As Map
    bodymap.Initialize
    bodymap.Put("id","10")
    bodymap.Put("name","testname10")
    bodymap.Put("price","10000")
   
    bodylist.Add(map1)

    Log(myclass.testlist(bodylist))

Code: Copy
 public static String testlist(ArrayList cars){

        for(int i= 0; i< cars.size(); i++) {
            anywheresoftware.b4a.objects.collections.Map map1 = new anywheresoftware.b4a.objects.collections.Map();
            map1.Initialize();
            map1= (Map) cars.get(i);

            return map1.Get("id").toString() + map1.Get("name").toString()+map1.Get("price").toString();
        }
       return null;
    }

Code: Copy
Waiting for debugger to connect...
Program started.
1712928404207
Error occurred on line: 99 (Main)
java.lang.ClassCastException: class anywheresoftware.b4a.objects.collections.Map$MyMap cannot be cast to class anywheresoftware.b4a.objects.collections.Map (anywheresoftware.b4a.objects.collections.Map$MyMap and anywheresoftware.b4a.objects.collections.Map are in unnamed module of loader 'app')
    at mypackage.TaxApiSDKV1.testlist(TaxApiSDKV1.java:489)
    at b4j.example.main._button1_click(main.java:238)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at anywheresoftware.b4a.shell.Shell.runMethod(Shell.java:629)
    at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:234)
    at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:167)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at anywheresoftware.b4a.BA.raiseEvent2(BA.java:111)
    at anywheresoftware.b4a.shell.ShellBA.raiseEvent2(ShellBA.java:100)
    at anywheresoftware.b4a.BA$1.run(BA.java:236)
    at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:428)
    at java.base/java.security.AccessController.doPrivileged(Native Method)
    at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$11(PlatformImpl.java:427)
    at javafx.graphics/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
    at javafx.graphics/com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
    at javafx.graphics/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:174)
    at java.base/java.lang.Thread.run(Thread.java:834)
 
ChatGPT says...

The error you're encountering in your Java code is due to a type mismatch when casting objects passed from B4J to Java. Specifically, the ClassCastException indicates that Java is unable to cast the object of anywheresoftware.b4a.objects.collections.Map$MyMap to anywheresoftware.b4a.objects.collections.Map.

The problem arises because the object you receive in Java (cars.get(i)) is of a type internal to the B4A Map class (like a private subclass), and not directly the Map class itself. To fix this issue, you will need to handle the casting or conversion differently.

One way to address this is to utilize Java's HashMap instead of B4A's Map when fetching the map from the list in Java. You can convert the received object to a HashMap in Java, which is more generic and should work smoothly for key-value pair manipulations. Here is the corrected Java code:

B4X: Copy
import java.util.ArrayList;
import java.util.HashMap;

public static String testlist(ArrayList cars) {
    StringBuilder result = new StringBuilder();

    for (int i = 0; i < cars.size(); i++) {
        HashMap map1 = (HashMap) cars.get(i);

        String id = map1.get("id").toString();
        String name = map1.get("name").toString();
        String price = map1.get("price").toString();

        result.append(id).append(name).append(price);
    }
    return result.toString();
}
Make sure that the data passed from B4J are HashMaps in Java compatible format. In your B4X code, the transmission of data appears to be correct, but ensure the map you add to bodylist is indeed bodymap (you have a typo using map1 instead of bodymap).

Here's a corrected version of your B4X code with minor adjustments for clarity and correctness:

B4X: Copy
Dim bodylist As List
bodylist.Initialize

Dim bodymap As Map
bodymap.Initialize
bodymap.Put("id", "10")
bodymap.Put("name", "testname10")
bodymap.Put("price", "10000")

bodylist.Add(bodymap)  ' Ensure correct map is added

Log(myclass.testlist(bodylist))
With these changes, your code should successfully pass the map from B4J to Java and handle it correctly in Java without casting errors.
 
or see: (It will give you an idea.)
 
Thank you, none of them helped
For now, I solved the problem with Jason, but I would like to know the solution of using maps
 
maybe
Code: Copy
...
    Dim bodylist As List
    bodylist.Initialize
  
    Dim bodymap As Map
    bodymap.Initialize
    bodymap.Put("id","10")
    bodymap.Put("name","testname10")
    bodymap.Put("price","10000")
  
    bodylist.Add(bodymap)

    Log((Me).As(JavaObject).RunMethod("testlist",Array(bodylist)))
End Sub
#If java
import java.util.*;

public static String testlist(ArrayList cars){

        for(int i= 0; i< cars.size(); i++) {
            Map map1 = new HashMap();
            map1 = (Map) cars.get(i);

            return (map1.get("id").toString()+ " " + map1.get("name").toString() + " " + map1.get("price").toString());
        }
       return null;
    }
#End If
You can shorten the java by having
Code: Copy
 Map map1 = new HashMap((Map)cars.get(i));
instead of
Code: Copy
            Map map1 = new HashMap();
            map1 = (Map) cars.get(i);
 
There's a logic flaw in the code, it will only ever return the first map items.
You need something like
Code: Copy
public static String[] testlist(ArrayList cars){
        String reply[] = new String[cars.size()];
        for(int i= 0; i< cars.size(); i++) {
            Map map1 = new HashMap((Map)cars.get(i));
            reply[i] = (map1.get("id").toString()+ " " + map1.get("name").toString() + " " + map1.get("price").toString());
        }
       return reply;
    }

Called like
Code: Copy
    Dim rep() As String = (Me).As(JavaObject).RunMethod("testlist",Array(bodylist))
    For Each s As String In rep
        Log(s)
    Next
 
Back
Top