Sounds very interesting and I'm +1 in general for the idea.

Some remarks:

* is it possible to decide that you don't want to clone some property
that has been declared as cloneable in the parent Context ? For
example in your isolated code you have a well know property that could
have been set in the parent context by any extension and which is
completely different from yours
* it does not seems to be possible to have a use case where you make a
property read-during for some time and then back to normal. Can you
make a property in a new EContext both inherit the value of it's
parent context and make it readonly even if the parent one is not ?

On Wed, Oct 17, 2012 at 9:20 AM, Vincent Massol <[email protected]> wrote:
>
> On Oct 16, 2012, at 3:08 PM, Andreas Jonsson <[email protected]> wrote:
>
>> Hi,
>>
>> 2012-10-16 11:03, Vincent Massol skrev:
>>> Hi Andreas,
>>>
>>> It would be great if you could explain your real use case and the reason 
>>> you wish to introduce this (I guess you have a use case where you need this 
>>> :)).
>>
>> I want to put authorization information in the execution context, and I
>> want to trust that this information is carried over to any new execution
>> context that is activated in the scope of the current request.
>
> That's always true, except where there are bugs (i.e. code that doesn't clone 
> the context but create a new one when it shouldn't) but that would be the 
> same even with your proposal.
>
>>  It is
>> also great if the object that holds the information cannot be replaced.
>> So, if you look at the code you will see that I have implemented a
>> rather aggressive enforcment of the combination of the attributes
>> read-only and inherited.
>
> Ok I'll need to read your code… :)
>
>> But also, the need for the inherited property already exists for
>> managing the properties "xwikicontext" and "velocityContext".  Just look
>> at the TODO and FIXME in DefaultExecutionContextManager in the master
>> branch.
>
> I wrote that code and those TODO/FIXME :)
>
> There's only one issue and you'll still have it: it's about putting objects 
> that can be cloned in the EC (that includes the velocitycontext and 
> xwikicontext).
>
>> But the general idea is just to be able to associate any kind of
>> metadata with each property.  It can be compared to how interpreted
>> languages handle variables.  Take for instance bash, where you can just
>> set a variable to a value, wich implicitly declares the variable.  But
>> you can also explicitly declare a variable, and in the declaration you
>> can provide flags that sets various attributes of the variable.  (e.g,
>> declare -r variable='readonly value'.)
>
> I'd be fine if it solved a problem but so far I fail to see how your solution 
> will solve the real issue we have now which is that the elements put in the 
> EC are not cloneable...
>
>>> See below.
>>>
>>> On Oct 12, 2012, at 9:27 AM, Andreas Jonsson <[email protected]> wrote:
>>>
>>>> Hi everyone,
>>>>
>>>> I would like to propose to introduce a possibility to associate
>>>> properties in the execution context with metadata by declaring them.  We
>>>> introduce the class 'ExecutionContextProperty' that will store the
>>>> metadata attributes, in addition to the actual property value.
>>>>
>>>> /**
>>>>  * Declare a property in the execution context.
>>>>  *
>>>>  * @param key The key that names the property
>>>>  * @param property The property to declare.
>>>>  */
>>>> public void declareProperty(String key, ExecutionContextProperty property)
>>> Does this mean the current ExecutionContext.setProperty() method would be 
>>> deprecated/removed?
>>>
>>> Why not use instead: setProperty(String key, ECP property)?
>>
>> Setting and declaring a property are completely different concepts.  In
>> a purely declarative model, properties would have to be declared before
>> being set.  But what I'm proposing is more in line with what bash does
>> with variables.  Setting a value on an undefined property will
>> implicitly declare it with default values for all attributes.  You can
>> also provide an initial value when declaring the property (which of
>> course is required for read-only properties).
>
> I still think a single semantic with setProperty is simpler to understand for 
> the user. He can either pass an untyped value or a type one.
>
> BTW what would the default property type? Cloned?
>
>>>> The metadata governs how the property should be treated when managing
>>>> the execution contexts.  For instance, these attributes could be supported:
>>>>
>>>> * Read-only  - The value may not be updated within the the execution
>>>> context.
>>> How do you ensure this? So getProperty() would continue to return the value 
>>> and not an ECP instance right?
>>
>> Yes, getProperty returns the value of the property.  I have not added
>> any method to obtain the declared ECP instance as I don't see any need
>> for it right now.
>>
>> Of course, it is only the reference to the value that is guaranteed to
>> be read-only by the execution context.  Depending on the application, it
>> may be desirable to make the object immutable, but that is not up to the
>> execution context to enforce.
>>>
>>> So when the user calls declareProperty() with the same key as an existing 
>>> key it would be refused if it's been declared Readonly?
>>
>> A property may only be declared once in an execution context, so it will
>> be refused if the property is already declared.  It doesn't matter if it
>> was an explicit or implicit declaration.  Attempting to declare an
>> already existing property is an indication that something is wrong, so
>> raising an exception seems appropriate.
>
> I don't understand this. You mean that we don't have a single use case where 
> we wish to update a property put in the EC? Like for example a counter that 
> we want to increment… IMO there's a valid use case in modifying an existing 
> property in the EC.

You don't declare a new property in the case of a counter to use setProperty.

