On Aug 30, 2008, at 12:28 AM, Vincent Massol
wrote:
[snip]
> For
2) I'd like to propose:
>
> * Create an interface for Velocity APIs. Something like
> VelocityBridge
> (or VelocityAccess or VelocityApi or...). It would be empty.
> * Each component that want to be accessed from velocity will
> need to
> implement a component implementing VelocityBridge. It'll have a
> role-
> hint being the name under which it'll be access from Velocity.
> * Create a VelocityService class (component) which has a single
> get(String name) method and which uses the ComponentManager to
> look up
> components which implement VelocityBridge using the name as the
> role
> hint.
> * Put that VelocityService in the Velocity context under the name
> "services".
>
> In practice this means that users will be able to access all our
> components through the VelocityBridge implementations with a
> syntax
> like:
>
> $services.office.convert(...)
> $services.translation.translate(...)
> ...
>
> Note1: We would need to be careful that it would be forbidden for
> any
> java code to use a VelocityBridge. This is to ensure all code
> logic is
> put into components and not into the bridges. We should use the
> maven
> enforcer plugin to enforce this rule.
> Note2: This means we'll have 2 APIs to maintain: the velocity one
> (the
> bridges) + the "Java"' one (the main components). But I don't see
> any
> other way...
>
> WDYT?
Why we can't just proxy "java" api with secure invocation handlers
with
using annotation rights as proposed some times ago?
Yes that's a good
question. I'm not sure but suddenly it seemed to
me easier to implement this way (less magic).
However you're right that this forces to expose the full api in the
velocity bridge implementation class.
Anyway, I think it is easier to not use proxy for
some cases,
so +1.
But I think it should be possible to use only one "java" api for
some
services.
We should have only 1 mechanism so we need to decide.
The problem with annotation I guess is when there's a strong
impedance mismatch between the Java API and the velocity one. In
that case there's no method to attach the annotation too although
the class could be used in those cases...
The annotation mechanism will require to write some velocity
uberspectors to intercept the method calls and redirect to the
correct velocity method handler.
To be honest, I'm not sure which solution is best. We should
probably take an existing module and see what the velocity API would
be for it. We could take the rendering module one.
I'm not ready to do that just now but I'll try to do the exercise
next week.
Ok here's what I propose:
* A module can have one or VelocityBridge components
* A VelocityBridge component can override or create new methods
* A VelocityBridge is registered as a component with a role-hint of
the class being bridged
* A VelocityBridge has a getName() method. That's the name under
which
it'll be known in velocity (more below)
* A VelocityBridge has a getWrappedService() method which returns the
instance of the class being wrapped.
* There's a MethodSwapUberspector uberspector which has a high
priority and thus intercepts all calls.
* On init the MethodSwapUberspector looks for all VelocityBridge
components and stores them in a hashmap indexed on their names.
* When "services.<name>.<method>" is called from Velocity, the
MethodSwapUberspector gets called and it looks in its hashmap for a
bridge named <name>. If found it looks for the <method> method in
that
class (with the same signature). If found it calls it. If not found
it
tries to call the method directly by calling it on
getWrappedService().
Two questions :
* How do you do when you want a method from the wrapped service not be
callable from velocity ? override and throw a specific exception ?
* I guess the velocity bridge would still be the one responsible for
checking programming rights, right ? One would have do something like
@Programming
public void myMethod(){
getWrappedService.myMethod();
}
is this correct ?