[jira] [Comment Edited] (WICKET-6823) Two instances of AbstractTransformerBehavior on the same component results in incomplete output.

2020-08-30 Thread Sven Meier (Jira)


[ 
https://issues.apache.org/jira/browse/WICKET-6823?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel=17187338#comment-17187338
 ] 

Sven Meier edited comment on WICKET-6823 at 8/30/20, 9:51 PM:
--

Wicket 9.x tests all work fine with this change though.


was (Author: svenmeier):
Wicket tests all work fine with this change though.

> Two instances of AbstractTransformerBehavior on the same component results in 
> incomplete output.
> 
>
> Key: WICKET-6823
> URL: https://issues.apache.org/jira/browse/WICKET-6823
> Project: Wicket
>  Issue Type: Bug
>  Components: wicket-core
>Affects Versions: 8.9.0
>Reporter: Thorsten Schöning
>Assignee: Sven Meier
>Priority: Major
> Attachments: multiple_abstract_transformer_behavior.zip
>
>
> I'm using Wicket as a renderer for HTML-reports WITHOUT browser, web server 
> or requests, only by using ComponentRenderer. There are two implementations 
> of AbstractTransformerBehavior to update "colspan" attributes of table cells 
> and IDs of arbitrary HTML nodes. Both are used on the same component:
> {noformat}
> resultsCont.add(new DvResultsCont.ColSpanUpdater());
> resultsCont.add(new MkIdReplacer
> (
>   "th", "id", "td", "headers",
>   String.format("%d.%s", itemIdx, kindOfDetail)
> ));
> {noformat}
> When only ONE of both behaviours is used, the page renders successfully and 
> it doesn't make any difference which one is used. If both of those are used 
> OTOH, the page seems to be rendered at all as well, but some rendered content 
> is simply missing in the overall output in the end. My component 
> "resultsCont" renders to a table, so the last markup I have is the following:
> {noformat}
> 
> [...]
> 
> {noformat}
> In theory, after that table there should be additional content like foots, 
> closing elements for HTML itself etc. So the current rendering is invalid. 
> It's important to note, though, that I don't get any exception, the output 
> simply seems to not contain all data. When enabling DEBUG logging during 
> rendering, the logs make pretty much clear that Wicket really tries to 
> continue rendering, but the output is simply missing.
> As no exceptions are thrown and output seems to simply be ignored at some 
> point, I have the feeling the problem is in handling the response objects in 
> "AbstractTransformerBehavior". All of those assigned transformers to some 
> component are called before actually rendering anything and change the 
> response. "Component.java" contains the following code:
> {noformat}
> /**
>  * {@link Behavior#beforeRender(Component)} Notify all behaviors that are 
> assigned to this
>  * component that the component is about to be rendered.
>  */
> private void notifyBehaviorsComponentBeforeRender()
> {
>   for (Behavior behavior : getBehaviors())
>   {
>   if (isBehaviorAccepted(behavior))
>   {
>   behavior.beforeRender(this);
>   }
>   }
> }
> {noformat}
> Each call to "beforeRender" changes the response and all those changes are 
> done one after another. This means that the current request to render two 
> will be that one of the LAST applied transformer only.
> {noformat}
> @Override
> public void beforeRender(Component component)
> {
>   super.beforeRender(component);
>   final RequestCycle requestCycle = RequestCycle.get();
>   // Temporarily replace the web response with a String response
>   originalResponse = requestCycle.getResponse();
>   WebResponse origResponse = (WebResponse)((originalResponse instanceof 
> WebResponse)
>   ? originalResponse : null);
>   BufferedWebResponse tempResponse = newResponse(origResponse);
>   // temporarily set StringResponse to collect the transformed output
>   requestCycle.setResponse(tempResponse);
> }
> {noformat}
> Only after all those changes to the current request, content is rendered and 
> transformed, using the current request AND changing it back to what each 
> individual transformer believes to be the original request.
> {noformat}
> @Override
> public void afterRender(final Component component)
> {
>   final RequestCycle requestCycle = RequestCycle.get();
>   try
>   {
>   BufferedWebResponse tempResponse = 
> (BufferedWebResponse)requestCycle.getResponse();
>   if (component instanceof Page && originalResponse instanceof 
> WebResponse)
>   {
>   tempResponse.writeMetaData((WebResponse) 
> originalResponse);
>   }
>   // Transform the data
>   CharSequence output = transform(component, 
> tempResponse.getText());
>   originalResponse.write(output);
>   }
>

[jira] [Commented] (WICKET-6823) Two instances of AbstractTransformerBehavior on the same component results in incomplete output.

2020-08-30 Thread Sven Meier (Jira)


[ 
https://issues.apache.org/jira/browse/WICKET-6823?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel=17187338#comment-17187338
 ] 

Sven Meier commented on WICKET-6823:


Wicket tests all work fine with this change though.

> Two instances of AbstractTransformerBehavior on the same component results in 
> incomplete output.
> 
>
> Key: WICKET-6823
> URL: https://issues.apache.org/jira/browse/WICKET-6823
> Project: Wicket
>  Issue Type: Bug
>  Components: wicket-core
>Affects Versions: 8.9.0
>Reporter: Thorsten Schöning
>Assignee: Sven Meier
>Priority: Major
> Attachments: multiple_abstract_transformer_behavior.zip
>
>
> I'm using Wicket as a renderer for HTML-reports WITHOUT browser, web server 
> or requests, only by using ComponentRenderer. There are two implementations 
> of AbstractTransformerBehavior to update "colspan" attributes of table cells 
> and IDs of arbitrary HTML nodes. Both are used on the same component:
> {noformat}
> resultsCont.add(new DvResultsCont.ColSpanUpdater());
> resultsCont.add(new MkIdReplacer
> (
>   "th", "id", "td", "headers",
>   String.format("%d.%s", itemIdx, kindOfDetail)
> ));
> {noformat}
> When only ONE of both behaviours is used, the page renders successfully and 
> it doesn't make any difference which one is used. If both of those are used 
> OTOH, the page seems to be rendered at all as well, but some rendered content 
> is simply missing in the overall output in the end. My component 
> "resultsCont" renders to a table, so the last markup I have is the following:
> {noformat}
> 
> [...]
> 
> {noformat}
> In theory, after that table there should be additional content like foots, 
> closing elements for HTML itself etc. So the current rendering is invalid. 
> It's important to note, though, that I don't get any exception, the output 
> simply seems to not contain all data. When enabling DEBUG logging during 
> rendering, the logs make pretty much clear that Wicket really tries to 
> continue rendering, but the output is simply missing.
> As no exceptions are thrown and output seems to simply be ignored at some 
> point, I have the feeling the problem is in handling the response objects in 
> "AbstractTransformerBehavior". All of those assigned transformers to some 
> component are called before actually rendering anything and change the 
> response. "Component.java" contains the following code:
> {noformat}
> /**
>  * {@link Behavior#beforeRender(Component)} Notify all behaviors that are 
> assigned to this
>  * component that the component is about to be rendered.
>  */
> private void notifyBehaviorsComponentBeforeRender()
> {
>   for (Behavior behavior : getBehaviors())
>   {
>   if (isBehaviorAccepted(behavior))
>   {
>   behavior.beforeRender(this);
>   }
>   }
> }
> {noformat}
> Each call to "beforeRender" changes the response and all those changes are 
> done one after another. This means that the current request to render two 
> will be that one of the LAST applied transformer only.
> {noformat}
> @Override
> public void beforeRender(Component component)
> {
>   super.beforeRender(component);
>   final RequestCycle requestCycle = RequestCycle.get();
>   // Temporarily replace the web response with a String response
>   originalResponse = requestCycle.getResponse();
>   WebResponse origResponse = (WebResponse)((originalResponse instanceof 
> WebResponse)
>   ? originalResponse : null);
>   BufferedWebResponse tempResponse = newResponse(origResponse);
>   // temporarily set StringResponse to collect the transformed output
>   requestCycle.setResponse(tempResponse);
> }
> {noformat}
> Only after all those changes to the current request, content is rendered and 
> transformed, using the current request AND changing it back to what each 
> individual transformer believes to be the original request.
> {noformat}
> @Override
> public void afterRender(final Component component)
> {
>   final RequestCycle requestCycle = RequestCycle.get();
>   try
>   {
>   BufferedWebResponse tempResponse = 
> (BufferedWebResponse)requestCycle.getResponse();
>   if (component instanceof Page && originalResponse instanceof 
> WebResponse)
>   {
>   tempResponse.writeMetaData((WebResponse) 
> originalResponse);
>   }
>   // Transform the data
>   CharSequence output = transform(component, 
> tempResponse.getText());
>   originalResponse.write(output);
>   }
>   catch (Exception ex)
>   {
>   throw new WicketRuntimeException("Error while transforming the 
> output of 

[jira] [Commented] (WICKET-6823) Two instances of AbstractTransformerBehavior on the same component results in incomplete output.

2020-08-30 Thread Sven Meier (Jira)


[ 
https://issues.apache.org/jira/browse/WICKET-6823?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel=17187335#comment-17187335
 ] 

Sven Meier commented on WICKET-6823:


Problem is that #beforeRender() and #afterRender() are *not* invoked 'nested' 
on the behaviors:
 * beforeRender is called on FooTrans
 * beforeRender is called on BarTrans
 * afterRender is called on FooTrans
 * afterRender is called on BarTrans

To allow multiple transformers the sequence has to be:
 * beforeRender is called on FooTrans
 * beforeRender is called on BarTrans
 * afterRender is called on BarTrans
 * afterRender is called on FooTrans

This can be fixed by reversing the iteration in 
Component#notifyBehaviorsComponentRendered()
{code:java}
private void notifyBehaviorsComponentRendered()
{
  // notify the behaviors in *reverse* that component has been rendered
  for (Behavior behavior : new ReverseListIterator<>(getBehaviors()))
  {
 if (isBehaviorAccepted(behavior))
 {
   behavior.afterRender(this);
 }
  }
}{code}
This might break existing applications, so we'll have to decide whether this 
change is worth it. Personally I never used more than one transformer on a 
component.

> Two instances of AbstractTransformerBehavior on the same component results in 
> incomplete output.
> 
>
> Key: WICKET-6823
> URL: https://issues.apache.org/jira/browse/WICKET-6823
> Project: Wicket
>  Issue Type: Bug
>  Components: wicket-core
>Affects Versions: 8.9.0
>Reporter: Thorsten Schöning
>Assignee: Sven Meier
>Priority: Major
> Attachments: multiple_abstract_transformer_behavior.zip
>
>
> I'm using Wicket as a renderer for HTML-reports WITHOUT browser, web server 
> or requests, only by using ComponentRenderer. There are two implementations 
> of AbstractTransformerBehavior to update "colspan" attributes of table cells 
> and IDs of arbitrary HTML nodes. Both are used on the same component:
> {noformat}
> resultsCont.add(new DvResultsCont.ColSpanUpdater());
> resultsCont.add(new MkIdReplacer
> (
>   "th", "id", "td", "headers",
>   String.format("%d.%s", itemIdx, kindOfDetail)
> ));
> {noformat}
> When only ONE of both behaviours is used, the page renders successfully and 
> it doesn't make any difference which one is used. If both of those are used 
> OTOH, the page seems to be rendered at all as well, but some rendered content 
> is simply missing in the overall output in the end. My component 
> "resultsCont" renders to a table, so the last markup I have is the following:
> {noformat}
> 
> [...]
> 
> {noformat}
> In theory, after that table there should be additional content like foots, 
> closing elements for HTML itself etc. So the current rendering is invalid. 
> It's important to note, though, that I don't get any exception, the output 
> simply seems to not contain all data. When enabling DEBUG logging during 
> rendering, the logs make pretty much clear that Wicket really tries to 
> continue rendering, but the output is simply missing.
> As no exceptions are thrown and output seems to simply be ignored at some 
> point, I have the feeling the problem is in handling the response objects in 
> "AbstractTransformerBehavior". All of those assigned transformers to some 
> component are called before actually rendering anything and change the 
> response. "Component.java" contains the following code:
> {noformat}
> /**
>  * {@link Behavior#beforeRender(Component)} Notify all behaviors that are 
> assigned to this
>  * component that the component is about to be rendered.
>  */
> private void notifyBehaviorsComponentBeforeRender()
> {
>   for (Behavior behavior : getBehaviors())
>   {
>   if (isBehaviorAccepted(behavior))
>   {
>   behavior.beforeRender(this);
>   }
>   }
> }
> {noformat}
> Each call to "beforeRender" changes the response and all those changes are 
> done one after another. This means that the current request to render two 
> will be that one of the LAST applied transformer only.
> {noformat}
> @Override
> public void beforeRender(Component component)
> {
>   super.beforeRender(component);
>   final RequestCycle requestCycle = RequestCycle.get();
>   // Temporarily replace the web response with a String response
>   originalResponse = requestCycle.getResponse();
>   WebResponse origResponse = (WebResponse)((originalResponse instanceof 
> WebResponse)
>   ? originalResponse : null);
>   BufferedWebResponse tempResponse = newResponse(origResponse);
>   // temporarily set StringResponse to collect the transformed output
>   requestCycle.setResponse(tempResponse);
> }
> {noformat}
> Only after all those changes to the current request, 

[jira] [Assigned] (WICKET-6823) Two instances of AbstractTransformerBehavior on the same component results in incomplete output.

2020-08-30 Thread Sven Meier (Jira)


 [ 
https://issues.apache.org/jira/browse/WICKET-6823?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Sven Meier reassigned WICKET-6823:
--

Assignee: Sven Meier

> Two instances of AbstractTransformerBehavior on the same component results in 
> incomplete output.
> 
>
> Key: WICKET-6823
> URL: https://issues.apache.org/jira/browse/WICKET-6823
> Project: Wicket
>  Issue Type: Bug
>  Components: wicket-core
>Affects Versions: 8.9.0
>Reporter: Thorsten Schöning
>Assignee: Sven Meier
>Priority: Major
> Attachments: multiple_abstract_transformer_behavior.zip
>
>
> I'm using Wicket as a renderer for HTML-reports WITHOUT browser, web server 
> or requests, only by using ComponentRenderer. There are two implementations 
> of AbstractTransformerBehavior to update "colspan" attributes of table cells 
> and IDs of arbitrary HTML nodes. Both are used on the same component:
> {noformat}
> resultsCont.add(new DvResultsCont.ColSpanUpdater());
> resultsCont.add(new MkIdReplacer
> (
>   "th", "id", "td", "headers",
>   String.format("%d.%s", itemIdx, kindOfDetail)
> ));
> {noformat}
> When only ONE of both behaviours is used, the page renders successfully and 
> it doesn't make any difference which one is used. If both of those are used 
> OTOH, the page seems to be rendered at all as well, but some rendered content 
> is simply missing in the overall output in the end. My component 
> "resultsCont" renders to a table, so the last markup I have is the following:
> {noformat}
> 
> [...]
> 
> {noformat}
> In theory, after that table there should be additional content like foots, 
> closing elements for HTML itself etc. So the current rendering is invalid. 
> It's important to note, though, that I don't get any exception, the output 
> simply seems to not contain all data. When enabling DEBUG logging during 
> rendering, the logs make pretty much clear that Wicket really tries to 
> continue rendering, but the output is simply missing.
> As no exceptions are thrown and output seems to simply be ignored at some 
> point, I have the feeling the problem is in handling the response objects in 
> "AbstractTransformerBehavior". All of those assigned transformers to some 
> component are called before actually rendering anything and change the 
> response. "Component.java" contains the following code:
> {noformat}
> /**
>  * {@link Behavior#beforeRender(Component)} Notify all behaviors that are 
> assigned to this
>  * component that the component is about to be rendered.
>  */
> private void notifyBehaviorsComponentBeforeRender()
> {
>   for (Behavior behavior : getBehaviors())
>   {
>   if (isBehaviorAccepted(behavior))
>   {
>   behavior.beforeRender(this);
>   }
>   }
> }
> {noformat}
> Each call to "beforeRender" changes the response and all those changes are 
> done one after another. This means that the current request to render two 
> will be that one of the LAST applied transformer only.
> {noformat}
> @Override
> public void beforeRender(Component component)
> {
>   super.beforeRender(component);
>   final RequestCycle requestCycle = RequestCycle.get();
>   // Temporarily replace the web response with a String response
>   originalResponse = requestCycle.getResponse();
>   WebResponse origResponse = (WebResponse)((originalResponse instanceof 
> WebResponse)
>   ? originalResponse : null);
>   BufferedWebResponse tempResponse = newResponse(origResponse);
>   // temporarily set StringResponse to collect the transformed output
>   requestCycle.setResponse(tempResponse);
> }
> {noformat}
> Only after all those changes to the current request, content is rendered and 
> transformed, using the current request AND changing it back to what each 
> individual transformer believes to be the original request.
> {noformat}
> @Override
> public void afterRender(final Component component)
> {
>   final RequestCycle requestCycle = RequestCycle.get();
>   try
>   {
>   BufferedWebResponse tempResponse = 
> (BufferedWebResponse)requestCycle.getResponse();
>   if (component instanceof Page && originalResponse instanceof 
> WebResponse)
>   {
>   tempResponse.writeMetaData((WebResponse) 
> originalResponse);
>   }
>   // Transform the data
>   CharSequence output = transform(component, 
> tempResponse.getText());
>   originalResponse.write(output);
>   }
>   catch (Exception ex)
>   {
>   throw new WicketRuntimeException("Error while transforming the 
> output of component: " +
>   component, ex);
>   }
>   

[jira] [Commented] (WICKET-6824) Use concatenation instead of String.format for frequently called methods

2020-08-30 Thread Sven Meier (Jira)


[ 
https://issues.apache.org/jira/browse/WICKET-6824?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel=17187326#comment-17187326
 ] 

Sven Meier commented on WICKET-6824:


Thanks Thomas, your performance analyses are highly appreciated.

Sorry that I've already merged your PR, I didn't recognize you when looking at 
it.

> Use concatenation instead of String.format for frequently called methods
> 
>
> Key: WICKET-6824
> URL: https://issues.apache.org/jira/browse/WICKET-6824
> Project: Wicket
>  Issue Type: Improvement
>  Components: wicket-core
>Affects Versions: 9.0.0
>Reporter: Thomas Heigl
>Assignee: Thomas Heigl
>Priority: Minor
> Attachments: image-2020-08-30-20-34-57-261.png, 
> image-2020-08-30-20-35-04-970.png
>
>
> Two usages of {{String.format}} frequently show up in my production profiler:
> !image-2020-08-30-20-34-57-261.png!
> !image-2020-08-30-20-35-04-970.png!
> Both methods are potentially called dozens or even hundreds of times for 
> large pages.
> {{String.format}} has horrible performance and should mostly be used for 
> generating error messages and debug information. For a detailed analysis see: 
> [https://redfin.engineering/java-string-concatenation-which-way-is-best-8f590a7d22a8]
> We should replace {{String.format}} with simple concatenation in both 
> instances.



--
This message was sent by Atlassian Jira
(v8.3.4#803005)


buildbot failure in on wicket-master-java14

2020-08-30 Thread buildbot
The Buildbot has detected a new failure on builder wicket-master-java14 while 
building wicket. Full details are available at:
https://ci.apache.org/builders/wicket-master-java14/builds/235

Buildbot URL: https://ci.apache.org/

Buildslave for this Build: bb_slave6_ubuntu

Build Reason: The SingleBranchScheduler scheduler named 
'on-wicket-master-java14-commit' triggered this build
Build Source Stamp: [branch master] ad5e81b83b49ba1b58945cb14df1a63fa508f44a
Blamelist: Thomas Heigl 

BUILD FAILED: failed compile

Sincerely,
 -The Buildbot





[jira] [Commented] (WICKET-6824) Use concatenation instead of String.format for frequently called methods

2020-08-30 Thread ASF subversion and git services (Jira)


[ 
https://issues.apache.org/jira/browse/WICKET-6824?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel=17187324#comment-17187324
 ] 

ASF subversion and git services commented on WICKET-6824:
-

Commit ad5e81b83b49ba1b58945cb14df1a63fa508f44a in wicket's branch 
refs/heads/master from Thomas Heigl
[ https://gitbox.apache.org/repos/asf?p=wicket.git;h=ad5e81b ]

WICKET-6824 Replace slow `String.format` with concatenation

This closes #449

> Use concatenation instead of String.format for frequently called methods
> 
>
> Key: WICKET-6824
> URL: https://issues.apache.org/jira/browse/WICKET-6824
> Project: Wicket
>  Issue Type: Improvement
>  Components: wicket-core
>Affects Versions: 9.0.0
>Reporter: Thomas Heigl
>Assignee: Thomas Heigl
>Priority: Minor
> Attachments: image-2020-08-30-20-34-57-261.png, 
> image-2020-08-30-20-35-04-970.png
>
>
> Two usages of {{String.format}} frequently show up in my production profiler:
> !image-2020-08-30-20-34-57-261.png!
> !image-2020-08-30-20-35-04-970.png!
> Both methods are potentially called dozens or even hundreds of times for 
> large pages.
> {{String.format}} has horrible performance and should mostly be used for 
> generating error messages and debug information. For a detailed analysis see: 
> [https://redfin.engineering/java-string-concatenation-which-way-is-best-8f590a7d22a8]
> We should replace {{String.format}} with simple concatenation in both 
> instances.



--
This message was sent by Atlassian Jira
(v8.3.4#803005)


[wicket] branch master updated: WICKET-6824 Replace slow `String.format` with concatenation

2020-08-30 Thread svenmeier
This is an automated email from the ASF dual-hosted git repository.

svenmeier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/wicket.git


The following commit(s) were added to refs/heads/master by this push:
 new ad5e81b  WICKET-6824 Replace slow `String.format` with concatenation
ad5e81b is described below

commit ad5e81b83b49ba1b58945cb14df1a63fa508f44a
Author: Thomas Heigl 
AuthorDate: Sun Aug 30 20:42:46 2020 +0200

WICKET-6824 Replace slow `String.format` with concatenation

This closes #449
---
 .../src/main/java/org/apache/wicket/Component.java |  6 ++-
 .../wicket/ajax/AbstractDefaultAjaxBehavior.java   | 52 +++---
 2 files changed, 31 insertions(+), 27 deletions(-)

diff --git a/wicket-core/src/main/java/org/apache/wicket/Component.java 
b/wicket-core/src/main/java/org/apache/wicket/Component.java
index d72f24e..423355c 100644
--- a/wicket-core/src/main/java/org/apache/wicket/Component.java
+++ b/wicket-core/src/main/java/org/apache/wicket/Component.java
@@ -2365,9 +2365,11 @@ public abstract class Component
{
String name = Strings.isEmpty(tag.getNamespace()) ? 
tag.getName()
: tag.getNamespace() + ':' + tag.getName();
+   
+   // prefer concatenation over String#format() for performance 
response.write(
-   String.format("<%s id=\"%s\" hidden=\"\" 
data-wicket-placeholder=\"\">", name,
-   getAjaxRegionMarkupId(), name));
+   "<" + name + " id=\"" + getAjaxRegionMarkupId() +
+   "\" hidden=\"\" 
data-wicket-placeholder=\"\">");
}
 
 
diff --git 
a/wicket-core/src/main/java/org/apache/wicket/ajax/AbstractDefaultAjaxBehavior.java
 
b/wicket-core/src/main/java/org/apache/wicket/ajax/AbstractDefaultAjaxBehavior.java
index 291303f..7da491b 100644
--- 
a/wicket-core/src/main/java/org/apache/wicket/ajax/AbstractDefaultAjaxBehavior.java
+++ 
b/wicket-core/src/main/java/org/apache/wicket/ajax/AbstractDefaultAjaxBehavior.java
@@ -61,16 +61,16 @@ public abstract class AbstractDefaultAjaxBehavior extends 
AbstractAjaxBehavior
public static final ResourceReference INDICATOR = new 
PackageResourceReference(
AbstractDefaultAjaxBehavior.class, "indicator.gif");
 
-   private static final String DYNAMIC_PARAMETER_FUNCTION_TEMPLATE = 
"function(attrs){%s}";
-   private static final String PRECONDITION_FUNCTION_TEMPLATE = 
"function(attrs){%s}";
-   private static final String COMPLETE_HANDLER_FUNCTION_TEMPLATE = 
"function(attrs, jqXHR, textStatus){%s}";
-   private static final String FAILURE_HANDLER_FUNCTION_TEMPLATE = 
"function(attrs, jqXHR, errorMessage, textStatus){%s}";
-   private static final String SUCCESS_HANDLER_FUNCTION_TEMPLATE = 
"function(attrs, jqXHR, data, textStatus){%s}";
-   private static final String AFTER_HANDLER_FUNCTION_TEMPLATE = 
"function(attrs){%s}";
-   private static final String BEFORE_SEND_HANDLER_FUNCTION_TEMPLATE = 
"function(attrs, jqXHR, settings){%s}";
-   private static final String BEFORE_HANDLER_FUNCTION_TEMPLATE = 
"function(attrs){%s}";
-   private static final String INIT_HANDLER_FUNCTION_TEMPLATE = 
"function(attrs){%s}";
-   private static final String DONE_HANDLER_FUNCTION_TEMPLATE = 
"function(attrs){%s}";
+   private static final String DYNAMIC_PARAMETER_FUNCTION_SIGNATURE = 
"function(attrs)";
+   private static final String PRECONDITION_FUNCTION_SIGNATURE = 
"function(attrs)";
+   private static final String COMPLETE_HANDLER_FUNCTION_SIGNATURE = 
"function(attrs, jqXHR, textStatus)";
+   private static final String FAILURE_HANDLER_FUNCTION_SIGNATURE = 
"function(attrs, jqXHR, errorMessage, textStatus)";
+   private static final String SUCCESS_HANDLER_FUNCTION_SIGNATURE = 
"function(attrs, jqXHR, data, textStatus)";
+   private static final String AFTER_HANDLER_FUNCTION_SIGNATURE = 
"function(attrs)";
+   private static final String BEFORE_SEND_HANDLER_FUNCTION_SIGNATURE = 
"function(attrs, jqXHR, settings)";
+   private static final String BEFORE_HANDLER_FUNCTION_SIGNATURE = 
"function(attrs)";
+   private static final String INIT_HANDLER_FUNCTION_SIGNATURE = 
"function(attrs)";
+   private static final String DONE_HANDLER_FUNCTION_SIGNATURE = 
"function(attrs)";
 
/**
 * Subclasses should call super.onBind()
@@ -261,46 +261,46 @@ public abstract class AbstractDefaultAjaxBehavior extends 
AbstractAjaxBehavior
CharSequence initHandler = 
ajaxCallListener.getInitHandler(component);
appendListenerHandler(initHandler, 
attributesJson,

AjaxAttributeName.INIT_HANDLER.jsonName(),
-   INIT_HANDLER_FUNCTION_TEMPLATE);
+ 

[jira] [Commented] (WICKET-6824) Use concatenation instead of String.format for frequently called methods

2020-08-30 Thread Thomas Heigl (Jira)


[ 
https://issues.apache.org/jira/browse/WICKET-6824?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel=17187314#comment-17187314
 ] 

Thomas Heigl commented on WICKET-6824:
--

Created PR: https://github.com/apache/wicket/pull/449

> Use concatenation instead of String.format for frequently called methods
> 
>
> Key: WICKET-6824
> URL: https://issues.apache.org/jira/browse/WICKET-6824
> Project: Wicket
>  Issue Type: Improvement
>  Components: wicket-core
>Affects Versions: 9.0.0
>Reporter: Thomas Heigl
>Assignee: Thomas Heigl
>Priority: Minor
> Attachments: image-2020-08-30-20-34-57-261.png, 
> image-2020-08-30-20-35-04-970.png
>
>
> Two usages of {{String.format}} frequently show up in my production profiler:
> !image-2020-08-30-20-34-57-261.png!
> !image-2020-08-30-20-35-04-970.png!
> Both methods are potentially called dozens or even hundreds of times for 
> large pages.
> {{String.format}} has horrible performance and should mostly be used for 
> generating error messages and debug information. For a detailed analysis see: 
> [https://redfin.engineering/java-string-concatenation-which-way-is-best-8f590a7d22a8]
> We should replace {{String.format}} with simple concatenation in both 
> instances.



--
This message was sent by Atlassian Jira
(v8.3.4#803005)


[jira] [Created] (WICKET-6824) Use concatenation instead of String.format for frequently called methods

2020-08-30 Thread Thomas Heigl (Jira)
Thomas Heigl created WICKET-6824:


 Summary: Use concatenation instead of String.format for frequently 
called methods
 Key: WICKET-6824
 URL: https://issues.apache.org/jira/browse/WICKET-6824
 Project: Wicket
  Issue Type: Improvement
  Components: wicket-core
Affects Versions: 9.0.0
Reporter: Thomas Heigl
Assignee: Thomas Heigl
 Attachments: image-2020-08-30-20-34-57-261.png, 
image-2020-08-30-20-35-04-970.png

Two usages of {{String.format}} frequently show up in my production profiler:

!image-2020-08-30-20-34-57-261.png!

!image-2020-08-30-20-35-04-970.png!

Both methods are potentially called dozens or even hundreds of times for large 
pages.

{{String.format}} has horrible performance and should mostly be used for 
generating error messages and debug information. For a detailed analysis see: 
[https://redfin.engineering/java-string-concatenation-which-way-is-best-8f590a7d22a8]

We should replace {{String.format}} with simple concatenation in both instances.



--
This message was sent by Atlassian Jira
(v8.3.4#803005)


[jira] [Commented] (WICKET-6823) Two instances of AbstractTransformerBehavior on the same component results in incomplete output.

2020-08-30 Thread Jira


[ 
https://issues.apache.org/jira/browse/WICKET-6823?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel=17187289#comment-17187289
 ] 

Thorsten Schöning commented on WICKET-6823:
---

I've attached a quickstart demonstrating the issue by creating two very simple 
transformers to change the version number rendered on runtime. When attaching 
only one transformer, the textual phrase "" is found in the rendered 
output, otherwise it's not. This demonstrates the overall problem, that neither 
the output of the transformer itself is available, e..g the phrase "bar" in 
this test, nor any markup after the component the two transformers are applied 
to.

{noformat}
String  version = getApplication().getFrameworkSettings().getVersion();
Label   label   = new Label("version", version);

label.add(new FooTrans());
//label.add(new BarTrans());
{noformat}

Just change the comment about "BarTrans" to make the test succeed or fail. If 
it fails, the stacktrace already shows where the HTML-output stops as well:

{noformat}
junit.framework.AssertionFailedError: pattern '' not found in:

http://wicket.apache.org;>


Apache Wicket Quickstart







Apache Wicket



Reporting a bug

Help us help you:


reproduce the bug with the 
least amount of code
create a unit test that shows the bug
fix the bug and create a patch
attach the result of step 1, 2 or 3 to a https://issues.apache.org/jira/browse/WICKET; target="_blank">JIRA 
issue
profit!


Please mention the correct Wicket version: 
8.9.0 foo
at 
org.apache.wicket.util.tester.WicketTester.assertResult(WicketTester.java:798)
at 
org.apache.wicket.util.tester.WicketTester.assertContains(WicketTester.java:365)
at 
de.am_soft.TestHomePage.homepageRendersSuccessfully(TestHomePage.java:31)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at 
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at 
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at 
org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at 
org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at 
org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at 
org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at 
org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at 
org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at 
org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at 
org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:89)
at 
org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:41)
at 
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:542)
at 
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:770)
at 
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:464)
at 
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:210)
{noformat}


> Two instances of AbstractTransformerBehavior on the same component results in 
> incomplete output.
> 
>
> Key: WICKET-6823
> URL: https://issues.apache.org/jira/browse/WICKET-6823
> Project: Wicket
>  Issue Type: Bug
>  Components: wicket-core
>Affects Versions: 8.9.0
> 

[jira] [Updated] (WICKET-6823) Two instances of AbstractTransformerBehavior on the same component results in incomplete output.

2020-08-30 Thread Jira


 [ 
https://issues.apache.org/jira/browse/WICKET-6823?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Thorsten Schöning updated WICKET-6823:
--
Attachment: multiple_abstract_transformer_behavior.zip

> Two instances of AbstractTransformerBehavior on the same component results in 
> incomplete output.
> 
>
> Key: WICKET-6823
> URL: https://issues.apache.org/jira/browse/WICKET-6823
> Project: Wicket
>  Issue Type: Bug
>  Components: wicket-core
>Affects Versions: 8.9.0
>Reporter: Thorsten Schöning
>Priority: Major
> Attachments: multiple_abstract_transformer_behavior.zip
>
>
> I'm using Wicket as a renderer for HTML-reports WITHOUT browser, web server 
> or requests, only by using ComponentRenderer. There are two implementations 
> of AbstractTransformerBehavior to update "colspan" attributes of table cells 
> and IDs of arbitrary HTML nodes. Both are used on the same component:
> {noformat}
> resultsCont.add(new DvResultsCont.ColSpanUpdater());
> resultsCont.add(new MkIdReplacer
> (
>   "th", "id", "td", "headers",
>   String.format("%d.%s", itemIdx, kindOfDetail)
> ));
> {noformat}
> When only ONE of both behaviours is used, the page renders successfully and 
> it doesn't make any difference which one is used. If both of those are used 
> OTOH, the page seems to be rendered at all as well, but some rendered content 
> is simply missing in the overall output in the end. My component 
> "resultsCont" renders to a table, so the last markup I have is the following:
> {noformat}
> 
> [...]
> 
> {noformat}
> In theory, after that table there should be additional content like foots, 
> closing elements for HTML itself etc. So the current rendering is invalid. 
> It's important to note, though, that I don't get any exception, the output 
> simply seems to not contain all data. When enabling DEBUG logging during 
> rendering, the logs make pretty much clear that Wicket really tries to 
> continue rendering, but the output is simply missing.
> As no exceptions are thrown and output seems to simply be ignored at some 
> point, I have the feeling the problem is in handling the response objects in 
> "AbstractTransformerBehavior". All of those assigned transformers to some 
> component are called before actually rendering anything and change the 
> response. "Component.java" contains the following code:
> {noformat}
> /**
>  * {@link Behavior#beforeRender(Component)} Notify all behaviors that are 
> assigned to this
>  * component that the component is about to be rendered.
>  */
> private void notifyBehaviorsComponentBeforeRender()
> {
>   for (Behavior behavior : getBehaviors())
>   {
>   if (isBehaviorAccepted(behavior))
>   {
>   behavior.beforeRender(this);
>   }
>   }
> }
> {noformat}
> Each call to "beforeRender" changes the response and all those changes are 
> done one after another. This means that the current request to render two 
> will be that one of the LAST applied transformer only.
> {noformat}
> @Override
> public void beforeRender(Component component)
> {
>   super.beforeRender(component);
>   final RequestCycle requestCycle = RequestCycle.get();
>   // Temporarily replace the web response with a String response
>   originalResponse = requestCycle.getResponse();
>   WebResponse origResponse = (WebResponse)((originalResponse instanceof 
> WebResponse)
>   ? originalResponse : null);
>   BufferedWebResponse tempResponse = newResponse(origResponse);
>   // temporarily set StringResponse to collect the transformed output
>   requestCycle.setResponse(tempResponse);
> }
> {noformat}
> Only after all those changes to the current request, content is rendered and 
> transformed, using the current request AND changing it back to what each 
> individual transformer believes to be the original request.
> {noformat}
> @Override
> public void afterRender(final Component component)
> {
>   final RequestCycle requestCycle = RequestCycle.get();
>   try
>   {
>   BufferedWebResponse tempResponse = 
> (BufferedWebResponse)requestCycle.getResponse();
>   if (component instanceof Page && originalResponse instanceof 
> WebResponse)
>   {
>   tempResponse.writeMetaData((WebResponse) 
> originalResponse);
>   }
>   // Transform the data
>   CharSequence output = transform(component, 
> tempResponse.getText());
>   originalResponse.write(output);
>   }
>   catch (Exception ex)
>   {
>   throw new WicketRuntimeException("Error while transforming the 
> output of component: " +
>   component, ex);
>  

[jira] [Created] (WICKET-6823) Two instances of AbstractTransformerBehavior on the same component results in incomplete output.

2020-08-30 Thread Jira
Thorsten Schöning created WICKET-6823:
-

 Summary: Two instances of AbstractTransformerBehavior on the same 
component results in incomplete output.
 Key: WICKET-6823
 URL: https://issues.apache.org/jira/browse/WICKET-6823
 Project: Wicket
  Issue Type: Bug
  Components: wicket-core
Affects Versions: 8.9.0
Reporter: Thorsten Schöning


I'm using Wicket as a renderer for HTML-reports WITHOUT browser, web server or 
requests, only by using ComponentRenderer. There are two implementations of 
AbstractTransformerBehavior to update "colspan" attributes of table cells and 
IDs of arbitrary HTML nodes. Both are used on the same component:

{noformat}
resultsCont.add(new DvResultsCont.ColSpanUpdater());
resultsCont.add(new MkIdReplacer
(
  "th", "id", "td", "headers",
  String.format("%d.%s", itemIdx, kindOfDetail)
));
{noformat}

When only ONE of both behaviours is used, the page renders successfully and it 
doesn't make any difference which one is used. If both of those are used OTOH, 
the page seems to be rendered at all as well, but some rendered content is 
simply missing in the overall output in the end. My component "resultsCont" 
renders to a table, so the last markup I have is the following:

{noformat}

[...]

{noformat}

In theory, after that table there should be additional content like foots, 
closing elements for HTML itself etc. So the current rendering is invalid. It's 
important to note, though, that I don't get any exception, the output simply 
seems to not contain all data. When enabling DEBUG logging during rendering, 
the logs make pretty much clear that Wicket really tries to continue rendering, 
but the output is simply missing.

As no exceptions are thrown and output seems to simply be ignored at some 
point, I have the feeling the problem is in handling the response objects in 
"AbstractTransformerBehavior". All of those assigned transformers to some 
component are called before actually rendering anything and change the 
response. "Component.java" contains the following code:

{noformat}
/**
 * {@link Behavior#beforeRender(Component)} Notify all behaviors that are 
assigned to this
 * component that the component is about to be rendered.
 */
private void notifyBehaviorsComponentBeforeRender()
{
for (Behavior behavior : getBehaviors())
{
if (isBehaviorAccepted(behavior))
{
behavior.beforeRender(this);
}
}
}
{noformat}

Each call to "beforeRender" changes the response and all those changes are done 
one after another. This means that the current request to render two will be 
that one of the LAST applied transformer only.

{noformat}
@Override
public void beforeRender(Component component)
{
super.beforeRender(component);

final RequestCycle requestCycle = RequestCycle.get();

// Temporarily replace the web response with a String response
originalResponse = requestCycle.getResponse();

WebResponse origResponse = (WebResponse)((originalResponse instanceof 
WebResponse)
? originalResponse : null);
BufferedWebResponse tempResponse = newResponse(origResponse);

// temporarily set StringResponse to collect the transformed output
requestCycle.setResponse(tempResponse);
}
{noformat}

Only after all those changes to the current request, content is rendered and 
transformed, using the current request AND changing it back to what each 
individual transformer believes to be the original request.

{noformat}
@Override
public void afterRender(final Component component)
{
final RequestCycle requestCycle = RequestCycle.get();

try
{
BufferedWebResponse tempResponse = 
(BufferedWebResponse)requestCycle.getResponse();

if (component instanceof Page && originalResponse instanceof 
WebResponse)
{
tempResponse.writeMetaData((WebResponse) 
originalResponse);
}

// Transform the data
CharSequence output = transform(component, 
tempResponse.getText());
originalResponse.write(output);
}
catch (Exception ex)
{
throw new WicketRuntimeException("Error while transforming the 
output of component: " +
component, ex);
}
finally
{
// Restore the original response object
requestCycle.setResponse(originalResponse);
}
}
{noformat}

Because all transformers are executed in order at this stage, the FIRST 
executed transformer works on the content of the request of the LAST one which 
put requests into place. After applying its own transformation, it puts its own 
original request in place and the next transformer works on that and puts its 
own