>
>> If the property is read-only, then also setProperty will refuse to
>> replace the value.
>
> That one makes sense.
>
>>> Now imagine that I pass an ECP instance with a value of List. How do you 
>>> prevent some from doing: getProperty("mylistkey").add(somenewelement)?
>>>
>>>> * Inherited  - The property will be inherited from the current context
>>>> when replacing the execution context within the scope of a request.
>>> I don't understand this one, we create a new Execution Context for each 
>>> Request.
>>
>> No, you are mistaken.  We allow the creation and activation of several
>> execution contexts per request.  That's why we have the kludges in
>> DefaultExecutionContextManager for copying and cloning "xwikicontext"
>> and "velocityContext".
>
> I'm pretty sure I'm right. We create a new EC for each Request and then there 
> are parts of the code that require a clean context and for that they clean 
> the current EC, push it and then pop it.
>
>>>> * Clone      - Also clone the value when the execution context is cloned.
>>> What are the cases when we don't want to clone a property? I don't see any, 
>>> for me we always want to clone them and in practice we would instead need 
>>> to change our current signature to:
>>>
>>> setProperty(String key, Cloneable value)
>>
>> I do not want to clone my authorization data.  It wouldn't hurt cloning
>> it, but it would serve no purpose.  But I can also imagine that some
>> applications might want to put objects that are expensive to clone in
>> the execution context.
>
> Ah ok i think I understand what you mean now. You want to create a 
> relationship between EC instances in the EC stack so that when reading a 
> property value from the current EC, if the property is inherited it's taken 
> from the next EC in the stack…
>
> So basically you wish to remove the need for cloning and replace it with 
> inheritance. I get it now! :)
>
> It's interesting since it could make creating a new EC faster… I now 
> understand the need for readonly. It's a bit dangerous though since it means 
> there's no way of ensuring a clean EC and there's always the risk that you'd 
> modify a value located in the previous EC in the stack. Unless we don't allow 
> this, which would make sense (that's probably what you're doing I guess… 
> :))...
>
>>>> * Type       - The class of the value, for typechecking when replacing
>>>> the value.
>>> Can you explain more? Does it mean you wish that getProperty() returns a 
>>> typed value? We can already do this by using generics.
>>
>> No, it just means that we can perform run-time type checking when
>> setting the value of a declared property.  It would catch some errors
>> earlier, but not as early as compile time.
>>
>>>> * Non-null   - The value may not be null
>>>>
>>>> So, the arguments for this proposal are at least two:
>>>>
>>>> 1. Catch errors early and simplify debugging.
>>> Can you explain more this point, I don't see the benefit over what we can 
>>> already do.
>>
>> You can let the execution context provide some basic validation when
>> setting it.  If you mark a value read-only, you will not need to worry
>> about if any component suddenly replaces or remove it in the middle of
>> the request.
>>
>>>> 2. Convenience of having properties automatically maintained across
>>>> execution contexts within the same request cycle.
>>> This is probably related to the inherit item which I don't understand.
>>
>> Yes it is. ;)
>>
>>>> What do you think?
>>> Honestly I don't see the need for this.
>>>
>>> What we lack IMO is proper Execution Context cloning and for this to happen 
>>> we need to ensure we only cloneable items in the EC. As for the other 
>>> "types" I don't really see a strong need but maybe I've misunderstood a few 
>>> things (hence my questions above).
>>>
>>>> I would like to implement and merge this ASAP.
>>> We need to be very careful because the EC is a key class and introducing 
>>> this means we're changing an important public API and we cannot go back 
>>> easily (except through some deprecation cycles). IMO, seen the importance 
>>> this should be a VOTE instead of a PROPOSAL.
>>
>> The proposal adds two methods and one class, while beeing backwards
>> compliant with current code.  To me it seems that we have plenty of time
>> to change our minds before releasing 4.3-rc1 if I were to merge this
>> with master right now.  Or is our policy that we have to commit to any
>> API that we have added in a milestone release?
>
> Well IMO it's much better to get an agreement before committing but you run 
> the high risk to be asked to remove it in hurry at the last moment before the 
> release and fix everything that's beed modified because of it + the 
> stabilization risk when we're getting close to the release due to the 
> rollback.
>
> We have a lazy commit rule but this rule means that any committer can ask for 
> a rollback at any time. I'd have personally asked for one because I think 
> this is a critical API and I would have liked to understand it before we put 
> it in.
>
> Now, I've just understood your proposal and for me the winning argument is 
> that your proposal makes it faster to create a new sub-EC for the same 
> request and since we create an insane number of EC in the course of a request 
> it can only be a good thing. Note: we need to check the place where we create 
> those EC and fix them since I believe creation of a new EC is not always 
> required. One such place for example is $doc.display() calls. I think each 
> one create a new EC.
>
> So while your proposal adds a lot of complexity it's also interesting. I'd 
> like to have other's opinion on this too.
>
> One thing that I'd like to see deprecated is the default setProperty() 
> without Typing information. IMO we need to explicitly control each property 
> with this proposal and not use a default. It becomes very important that each 
> property's type is controlled since it can lead to important bugs.
>
> Thanks
> -Vincent
>
>>
>> I will propose a vote for it later in any event.
>>
>>
>> Best Regards,
>>
>> /Andreas
>>
>>>
>>> We would really need some feedback from several devs before going on with 
>>> this IMO. ATM I'd like to understand it more before voting.
>>>
>>> Thanks
>>> -Vincent
>>>
>>> PS: Didn't get the time to read your implementation code yet
>>>
>>>> Best Regards,
>>>>
>>>> /Andreas
> _______________________________________________
> devs mailing list
> [email protected]
> http://lists.xwiki.org/mailman/listinfo/devs



-- 
Thomas Mortagne
_______________________________________________
devs mailing list
[email protected]
http://lists.xwiki.org/mailman/listinfo/devs

Reply via email to