You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tapestry.apache.org by Barry Books <tr...@gmail.com> on 2013/03/26 12:20:05 UTC

Questions about making Parameters defaulted to Symbols writable (includes solution)

There have been several discussions on the user list about the failure
@BindParameter to override Parameters that have defaults set to
Symbols. The symbol bind prefix is readonly so attempting to override
the parameter value results in a read only exception. I've also run
into this issue and decided to try and fix it. After thinking about it
the fix seems easy enough and the following code works. The question
is why.

public class MySymbolBindingFactory implements BindingFactory {
	
	private final SymbolSource symbolSource;
	private final Logger logger;
	
	       public MySymbolBindingFactory(SymbolSource symbolSource, Logger logger)
	       {
	           this.symbolSource = symbolSource;
	           this.logger = logger;
	       }
	
	       public Binding newBinding(String description,
ComponentResources container,
	               ComponentResources component, String expression,
Location location)
	       {
	
	           String value = symbolSource.valueForSymbol(expression);
	           return new SymbolBinding(location, description, value);
	       }
	
	       public class SymbolBinding implements Binding {
	    	   private Object value;
	    	   	    	
	    	   public SymbolBinding(Location location, String description,
String value) {
	    		   this.value = value;
	    	   }

			@Override
			public <T extends Annotation> T getAnnotation(Class<T> arg0) {
				return null;
			}

			@Override
			public Object get() {
				return value;
			}

			@Override
			public Class getBindingType() {
				return value.getClass();
			}

			@Override
			public boolean isInvariant() {
				return false;
			}

			@Override
			public void set(Object value) {
				//just ignore this
			}
	    	
	       }
}

The original symbol binding throws an error in the set method. This
one just ignores it. I've done some limited testing and this appears
to work but the questions are why does it work, will it continuing to
work and what are the drawbacks.

>From what I can tell the actual value for the parameter is not stored
in the binding but in a per request map behind a proxy. When the
component is initialized by a request the value in the map is set to
the default (a symbol binding) if no value is provided. Using
@BindParamter attaches to the proxy and calling set in the mixin calls
set on the map and the symbol. Reading the parameter value results in
a get from the map so it does not matter what the symbol value is.

What if any are the drawbacks to this? One is the binding is no longer
invariant. I suppose this could have performance implications since
the value is no longer cacheable. I'm not sure that's really a problem
and certainly no worse that just removing the default. The second I'm
less sure about. Much of the magic behind Parameters is undocumented
and I'm guessing it's possible some change could break this.

I think if for some reason the actual value was stored in the binding
object it would be possible to use the request object to store the
value but at this point that seems like an unnecessary complication.

Any comments from someone that really understands this subject would
be appreciated.

Thanks
Barry

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tapestry.apache.org
For additional commands, e-mail: dev-help@tapestry.apache.org


Re: Questions about making Parameters defaulted to Symbols writable (includes solution)

Posted by Barry Books <tr...@gmail.com>.
I agree it seems like the limitation was not intended and your suggestion is best long term. Until then this part seemed the easiest to override. 
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tapestry.apache.org
For additional commands, e-mail: dev-help@tapestry.apache.org


Re: Questions about making Parameters defaulted to Symbols writable (includes solution)

Posted by Thiago H de Paula Figueiredo <th...@gmail.com>.
I'll post my opinion here without having given much thought, but here's it  
anyway: it seems to me that, as Tapestry implemented parameter bindings  
way before @BindParameter was created, it supposed that a parameter  
binding would never be changed from the one in the template or @Component  
annotation. Shouldn't Tapestry's component parameter handling code should  
be updated so it handles @BindParameter itself, without the need to change  
read-only binding implementations? For example, for me, changing or  
overriding the symbol binding is an ugly hack, so, if possible, the  
@BindParameter problem should be solved as its root, not in the symbol  
binding, which IMHO should remain invariant and read-only.

On Tue, 26 Mar 2013 08:20:05 -0300, Barry Books <tr...@gmail.com> wrote:

> There have been several discussions on the user list about the failure
> @BindParameter to override Parameters that have defaults set to
> Symbols. The symbol bind prefix is readonly so attempting to override
> the parameter value results in a read only exception. I've also run
> into this issue and decided to try and fix it. After thinking about it
> the fix seems easy enough and the following code works. The question
> is why.
>
> public class MySymbolBindingFactory implements BindingFactory {
> 	
> 	private final SymbolSource symbolSource;
> 	private final Logger logger;
> 	
> 	       public MySymbolBindingFactory(SymbolSource symbolSource, Logger  
> logger)
> 	       {
> 	           this.symbolSource = symbolSource;
> 	           this.logger = logger;
> 	       }
> 	
> 	       public Binding newBinding(String description,
> ComponentResources container,
> 	               ComponentResources component, String expression,
> Location location)
> 	       {
> 	
> 	           String value = symbolSource.valueForSymbol(expression);
> 	           return new SymbolBinding(location, description, value);
> 	       }
> 	
> 	       public class SymbolBinding implements Binding {
> 	    	   private Object value;
> 	    	   	    	
> 	    	   public SymbolBinding(Location location, String description,
> String value) {
> 	    		   this.value = value;
> 	    	   }
>
> 			@Override
> 			public <T extends Annotation> T getAnnotation(Class<T> arg0) {
> 				return null;
> 			}
>
> 			@Override
> 			public Object get() {
> 				return value;
> 			}
>
> 			@Override
> 			public Class getBindingType() {
> 				return value.getClass();
> 			}
>
> 			@Override
> 			public boolean isInvariant() {
> 				return false;
> 			}
>
> 			@Override
> 			public void set(Object value) {
> 				//just ignore this
> 			}
> 	    	
> 	       }
> }
>
> The original symbol binding throws an error in the set method. This
> one just ignores it. I've done some limited testing and this appears
> to work but the questions are why does it work, will it continuing to
> work and what are the drawbacks.
>
> From what I can tell the actual value for the parameter is not stored
> in the binding but in a per request map behind a proxy. When the
> component is initialized by a request the value in the map is set to
> the default (a symbol binding) if no value is provided. Using
> @BindParamter attaches to the proxy and calling set in the mixin calls
> set on the map and the symbol. Reading the parameter value results in
> a get from the map so it does not matter what the symbol value is.
>
> What if any are the drawbacks to this? One is the binding is no longer
> invariant. I suppose this could have performance implications since
> the value is no longer cacheable. I'm not sure that's really a problem
> and certainly no worse that just removing the default. The second I'm
> less sure about. Much of the magic behind Parameters is undocumented
> and I'm guessing it's possible some change could break this.
>
> I think if for some reason the actual value was stored in the binding
> object it would be possible to use the request object to store the
> value but at this point that seems like an unnecessary complication.
>
> Any comments from someone that really understands this subject would
> be appreciated.
>
> Thanks
> Barry
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@tapestry.apache.org
> For additional commands, e-mail: dev-help@tapestry.apache.org
>


-- 
Thiago H. de Paula Figueiredo

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tapestry.apache.org
For additional commands, e-mail: dev-help@tapestry.apache.org