B4J Question [SOLVED] Error using #If Java in non-ui B4J app - help desperately sought

JackKirk

Well-Known Member
Licensed User
Longtime User
I am tearing what little hair I have left out on this.

Copilot and Grok run round in circles.

I am attempting to filter logs in a non-ui B4J app (an ABMaterial framework web app):

B4X:
Public Sub RedirectFilteredLogs
    Dim system As JavaObject
    system.InitializeStatic("java.lang.System")

    ' Capture original System.out
    Dim originalOut As JavaObject = system.GetField("out")

    ' Initialize the custom PrintStreamWrapper
    Dim filteredStream As JavaObject
    filteredStream.InitializeNewInstance("PrintStreamWrapper", Array(originalOut, Me))
    system.RunMethod("setOut", Array(filteredStream)) ' Redirect standard output
    system.RunMethod("setErr", Array(filteredStream)) ' Redirect error output
End Sub

Public Sub ProcessLogMessage(message As String)
    If message.Contains("DEBUG") = False Then 'expand as necessary
        File.WriteString(File.DirApp, "filtered_logs.txt", message & Chr(10))
        CallSubDelayed2(Me, "ProcessLogMessageInternal", message)
    End If
End Sub

Public Sub ProcessLogMessageInternal(message As String)
    Dim system As JavaObject
    system.InitializeStatic("java.lang.System")
    Dim originalOut As JavaObject = system.GetField("out")
    originalOut.RunMethod("println", Array(message))
End Sub

#If Java
import java.io.PrintStream;
import java.lang.reflect.Method;

public class PrintStreamWrapper extends PrintStream {
    private Object b4jModule;

    public PrintStreamWrapper(PrintStream original, Object b4jModule) {
        super(original);
        this.b4jModule = b4jModule;
    }

    @Override
    public void println(String message) {
        try {
            if (b4jModule != null) {
                Method method = b4jModule.getClass().getMethod("ProcessLogMessage", String.class);
                method.invoke(b4jModule, message);
            } else {
                System.out.println("Error: b4jModule is null.");
            }
        } catch (Exception e) {
            System.out.println("Exception calling ProcessLogMessage: " + e.getMessage());
        }
    }
}
#End If

In DEBUG mode it compiles OK but fails with run time error:
Error occurred on line: 1295 (Main)
java.lang.ClassNotFoundException: java$lang$PrintStreamWrapper
at anywheresoftware.b4j.object.JavaObject.getCorrectClassName(JavaObject.java:289)
at anywheresoftware.b4j.object.JavaObject.InitializeNewInstance(JavaObject.java:84)
at com.ab.template.main._redirectfilteredlogs(main.java:3137)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
at java.base/java.lang.reflect.Method.invoke(Method.java:578)
at anywheresoftware.b4a.shell.Shell.runMethod(Shell.java:629)
at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:237)
at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:167)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
at java.base/java.lang.reflect.Method.invoke(Method.java:578)
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:111)
at anywheresoftware.b4a.shell.ShellBA.raiseEvent2(ShellBA.java:100)
at anywheresoftware.b4a.BA.raiseEvent(BA.java:98)
at anywheresoftware.b4a.shell.DebugResumableSub$RemoteResumableSub.resume(DebugResumableSub.java:21)
at anywheresoftware.b4a.BA.checkAndRunWaitForEvent(BA.java:156)
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:105)
at anywheresoftware.b4a.shell.ShellBA.raiseEvent2(ShellBA.java:100)
at anywheresoftware.b4a.BA.raiseEvent(BA.java:98)
at anywheresoftware.b4a.keywords.Common$3.run(Common.java:1118)
at anywheresoftware.b4a.keywords.SimpleMessageLoop.runMessageLoop(SimpleMessageLoop.java:47)
at anywheresoftware.b4a.StandardBA.startMessageLoop(StandardBA.java:43)
at anywheresoftware.b4a.shell.ShellBA.startMessageLoop(ShellBA.java:121)
at anywheresoftware.b4a.keywords.Common.StartMessageLoop(Common.java:180)
at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:309)
at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:167)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
at java.base/java.lang.reflect.Method.invoke(Method.java:578)
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:111)
at anywheresoftware.b4a.shell.ShellBA.raiseEvent2(ShellBA.java:100)
at anywheresoftware.b4a.BA.raiseEvent(BA.java:98)
at com.ab.template.main.main(main.java:31)
where line 1295 is:
filteredStream.InitializeNewInstance("PrintStreamWrapper", Array(originalOut, Me))

I know I'm doing something stupidly wrong but what?

Any help gratefully accepted...


EDIT: see final solution here:
https://www.b4x.com/android/forum/t...-with-assistance-of-microsoft-copilot.167188/
 
Last edited:

JackKirk

Well-Known Member
Licensed User
Longtime User
Digging a bit, i find that in ...\Objects\bin\classes\com\ab\template there is a file main$PrintStreamWrapper.class all freshly minted.

com.ab.template is the projects package name.
 
Upvote 0

hatzisn

Expert
Licensed User
Longtime User
Search in Google the full name of the class f.e. "xxxx.yyyyy.zzzzzzz.wwwwww.PrintStreamWrapper"
 
Upvote 0

hatzisn

Expert
Licensed User
Longtime User
Sorry, a mistake. Use your package name+module name in non capital letters+class name.
 
Upvote 0

hatzisn

Expert
Licensed User
Longtime User
And maybe module name is not needed.
 
Last edited:
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
The class should be defined as a static class:
B4X:
public static class PrintStreamWrapper extends PrintStream

And you need to include the package name:
B4X:
filteredStream.InitializeNewInstance("com.ab.template.main$PrintStreamWrapper", Array(originalOut, Me))
 
Upvote 0

JackKirk

Well-Known Member
Licensed User
Longtime User
The class should be defined as a static class:
B4X:
public static class PrintStreamWrapper extends PrintStream
And you need to include the package name:
B4X:
filteredStream.InitializeNewInstance("com.ab.template.main$PrintStreamWrapper", Array(originalOut, Me))
Thanks Erel, I now have a fully functioning Log message filter for B4J (well at least non-UI but should work on UI), see:
https://www.b4x.com/android/forum/t...-with-assistance-of-microsoft-copilot.167188/
 
Upvote 0
Top