You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tapestry.apache.org by hl...@apache.org on 2014/08/01 19:11:09 UTC
git commit: TAP5-1481: In production mode,
component event requests that reference an unknown component should
respond with a 404
Repository: tapestry-5
Updated Branches:
refs/heads/master 7345bfb29 -> d9b3813a0
TAP5-1481: In production mode, component event requests that reference an unknown component should respond with a 404
Project: http://git-wip-us.apache.org/repos/asf/tapestry-5/repo
Commit: http://git-wip-us.apache.org/repos/asf/tapestry-5/commit/d9b3813a
Tree: http://git-wip-us.apache.org/repos/asf/tapestry-5/tree/d9b3813a
Diff: http://git-wip-us.apache.org/repos/asf/tapestry-5/diff/d9b3813a
Branch: refs/heads/master
Commit: d9b3813a09c0d685b28b36192f578b01744af725
Parents: 7345bfb
Author: Howard M. Lewis Ship <hl...@apache.org>
Authored: Fri Aug 1 10:11:11 2014 -0700
Committer: Howard M. Lewis Ship <hl...@apache.org>
Committed: Fri Aug 1 10:11:11 2014 -0700
----------------------------------------------------------------------
.../tapestry5/internal/InternalConstants.java | 12 ++++
.../services/ComponentEventDispatcher.java | 11 +++-
.../ComponentEventRequestHandlerImpl.java | 2 -
.../internal/services/PageRenderDispatcher.java | 11 +++-
.../ProductionModeUnknownComponentFilter.java | 64 ++++++++++++++++++++
.../tapestry5/internal/structure/Page.java | 3 +-
.../tapestry5/modules/TapestryModule.java | 58 ++++++++++--------
tapestry-core/src/test/conf/testng.xml | 2 +-
.../integration/app5/ProductionModeTests.groovy | 23 +++++++
.../integration/app5/services/AppModule.groovy | 2 +-
.../services/ComponentEventDispatcherTest.java | 10 ++-
11 files changed, 162 insertions(+), 36 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/d9b3813a/tapestry-core/src/main/java/org/apache/tapestry5/internal/InternalConstants.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/InternalConstants.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/InternalConstants.java
index c069f11..7fa95e9 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/internal/InternalConstants.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/InternalConstants.java
@@ -186,4 +186,16 @@ public final class InternalConstants
* @since 5.4
*/
public static final String SUPPRESS_CORE_STYLESHEETS = "tapestry.suppress-core-stylesheets";
+
+ /**
+ * A bit of a hack that allows, in production mode, for a component event request to "unwind" when
+ * the component referenced in the URL does not exist. This is related to TAP5-1481. This situation
+ * can most likely occur when a web spider, such as Google, uses an old component event URI from
+ * a prior deployment, which no longer works in a new deployment, due to structural changes. Since
+ * changing the APIs that significantly is forbidden, a non-null value is added as an
+ * {@link org.apache.tapestry5.services.Request} attribute.
+ *
+ * @since 5.4
+ */
+ public static final String REFERENCED_COMPONENT_NOT_FOUND = "tapestry.referenced-component-not-found";
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/d9b3813a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentEventDispatcher.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentEventDispatcher.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentEventDispatcher.java
index ef16591..1d0bd5d 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentEventDispatcher.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentEventDispatcher.java
@@ -1,5 +1,3 @@
-// Copyright 2006, 2007, 2008, 2009 The Apache Software Foundation
-//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
@@ -14,6 +12,7 @@
package org.apache.tapestry5.internal.services;
+import org.apache.tapestry5.internal.InternalConstants;
import org.apache.tapestry5.services.*;
import java.io.IOException;
@@ -43,8 +42,16 @@ public class ComponentEventDispatcher implements Dispatcher
if (parameters == null) return false;
+ // Inside this pipeline, may find that the component id does not exist (this check only occurs in production
+ // mode) ...
+
componentRequestHandler.handleComponentEvent(parameters);
+ // ... in which case, this attribute is set.
+ if (request.getAttribute(InternalConstants.REFERENCED_COMPONENT_NOT_FOUND) != null) {
+ return false;
+ }
+
return true;
}
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/d9b3813a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentEventRequestHandlerImpl.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentEventRequestHandlerImpl.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentEventRequestHandlerImpl.java
index 9450722..e1247c7 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentEventRequestHandlerImpl.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentEventRequestHandlerImpl.java
@@ -1,5 +1,3 @@
-// Copyright 2006, 2007, 2008, 2009, 2010, 2011 The Apache Software Foundation
-//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/d9b3813a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PageRenderDispatcher.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PageRenderDispatcher.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PageRenderDispatcher.java
index 39da112..1fb7b3e 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PageRenderDispatcher.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PageRenderDispatcher.java
@@ -1,5 +1,3 @@
-// Copyright 2006, 2007, 2008, 2009 The Apache Software Foundation
-//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
@@ -14,6 +12,7 @@
package org.apache.tapestry5.internal.services;
+import org.apache.tapestry5.internal.InternalConstants;
import org.apache.tapestry5.services.*;
import java.io.IOException;
@@ -37,6 +36,14 @@ public class PageRenderDispatcher implements Dispatcher
public boolean dispatch(Request request, final Response response) throws IOException
{
+ // If a component event request arrives (in production)
+ // with an invalid component id, then we want it to be a 404
+ // See TAP5-1481
+
+ if (request.getAttribute(InternalConstants.REFERENCED_COMPONENT_NOT_FOUND) != null)
+ {
+ return false;
+ }
PageRenderRequestParameters parameters = linkEncoder.decodePageRenderRequest(request);
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/d9b3813a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ProductionModeUnknownComponentFilter.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ProductionModeUnknownComponentFilter.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ProductionModeUnknownComponentFilter.java
new file mode 100644
index 0000000..9f95796
--- /dev/null
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ProductionModeUnknownComponentFilter.java
@@ -0,0 +1,64 @@
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package org.apache.tapestry5.internal.services;
+
+import org.apache.tapestry5.internal.InternalConstants;
+import org.apache.tapestry5.internal.structure.Page;
+import org.apache.tapestry5.ioc.util.UnknownValueException;
+import org.apache.tapestry5.services.*;
+
+import java.io.IOException;
+
+/**
+ * A filter, used only in production mode, that does a "pre-flight check" that the indicated component
+ * actually exists. If it does not, then the handling of the component event is aborted and other
+ * hooks will ensure that request ultimately becomes a 404.
+ *
+ * @since 5.4
+ */
+public class ProductionModeUnknownComponentFilter implements ComponentRequestFilter
+{
+ private final Request request;
+
+ private final RequestPageCache cache;
+
+ public ProductionModeUnknownComponentFilter(Request request, RequestPageCache cache)
+ {
+ this.request = request;
+ this.cache = cache;
+ }
+
+ @Override
+ public void handleComponentEvent(ComponentEventRequestParameters parameters, ComponentRequestHandler handler) throws IOException
+ {
+ Page containerPage = cache.get(parameters.getContainingPageName());
+
+ try
+ {
+ containerPage.getComponentElementByNestedId(parameters.getNestedComponentId());
+
+ handler.handleComponentEvent(parameters);
+
+ } catch (UnknownValueException ex)
+ {
+ request.setAttribute(InternalConstants.REFERENCED_COMPONENT_NOT_FOUND, true);
+ }
+ }
+
+ @Override
+ public void handlePageRender(PageRenderRequestParameters parameters, ComponentRequestHandler handler) throws IOException
+ {
+ // Pass these through to the default handler.
+ handler.handlePageRender(parameters);
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/d9b3813a/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/Page.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/Page.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/Page.java
index 48d1d64..3099c72 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/Page.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/structure/Page.java
@@ -15,6 +15,7 @@ package org.apache.tapestry5.internal.structure;
import org.apache.tapestry5.ComponentResources;
import org.apache.tapestry5.beaneditor.NonVisual;
import org.apache.tapestry5.ioc.services.PerthreadManager;
+import org.apache.tapestry5.ioc.util.UnknownValueException;
import org.apache.tapestry5.runtime.Component;
import org.apache.tapestry5.runtime.PageLifecycleCallbackHub;
import org.apache.tapestry5.runtime.PageLifecycleListener;
@@ -170,7 +171,7 @@ public interface Page extends PageLifecycleCallbackHub
* string) returns the root
* element of the page.
*
- * @throws IllegalArgumentException
+ * @throws UnknownValueException
* if the nestedId does not correspond to a component
*/
ComponentPageElement getComponentElementByNestedId(String nestedId);
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/d9b3813a/tapestry-core/src/main/java/org/apache/tapestry5/modules/TapestryModule.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/modules/TapestryModule.java b/tapestry-core/src/main/java/org/apache/tapestry5/modules/TapestryModule.java
index 2d852a9..a90003f 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/modules/TapestryModule.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/modules/TapestryModule.java
@@ -97,7 +97,6 @@ import org.slf4j.Logger;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
-
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.math.BigDecimal;
@@ -1729,7 +1728,7 @@ public final class TapestryModule
@Symbol(SymbolConstants.PRODUCTION_MODE)
boolean productionMode,
-
+
@Symbol(SymbolConstants.INCLUDE_CORE_STACK)
final boolean includeCoreStack,
@@ -1812,8 +1811,9 @@ public final class TapestryModule
configuration.add("ClientBehaviorSupport", clientBehaviorSupport, "after:JavaScriptSupport");
configuration.add("Heartbeat", heartbeat);
configuration.add("ValidationDecorator", defaultValidationDecorator);
-
- if (includeCoreStack) {
+
+ if (includeCoreStack)
+ {
configuration.add("ImportCoreStack", importCoreStack);
}
@@ -2057,8 +2057,6 @@ public final class TapestryModule
configuration.add(SymbolConstants.MIN_GZIP_SIZE, 100);
- Random random = new Random(System.currentTimeMillis());
-
configuration.add(SymbolConstants.APPLICATION_VERSION, "0.0.1");
configuration.add(SymbolConstants.OMIT_GENERATOR_META, false);
@@ -2116,25 +2114,25 @@ public final class TapestryModule
// TAP5-2070 keep the old behavior, defaults to false
configuration.add(MetaDataConstants.UNKNOWN_ACTIVATION_CONTEXT_CHECK, false);
-
+
// TAP5-2197
configuration.add(SymbolConstants.INCLUDE_CORE_STACK, true);
-
+
// TAP5-2182
configuration.add(SymbolConstants.FORM_GROUP_WRAPPER_CSS_CLASS, "form-group");
configuration.add(SymbolConstants.FORM_GROUP_LABEL_CSS_CLASS, "control-label");
configuration.add(SymbolConstants.FORM_GROUP_FORM_FIELD_WRAPPER_ELEMENT_NAME, "");
configuration.add(SymbolConstants.FORM_GROUP_FORM_FIELD_WRAPPER_ELEMENT_CSS_CLASS, "");
configuration.add(SymbolConstants.FORM_FIELD_CSS_CLASS, "form-control");
-
+
// TAP5-1998
configuration.add(SymbolConstants.LENIENT_DATE_FORMAT, false);
-
+
// TAP5-2187
configuration.add(SymbolConstants.STRICT_CSS_URL_REWRITING, false);
configuration.add(SymbolConstants.EXCEPTION_REPORTS_DIR, "build/exceptions");
-
+
// TAP5-1815
configuration.add(SymbolConstants.ENABLE_HTML5_SUPPORT, false);
@@ -2442,6 +2440,8 @@ public final class TapestryModule
* <dl>
* <dt>OperationTracker</dt>
* <dd>Tracks general information about the request using {@link OperationTracker}</dd>
+ * <dt>UnknownComponentFilter (production mode only)</dt>
+ * <dd>{@link org.apache.tapestry5.internal.services.ProductionModeUnknownComponentFilter} - Detects request with unknown component and aborts handling to ultimately deliver a 404 response</dd>
* <dt>InitializeActivePageName
* <dd>{@link InitializeActivePageName}
* <dt>DeferredResponseRenderer</dt>
@@ -2450,9 +2450,15 @@ public final class TapestryModule
*
* @since 5.2.0
*/
- public void contributeComponentRequestHandler(OrderedConfiguration<ComponentRequestFilter> configuration)
+ public void contributeComponentRequestHandler(OrderedConfiguration<ComponentRequestFilter> configuration, @Symbol(SymbolConstants.PRODUCTION_MODE) boolean productionMode)
{
configuration.addInstance("OperationTracker", RequestOperationTracker.class);
+
+ if (productionMode)
+ {
+ configuration.addInstance("UnknownComponentFilter", ProductionModeUnknownComponentFilter.class);
+ }
+
configuration.addInstance("InitializeActivePageName", InitializeActivePageName.class);
configuration.addInstance("DeferredResponseRenderer", DeferredResponseRenderer.class);
}
@@ -2670,13 +2676,15 @@ public final class TapestryModule
{
return strategyBuilder.build(ValueLabelProvider.class, configuration);
}
-
+
@Advise(serviceInterface = ComponentInstantiatorSource.class)
- public static void componentReplacer(MethodAdviceReceiver methodAdviceReceiver,
- final ComponentOverride componentReplacer) throws NoSuchMethodException, SecurityException {
-
- if (componentReplacer.getReplacements().size() > 0) {
-
+ public static void componentReplacer(MethodAdviceReceiver methodAdviceReceiver,
+ final ComponentOverride componentReplacer) throws NoSuchMethodException, SecurityException
+ {
+
+ if (componentReplacer.getReplacements().size() > 0)
+ {
+
MethodAdvice advice = new MethodAdvice()
{
@Override
@@ -2684,30 +2692,30 @@ public final class TapestryModule
{
String className = (String) invocation.getParameter(0);
final Class<?> replacement = componentReplacer.getReplacement(className);
- if (replacement != null)
+ if (replacement != null)
{
invocation.setParameter(0, replacement.getName());
}
invocation.proceed();
}
};
-
+
methodAdviceReceiver.adviseMethod(
ComponentInstantiatorSource.class.getMethod("getInstantiator", String.class), advice);
-
+
}
}
-
+
public static ComponentLibraryInfoSource buildComponentLibraryInfoSource(List<ComponentLibraryInfoSource> configuration,
- ChainBuilder chainBuilder)
+ ChainBuilder chainBuilder)
{
return chainBuilder.build(ComponentLibraryInfoSource.class, configuration);
}
-
+
@Contribute(ComponentLibraryInfoSource.class)
public static void addMavenComponentLibraryInfoSource(OrderedConfiguration<ComponentLibraryInfoSource> configuration)
{
configuration.addInstance("Maven", MavenComponentLibraryInfoSource.class);
}
-
+
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/d9b3813a/tapestry-core/src/test/conf/testng.xml
----------------------------------------------------------------------
diff --git a/tapestry-core/src/test/conf/testng.xml b/tapestry-core/src/test/conf/testng.xml
index 9e8921a..6a6acac 100644
--- a/tapestry-core/src/test/conf/testng.xml
+++ b/tapestry-core/src/test/conf/testng.xml
@@ -78,7 +78,7 @@
</packages>
</test>
- <test name="App Skinning Tests" enabled="true">
+ <test name="App Skinning and Misc. Tests" enabled="true">
<packages>
<package name="org.apache.tapestry5.integration.app5"/>
</packages>
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/d9b3813a/tapestry-core/src/test/groovy/org/apache/tapestry5/integration/app5/ProductionModeTests.groovy
----------------------------------------------------------------------
diff --git a/tapestry-core/src/test/groovy/org/apache/tapestry5/integration/app5/ProductionModeTests.groovy b/tapestry-core/src/test/groovy/org/apache/tapestry5/integration/app5/ProductionModeTests.groovy
new file mode 100644
index 0000000..265ac0b
--- /dev/null
+++ b/tapestry-core/src/test/groovy/org/apache/tapestry5/integration/app5/ProductionModeTests.groovy
@@ -0,0 +1,23 @@
+package org.apache.tapestry5.integration.app5
+
+import org.apache.tapestry5.integration.TapestryCoreTestCase
+import org.apache.tapestry5.test.TapestryTestConfiguration
+import org.testng.annotations.Test
+
+
+@TapestryTestConfiguration(webAppFolder = "src/test/app5")
+class ProductionModeTests extends TapestryCoreTestCase {
+
+ @Test
+ void invalid_component_id_is_404()
+ {
+ openBaseURL()
+
+ assertTitle "Default Layout"
+
+ def invalid = new URL("${baseURL}index.missing")
+
+ assertEquals 404, invalid.openConnection().responseCode
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/d9b3813a/tapestry-core/src/test/groovy/org/apache/tapestry5/integration/app5/services/AppModule.groovy
----------------------------------------------------------------------
diff --git a/tapestry-core/src/test/groovy/org/apache/tapestry5/integration/app5/services/AppModule.groovy b/tapestry-core/src/test/groovy/org/apache/tapestry5/integration/app5/services/AppModule.groovy
index 49f784c..04c413a 100644
--- a/tapestry-core/src/test/groovy/org/apache/tapestry5/integration/app5/services/AppModule.groovy
+++ b/tapestry-core/src/test/groovy/org/apache/tapestry5/integration/app5/services/AppModule.groovy
@@ -31,7 +31,7 @@ import org.apache.tapestry5.services.pageload.ComponentResourceSelector
class AppModule {
void contributeApplicationDefaults(MappedConfiguration conf) {
- conf.add(SymbolConstants.PRODUCTION_MODE, false)
+ conf.add(SymbolConstants.PRODUCTION_MODE, true)
conf.add(SymbolConstants.SUPPORTED_LOCALES, "en,fr")
// Override to test TAP5-2361
conf.add(SymbolConstants.BOOTSTRAP_ROOT, "context:bootstrap")
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/d9b3813a/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/ComponentEventDispatcherTest.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/ComponentEventDispatcherTest.java b/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/ComponentEventDispatcherTest.java
index 416b588..b3f17a1 100644
--- a/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/ComponentEventDispatcherTest.java
+++ b/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/ComponentEventDispatcherTest.java
@@ -1,5 +1,3 @@
-// Copyright 2007, 2008, 2009, 2011, 2012 The Apache Software Foundation
-//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
@@ -162,6 +160,8 @@ public class ComponentEventDispatcherTest extends InternalBaseTestCase
train_getParameter(request, InternalConstants.CONTAINER_PAGE_NAME, null);
+ expect(request.getAttribute(InternalConstants.REFERENCED_COMPONENT_NOT_FOUND)).andStubReturn(null);
+
train_for_request_locale(request, ls);
handler.handleComponentEvent(expectedParameters);
@@ -203,6 +203,8 @@ public class ComponentEventDispatcherTest extends InternalBaseTestCase
train_getParameter(request, InternalConstants.CONTAINER_PAGE_NAME, "mypage");
+ expect(request.getAttribute(InternalConstants.REFERENCED_COMPONENT_NOT_FOUND)).andStubReturn(null);
+
train_canonicalizePageName(resolver, "mypage", "mypage");
train_for_request_locale(request, ls);
@@ -271,6 +273,8 @@ public class ComponentEventDispatcherTest extends InternalBaseTestCase
train_getParameter(request, InternalConstants.CONTAINER_PAGE_NAME, null);
+ expect(request.getAttribute(InternalConstants.REFERENCED_COMPONENT_NOT_FOUND)).andStubReturn(null);
+
handler.handleComponentEvent(expectedParameters);
train_for_request_locale(request, localizationSetter);
@@ -326,6 +330,8 @@ public class ComponentEventDispatcherTest extends InternalBaseTestCase
train_getParameter(request, InternalConstants.CONTAINER_PAGE_NAME, null);
+ expect(request.getAttribute(InternalConstants.REFERENCED_COMPONENT_NOT_FOUND)).andStubReturn(null);
+
train_for_request_locale(request, localizationSetter);
handler.handleComponentEvent(expectedParameters);