You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tapestry.apache.org by hl...@apache.org on 2007/01/05 19:01:33 UTC
svn commit: r493107 - in /tapestry/tapestry5/tapestry-core/trunk/src:
main/java/org/apache/tapestry/internal/bindings/
main/resources/org/apache/tapestry/internal/bindings/ site/apt/
site/apt/guide/ test/java/org/apache/tapestry/internal/bindings/
Author: hlship
Date: Fri Jan 5 10:01:32 2007
New Revision: 493107
URL: http://svn.apache.org/viewvc?view=rev&rev=493107
Log:
Add support for arbitrary method invocation inside property expressions
Modified:
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/bindings/BindingsMessages.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/bindings/PropBindingFactory.java
tapestry/tapestry5/tapestry-core/trunk/src/main/resources/org/apache/tapestry/internal/bindings/BindingsStrings.properties
tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/parameters.apt
tapestry/tapestry5/tapestry-core/trunk/src/site/apt/index.apt
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/bindings/PropBindingFactoryTest.java
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/bindings/StringHolder.java
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/bindings/StringHolderImpl.java
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/bindings/TargetBean.java
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/bindings/BindingsMessages.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/bindings/BindingsMessages.java?view=diff&rev=493107&r1=493106&r2=493107
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/bindings/BindingsMessages.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/bindings/BindingsMessages.java Fri Jan 5 10:01:32 2007
@@ -1,4 +1,4 @@
-// Copyright 2006 The Apache Software Foundation
+// Copyright 2006, 2007 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.
@@ -37,22 +37,40 @@
return MESSAGES.format("binding-is-write-only", binding);
}
- static String noSuchProperty(Class targetClass, String propertyName, String propertyPath)
+ static String noSuchProperty(Class targetClass, String propertyName, String propertyExpression)
{
return MESSAGES.format(
"no-such-property",
targetClass.getName(),
propertyName,
- propertyPath);
+ propertyExpression);
}
- static String writeOnlyProperty(String propertyName, Class clazz, String propertyPath)
+ static String writeOnlyProperty(String propertyName, Class clazz, String propertyExpression)
{
- return MESSAGES.format("write-only-property", propertyName, clazz.getName(), propertyPath);
+ return MESSAGES.format(
+ "write-only-property",
+ propertyName,
+ clazz.getName(),
+ propertyExpression);
}
static String validateBindingForFieldsOnly(ComponentResources component)
{
return MESSAGES.format("validate-binding-for-fields-only", component.getCompleteId());
+ }
+
+ static String methodNotFound(String methodName, Class inClass, String propertyExpression)
+ {
+ return MESSAGES.format(
+ "method-not-found",
+ methodName,
+ inClass.getName(),
+ propertyExpression);
+ }
+
+ static String methodIsVoid(String methodName, Class inClass, String propertyExpression)
+ {
+ return MESSAGES.format("method-is-void", methodName, inClass.getName(), propertyExpression);
}
}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/bindings/PropBindingFactory.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/bindings/PropBindingFactory.java?view=diff&rev=493107&r1=493106&r2=493107
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/bindings/PropBindingFactory.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/bindings/PropBindingFactory.java Fri Jan 5 10:01:32 2007
@@ -1,4 +1,4 @@
-// Copyright 2006 The Apache Software Foundation
+// Copyright 2006, 2007 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.
@@ -39,9 +39,31 @@
* Binding factory for reading and updating JavaBean properties. Uses
* {@link org.apache.tapestry.ioc.services.PropertyAccess} to analyze the properties, and generates
* a binding class using the component {@link org.apache.tapestry.ioc.services.ClassFactory}.
+ * <p>
+ * The {@link Binding} object that's returned is from a runtime-genereated class. The property
+ * expression is turned into type-safe Java code.
+ * <p>
+ * The expression is a dotted sequence of <em>terms</em>. Each term is either a property name, or
+ * the name of a public method. In the latter case, the term includes open and close parenthesis
+ * (the method must take no parameters and throw no checked exceptions). A method name is treated as
+ * if it were a <em>read-only property</em>.
+ * <p>
+ * Example property expressions:
+ * <ul>
+ * <li>userName</li>
+ * <li>userData.name</li>
+ * <li>usreList.size()</li>
+ * </ul>
+ * <p>
+ * Everything works in terms of the property or methods <em>declared type</em>, not the
+ * <em>actual type</em>. This means that, for example, if a property is type Collection, you may
+ * <em>not</em> reference the listIterator() method, even if the actual value returned is of type
+ * List. This is only really bites you when a method's return type is Object.
*/
public class PropBindingFactory implements BindingFactory, InvalidationListener
{
+ private static final String PARENS = "()";
+
private final PropertyAccess _access;
private final ClassFactory _classFactory;
@@ -131,70 +153,132 @@
return result;
}
- private BindingConstructor createConstructor(String key, Class targetClass, String propertyPath)
+ private BindingConstructor createConstructor(String key, Class targetClass,
+ String propertyExpression)
{
- // Race condition: simulataneous calls to createConstructor() for the same targetClass/propertyName
- // combination may result in duplicate binding classes being created, which causes no great
- // harm.
+ // Race condition: simultaneous calls to createConstructor() for the same
+ // targetClass/propertyExpression combination may result in duplicate binding classes being
+ // created, which causes no great harm.
StringBuilder builder = new StringBuilder("_target");
Class step = targetClass;
- String[] terms = propertyPath.split("\\.");
+ String[] terms = propertyExpression.split("\\.");
for (int i = 0; i < terms.length - 1; i++)
{
- String name = terms[i];
-
- PropertyAdapter pa = _access.getAdapter(step).getPropertyAdapter(name);
-
- if (pa == null)
- throw new RuntimeException(BindingsMessages
- .noSuchProperty(step, name, propertyPath));
+ String term = terms[i];
- Method m = pa.getReadMethod();
-
- if (m == null)
- throw new RuntimeException(BindingsMessages.writeOnlyProperty(
- name,
- step,
- propertyPath));
+ boolean isMethodReference = term.endsWith(PARENS);
- // Extend the expression by invoking the read access method.
+ step = isMethodReference ? extendWithMethodTerm(step, term, propertyExpression, builder)
+ : extendWithPropertyTerm(step, term, propertyExpression, builder);
+ }
- builder.append(".");
- builder.append(m.getName());
- builder.append("()");
+ String terminal = terms[terms.length - 1];
- // The next property (in the path, or the terminal) that is evaluated is in terms of the
- // return type of this method.
+ Class bindingType = null;
+ Method readMethod = null;
+ Method writeMethod = null;
- step = pa.getType();
+ if (terminal.endsWith(PARENS))
+ {
+ readMethod = validateMethodName(step, terminal, propertyExpression);
+ bindingType = readMethod.getReturnType();
}
+ else
+ {
+ PropertyAdapter adapter = _access.getAdapter(step).getPropertyAdapter(terminal);
- String terminalName = terms[terms.length - 1];
-
- PropertyAdapter adapter = _access.getAdapter(step).getPropertyAdapter(terminalName);
+ if (adapter == null)
+ throw new RuntimeException(BindingsMessages.noSuchProperty(
+ step,
+ terminal,
+ propertyExpression));
- if (adapter == null)
- throw new RuntimeException(BindingsMessages.noSuchProperty(
- step,
- terminalName,
- propertyPath));
+ bindingType = adapter.getType();
+ readMethod = adapter.getReadMethod();
+ writeMethod = adapter.getWriteMethod();
+ }
Class bindingClass = createBindingClass(
targetClass,
builder.toString(),
- terminalName,
- adapter);
+ terminal,
+ bindingType,
+ readMethod,
+ writeMethod);
// The fabricated class is only going to have the one constructor. This is the easiest
// way to access it.
- BindingConstructor result = new BindingConstructor(adapter.getType(), bindingClass
- .getConstructors()[0]);
+ return new BindingConstructor(bindingType, bindingClass.getConstructors()[0]);
+ }
- return result;
+ private Class extendWithMethodTerm(Class inClass, String term, String propertyExpression,
+ StringBuilder builder)
+ {
+ Method method = validateMethodName(inClass, term, propertyExpression);
+
+ builder.append(".");
+ builder.append(term);
+
+ return method.getReturnType();
+
+ }
+
+ private Method validateMethodName(Class inClass, String term, String propertyExpression)
+ {
+ String methodName = term.substring(0, term.length() - PARENS.length());
+
+ try
+ {
+ // Find a public method that takes no parameters.
+
+ Method method = inClass.getMethod(methodName);
+
+ if (method.getReturnType().equals(void.class))
+ throw new RuntimeException(BindingsMessages.methodIsVoid(
+ term,
+ inClass,
+ propertyExpression));
+
+ return method;
+
+ }
+ catch (NoSuchMethodException ex)
+ {
+ throw new RuntimeException(BindingsMessages.methodNotFound(
+ term,
+ inClass,
+ propertyExpression), ex);
+ }
+ }
+
+ private Class extendWithPropertyTerm(Class inClass, String term, String propertyExpression,
+ StringBuilder builder)
+ {
+ PropertyAdapter pa = _access.getAdapter(inClass).getPropertyAdapter(term);
+
+ if (pa == null)
+ throw new RuntimeException(BindingsMessages.noSuchProperty(
+ inClass,
+ term,
+ propertyExpression));
+
+ Method m = pa.getReadMethod();
+
+ if (m == null)
+ throw new RuntimeException(BindingsMessages.writeOnlyProperty(
+ term,
+ inClass,
+ propertyExpression));
+
+ builder.append(".");
+ builder.append(m.getName());
+ builder.append(PARENS);
+
+ return pa.getType();
}
/**
@@ -205,12 +289,10 @@
* _target instance variable
* @param propertyName
* the name of the terminal property
- * @param adapter
- * property adapter for the terminal property
* @return Class that implements Binding
*/
private Class createBindingClass(Class targetClass, String pathExpression, String propertyName,
- PropertyAdapter adapter)
+ Class propertyType, Method readMethod, Method writeMethod)
{
String name = ClassFabUtils.generateClassName("PropBinding");
@@ -224,18 +306,16 @@
null,
"{ super($2, $3, $4); _target = $1; }");
- if (adapter.isRead())
+ if (readMethod != null)
{
- String body = String.format("return ($w) %s.%s();", pathExpression, adapter
- .getReadMethod().getName());
+ String body = String.format("return ($w) %s.%s();", pathExpression, readMethod
+ .getName());
classFab.addMethod(Modifier.PUBLIC, GET_SIGNATURE, body);
}
- if (adapter.isUpdate())
+ if (writeMethod != null)
{
- Class propertyType = adapter.getType();
-
BodyBuilder builder = new BodyBuilder();
builder.begin();
@@ -255,7 +335,7 @@
else
builder.addln("(%s) $1;", propertyTypeName);
- builder.addln("%s.%s(value);", pathExpression, adapter.getWriteMethod().getName());
+ builder.addln("%s.%s(value);", pathExpression, writeMethod.getName());
builder.end();
classFab.addMethod(Modifier.PUBLIC, SET_SIGNATURE, builder.toString());
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/resources/org/apache/tapestry/internal/bindings/BindingsStrings.properties
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/resources/org/apache/tapestry/internal/bindings/BindingsStrings.properties?view=diff&rev=493107&r1=493106&r2=493107
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/resources/org/apache/tapestry/internal/bindings/BindingsStrings.properties (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/resources/org/apache/tapestry/internal/bindings/BindingsStrings.properties Fri Jan 5 10:01:32 2007
@@ -1,4 +1,4 @@
-# Copyright 2006 The Apache Software Foundation
+# Copyright 2006, 2007 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.
@@ -14,6 +14,8 @@
binding-is-read-only=Binding %s is read-only.
binding-is-write-only=Binding %s is write-only.
-no-such-property=Class %s does not contain a property named '%s' (within property path '%s').
-write-only-property=Property '%s' of class %s (within property path '%s') is not readable (it has no read accessor method).
+no-such-property=Class %s does not contain a property named '%s' (within property expression '%s').
+write-only-property=Property '%s' of class %s (within property expression '%s') is not readable (it has no read accessor method).
validate-binding-for-fields-only=Component '%s' is not a field (it does not implement the Field interface) and may not be used with the validate: binding prefix.
+method-not-found=No public method '%s' in class %s (within property expression '%s').
+method-is-void=Method '%s' returns void (in class %s, within property expression '%s').
\ No newline at end of file
Modified: tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/parameters.apt
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/parameters.apt?view=diff&rev=493107&r1=493106&r2=493107
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/parameters.apt (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/parameters.apt Fri Jan 5 10:01:32 2007
@@ -138,12 +138,24 @@
The "prop:" prefix indicates a property binding.
- Property bindings are normally either simple names of properties ("prop:userName")
- or paths to properties ("prop:user.address.city").
-
+ The expression for a property binding is a dotted sequence of property names. Simple
+ property expressions are just the name of a property, "prop:userName". Complex property
+ expression may do a little navigation before getting to the property to read and/or update:
+ "prop:userData.name".
+
+ In addition to property names, you may also invoke arbitrary methods. The methods must be public,
+ return a non-void value, throw no checked exceptions, and take no parameters. To differentiate
+ a method name from a property name, you simply append the open and close parenthesis. Thus
+ the prior examples could be rewritten as "prop:getUserName()" and "prop:getUserData().getName()".
+ Note that when the last term in the expression is a method name, the binding will be read-only,
+ rather than read/write.
+
+ This feature is most useful for accessing a couple of propertys of standard collection classes
+ that aren't named as proper properties, such as Collection.size(), or Map.keySet().
+
In addition, a few special cases are also supported.
In most cases, these special values save you the trouble of adding a "literal:" prefix to
- the value.
+ the value. These special cases are <alternatives> to property expressions.
* "true" and "false" will be converted to booleans.
Modified: tapestry/tapestry5/tapestry-core/trunk/src/site/apt/index.apt
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/site/apt/index.apt?view=diff&rev=493107&r1=493106&r2=493107
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/site/apt/index.apt (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/site/apt/index.apt Fri Jan 5 10:01:32 2007
@@ -36,6 +36,8 @@
Progress on Tapestry 5 is really taking off. This space lists some cool new features that have been added
recently.
+ * Property expressions may now reference public methods (with no parameters) in addition to traditional property names.
+
* Page templates are now allowed to be stored in the web application root, as well as on the classpath.
* Invisible instrumentation, hiding Tapestry components inside ordinary HTML elements (a favorite feature of Tapestry 4), has been added to Tapestry 5.
Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/bindings/PropBindingFactoryTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/bindings/PropBindingFactoryTest.java?view=diff&rev=493107&r1=493106&r2=493107
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/bindings/PropBindingFactoryTest.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/bindings/PropBindingFactoryTest.java Fri Jan 5 10:01:32 2007
@@ -1,4 +1,4 @@
-// Copyright 2006 The Apache Software Foundation
+// Copyright 2006, 2007 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.
@@ -114,7 +114,184 @@
"PropBinding[test binding foo.Bar:baz(stringHolder.value)]");
verify();
+ }
+
+ /** The "preamble" are the non-terminal property or method names. */
+ @Test
+ public void property_path_with_explicit_method_in_preamble()
+ {
+ TargetBean bean = new TargetBean();
+ ComponentResources resources = newComponentResources(bean);
+ Location l = newLocation();
+
+ replay();
+
+ Binding binding = _factory.newBinding(
+ "test binding",
+ resources,
+ null,
+ "stringHolderMethod().value",
+ l);
+
+ assertSame(binding.getBindingType(), String.class);
+
+ bean.getStringHolder().setValue("first");
+
+ assertEquals(binding.get(), "first");
+
+ assertEquals(
+ binding.toString(),
+ "PropBinding[test binding foo.Bar:baz(stringHolderMethod().value)]");
+
+ verify();
+ }
+
+ @Test
+ public void method_call_as_terminal()
+ {
+ TargetBean bean = new TargetBean();
+ ComponentResources resources = newComponentResources(bean);
+ Location l = newLocation();
+
+ replay();
+
+ Binding binding = _factory.newBinding(
+ "test binding",
+ resources,
+ null,
+ "stringHolderMethod().stringValue()",
+ l);
+
+ assertSame(binding.getBindingType(), String.class);
+
+ bean.getStringHolder().setValue("first");
+
+ assertEquals(binding.get(), "first");
+
+ try
+ {
+ binding.set("read-only");
+ unreachable();
+ }
+ catch (TapestryException ex)
+ {
+ assertEquals(
+ ex.getMessage(),
+ "Binding PropBinding[test binding foo.Bar:baz(stringHolderMethod().stringValue())] is read-only.");
+ assertSame(ex.getLocation(), l);
+ }
+
+ verify();
+
+ }
+
+ @Test
+ public void method_not_found_in_preamble()
+ {
+ TargetBean bean = new TargetBean();
+ ComponentResources resources = newComponentResources();
+ Location l = newLocation();
+
+ train_getComponent(resources, bean);
+
+ replay();
+
+ try
+ {
+ _factory.newBinding("test binding", resources, null, "isThatRealBlood().value", l);
+ unreachable();
+ }
+ catch (RuntimeException ex)
+ {
+ assertEquals(
+ ex.getMessage(),
+ "No public method \'isThatRealBlood()\' in class org.apache.tapestry.internal.bindings.TargetBean (within property expression \'isThatRealBlood().value\').");
+ }
+
+ verify();
+ }
+
+ @Test
+ public void method_not_found_in_terminal()
+ {
+ TargetBean bean = new TargetBean();
+ ComponentResources resources = newComponentResources();
+ Location l = newLocation();
+ train_getComponent(resources, bean);
+
+ replay();
+
+ try
+ {
+ _factory.newBinding(
+ "test binding",
+ resources,
+ null,
+ "stringHolder.isThatRealBlood()",
+ l);
+ unreachable();
+ }
+ catch (RuntimeException ex)
+ {
+ assertEquals(
+ ex.getMessage(),
+ "No public method \'isThatRealBlood()\' in class org.apache.tapestry.internal.bindings.StringHolder (within property expression \'stringHolder.isThatRealBlood()\').");
+ }
+
+ verify();
+ }
+
+ @Test
+ public void void_method_in_preamble()
+ {
+ TargetBean bean = new TargetBean();
+ ComponentResources resources = newComponentResources();
+ Location l = newLocation();
+
+ train_getComponent(resources, bean);
+
+ replay();
+
+ try
+ {
+ _factory.newBinding("test binding", resources, null, "voidMethod().value", l);
+ unreachable();
+ }
+ catch (RuntimeException ex)
+ {
+ assertEquals(
+ ex.getMessage(),
+ "Method \'voidMethod()\' returns void (in class org.apache.tapestry.internal.bindings.TargetBean, within property expression \'voidMethod().value\').");
+ }
+
+ verify();
+ }
+
+ @Test
+ public void void_method_as_terminal()
+ {
+ TargetBean bean = new TargetBean();
+ ComponentResources resources = newComponentResources();
+ Location l = newLocation();
+
+ train_getComponent(resources, bean);
+
+ replay();
+
+ try
+ {
+ _factory.newBinding("test binding", resources, null, "stringHolder.voidMethod()", l);
+ unreachable();
+ }
+ catch (RuntimeException ex)
+ {
+ assertEquals(
+ ex.getMessage(),
+ "Method \'voidMethod()\' returns void (in class org.apache.tapestry.internal.bindings.StringHolder, within property expression \'stringHolder.voidMethod()\').");
+ }
+
+ verify();
}
@Test
Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/bindings/StringHolder.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/bindings/StringHolder.java?view=diff&rev=493107&r1=493106&r2=493107
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/bindings/StringHolder.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/bindings/StringHolder.java Fri Jan 5 10:01:32 2007
@@ -1,4 +1,4 @@
-// Copyright 2006 The Apache Software Foundation
+// Copyright 2006, 2007 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.
@@ -18,5 +18,9 @@
{
void setValue(String value);
- String getValue();
+ String getValue();
+
+ String stringValue();
+
+ void voidMethod();
}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/bindings/StringHolderImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/bindings/StringHolderImpl.java?view=diff&rev=493107&r1=493106&r2=493107
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/bindings/StringHolderImpl.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/bindings/StringHolderImpl.java Fri Jan 5 10:01:32 2007
@@ -1,4 +1,4 @@
-// Copyright 2006 The Apache Software Foundation
+// Copyright 2006, 2007 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.
@@ -26,5 +26,14 @@
public void setValue(String value)
{
_value = value;
+ }
+
+ public String stringValue()
+ {
+ return _value;
+ }
+
+ public void voidMethod()
+ {
}
}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/bindings/TargetBean.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/bindings/TargetBean.java?view=diff&rev=493107&r1=493106&r2=493107
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/bindings/TargetBean.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/bindings/TargetBean.java Fri Jan 5 10:01:32 2007
@@ -1,4 +1,4 @@
-// Copyright 2006 The Apache Software Foundation
+// Copyright 2006, 2007 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.
@@ -27,6 +27,16 @@
public StringHolder getStringHolder()
{
return _stringHolder;
+ }
+
+ public StringHolder stringHolderMethod()
+ {
+ return _stringHolder;
+ }
+
+ public void voidMethod()
+ {
+
}
public int getIntValue()