Ah, thanks Jens.  I'm learning a lot about the GWT compiler!

It would be nice, in these situations, when using the codeserver, if GWT 
somehow either:
- Marked that line as not being able to put a breakpoint on, or
- Inserted a dummy line of JS code that allowed the breakpoint to be added 
in the correct place.

Maybe doing either of these just isn't possible.  It's just that I've 
wasted a bit of time in the past wondering why my breakpoints don't hit.  I 
usually get around it by adding a line of logging and putting a breakpoint 
on that.

On Thursday, 18 December 2025 at 1:35:48 am UTC+11 Jens wrote:

> In such a case you can keep the breakpoint you set in the Java file in the 
> browser and then open dev tools settings and disable sourcemaps. Then 
> reload the page and you see the original JS code. To better understand it 
> you can also add <style>PRETTY</style> to your root pom.xml below the 
> <launcherDir> configuration of the gwt-maven-plugin.
>
> You will see something like below with the bold line being the breakpoint 
> you set (I have added some comments above the functions):
>
> // thats the class initializer of MyHandler. It is empty because there is 
> no static {} block in Java
> function $clinit_App$1MyHandler_0_g$(){
>   $clinit_App$1MyHandler_0_g$ = Object;
>   $clinit_Object_0_g$();
> }
>
> // Thats the default constructor which receives everything that the nested 
> MyHandler class can reach in the outer class App.
> function App$1MyHandler_1_g$(this$0_0_g$, val$errorLabel_0_g$, 
> val$nameField_0_g$, val$sendButton_0_g$, val$textToServerLabel_0_g$, 
> val$serverResponseLabel_0_g$, val$dialogBox_0_g$, val$closeButton_0_g$){
>   $clinit_App$1MyHandler_0_g$();
>   this.this$01_1_g$ = this$0_0_g$;
>   this.val$errorLabel2_0_g$ = val$errorLabel_0_g$;
>   this.val$nameField3_0_g$ = val$nameField_0_g$;
>   this.val$sendButton4_0_g$ = val$sendButton_0_g$;
>   this.val$textToServerLabel5_0_g$ = val$textToServerLabel_0_g$;
>   this.val$serverResponseLabel6_0_g$ = val$serverResponseLabel_0_g$;
>   this.val$dialogBox7_0_g$ = val$dialogBox_0_g$;
>   this.val$closeButton8_0_g$ = val$closeButton_0_g$;
>   Object_1_g$.call(this);
>   this.$init_1443_g$();
> }
>
> // defineClass creates an underscore variable which is used to define all 
> the functions of MyHandler.
> defineClass_0_g$(5, 1, {5:1, 757:1, 838:1, 891:1, 1:1}, 
> App$1MyHandler_1_g$);
>
> // thats the instance initializer of MyHandler called by the constructor 
> above. It is empty because MyHandler does not have instance variables
> _.$init_1443_g$ = function $init_3_g$(){
>   $clinit_App$1MyHandler_0_g$();
> }
> ;
>
> // thats the lambda definition that you have used in the delay function. 
> *_.lambda$0_72_g$ = function lambda$0_1_g$(){*
>   $clinit_App$1MyHandler_0_g$();
>   {
>     this.sendNameToServer_1_g$();
>   }
> }
> ;
>
> // Here you see how GWT uses the lambda you have defined. 
> // GWT still uses for lambdas the same logic as for anonymous classes. 
> // So App$1MyHandler$lambda$0$Type_1_g$ is actually a class implementing 
> the functional interface 
> // and it receives the outer scope (MyHandler) so its execute() method 
> (from the interface) can 
> // call the lambda defined above on MyHandler.
> _.onClick_5_g$ = function onClick_1_g$(event_0_g$){
>   delay_0_g$(1000, new App$1MyHandler$lambda$0$Type_1_g$(this));
> }
> ;
> _.onKeyUp_5_g$ = function onKeyUp_0_g$(event_0_g$){
>   if (event_0_g$.getNativeKeyCode_1_g$() == 13) {
>     this.sendNameToServer_1_g$();
>   }
> }
> ;
> _.sendNameToServer_1_g$ = function sendNameToServer_0_g$(){
>   $clinit_App$1MyHandler_0_g$();
>   var textToServer_0_g$;
>   this.val$errorLabel2_0_g$.setText_15_g$('');
>   textToServer_0_g$ = this.val$nameField3_0_g$.getText_14_g$();
>   if (!isValidName_0_g$(textToServer_0_g$)) {
>     this.val$errorLabel2_0_g$.setText_15_g$('Please enter at least four 
> characters');
>     return;
>   }
>   this.val$sendButton4_0_g$.setEnabled_4_g$(false);
>   this.val$textToServerLabel5_0_g$.setText_15_g$(textToServer_0_g$);
>   this.val$serverResponseLabel6_0_g$.setText_15_g$('');
>   
> this.this$01_1_g$.greetingService_0_g$.greetServer_1_g$(textToServer_0_g$, 
> new App$1MyHandler$1_1_g$(this, this.val$dialogBox7_0_g$, 
> this.val$serverResponseLabel6_0_g$, this.val$closeButton8_0_g$));
> }
> ;
>
> // this creates the class literal for MyHandler
> var La_App$1MyHandler_2_classLit_0_g$ = createForClass_0_g$('a', 
> 'App/1MyHandler', 5, Ljava_lang_Object_2_classLit_0_g$);
>
>
> So when you place the breakpoint at the line you have used JS sourcemaps 
> maps that line to the definition of the lambda and not the call to delay(). 
> I am not sure if there is a right or wrong because it has to choose between 
> the two and generally before you can call delay() the lambda must be 
> created. So I think it is logical that way. In such cases you better place 
> the breakpoint inside the delay() function.
>
> -- J.
>
> Craig Mitchell schrieb am Mittwoch, 17. Dezember 2025 um 09:07:01 UTC+1:
>
>> I also just noticed, the breakpoint doesn't get hit when you click the 
>> "send" button on the page (when it should get hit).
>>
>> On Wednesday, 17 December 2025 at 7:03:18 pm UTC+11 Craig Mitchell wrote:
>>
>>> When debugging in Chrome, sometimes my breakpoints get hit on a page 
>>> refresh, but the code is not executed (nor should it be).
>>>
>>> I reproduced the issue with the following:
>>>
>>> 1. Create a sample project with 
>>> https://github.com/NaluKit/gwt-maven-springboot-archetype:
>>> mvn archetype:generate -DarchetypeGroupId=com.github.nalukit.archetype 
>>> -DarchetypeVersion=LATEST -DarchetypeArtifactId=modular-springboot-webapp
>>>
>>> (use any values, I just entered "a" for everything)
>>>
>>> 2. Modify the a-client\src\main\java\a\App.java with the following:
>>>
>>> 2.1 Add this static method:
>>> public static void delay(int delayMs, com.google.gwt.user.client.Command 
>>> run) {
>>> com.google.gwt.core.client.Scheduler.get().scheduleFixedDelay(() -> {
>>> run.execute();
>>> return false;
>>> }, delayMs);
>>> }
>>>
>>> 2.2 In the MyHandler class onClick, call the static method:
>>> public void onClick(ClickEvent event) {
>>> delay(1000, () -> {
>>> sendNameToServer();
>>> });
>>> }
>>>
>>> 3. Start it up:
>>> 3.1:  mvn gwt:codeserver -pl *-client -am
>>> 3.2:  mvn spring-boot:run -pl *-server -am
>>>
>>> 4. Open it in Chrome:  http://localhost:8080/
>>>
>>> 5. Open the Chrome debugger, put a breakpoint on the line:
>>> delay(1000, () -> {
>>>
>>> 6. Refresh the page.  The breakpoint gets hit.  It looks like this:
>>> [image: Screenshot 2025-12-17 185721.png]
>>>
>>> It doesn't have a call stack, and if you try to step into it, it doesn't 
>>> step into the delay method.
>>>
>>> Any idea why this occurs?
>>>
>>

-- 
You received this message because you are subscribed to the Google Groups "GWT 
Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion visit 
https://groups.google.com/d/msgid/google-web-toolkit/6cd54e22-6158-4e2b-b993-47430a625d27n%40googlegroups.com.

Reply via email to