You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@velocity.apache.org by Bill Burton <bi...@progress.com> on 2001/05/14 23:08:54 UTC

Introspection problems

Hello,

I'm just starting to look at Velocity.  Wrote a servlet that extends
VelocityServlet.  However, I'm running into some problems where properties
are not being recognized and evaluated.  For instance:

  pagename parameter = ${req.Parameter.pagename}      <-- fails
                  or   $req.parameter.pagename        <-- fails
                  or   $req.getParameter("pagename")  <-- works in 1.0.1
but fails in 5-14 nighly
  req.getServlet() = $req.servlet or $req.Servlet or $req.getServlet() <--
all fail

The log shows:
Mon May 14 14:43:59 EDT 2001   [warn]
org.apache.velocity.runtime.exception.ReferenceException: reference :
template = ICS.Read [line 17,column 24] : ${req.Parameter.pagename} is not
a valid reference.
Mon May 14 14:43:59 EDT 2001   [warn]
org.apache.velocity.runtime.exception.ReferenceException: reference :
template = ICS.Read [line 18,column 24] : $req.parameter.pagename is not a
valid reference.
Mon May 14 14:43:59 EDT 2001   [warn]
org.apache.velocity.runtime.exception.ReferenceException: reference :
template = ICS.Read [line 20,column 21] : $req.servlet is not a valid
reference.
Mon May 14 14:43:59 EDT 2001   [warn]
org.apache.velocity.runtime.exception.ReferenceException: reference :
template = ICS.Read [line 20,column 37] : $req.Servlet is not a valid
reference.
Mon May 14 14:43:59 EDT 2001   [warn]
org.apache.velocity.runtime.exception.ReferenceException: reference :
template = ICS.Read [line 20,column 53] : $req.getServlet() is not a valid
reference.

Is there any debugging or logging that can be turned on to help debug
this?

In addition, I'm adding a couple of my own objects to the Velocity
context.  On one of them introspection works on methods only, not
properties.  On the other object, introspection doesn't work at all.

I should also note that I'm calling Velocity.evaluate() in an overridden
mergeTemplate method.  This is necessary because the template is being
read out of a database through a high level API.  I can't create a
resource to read the database because this high level API only exists in
the context of a request.

Environment:
  Velocity 1.0.1 (tried 05-14 nightly build too)
  Using default properties

Thanks for any assistance,
-Bill

Re: Introspection problems

Posted by "Geir Magnusson Jr." <ge...@optonline.net>.
Bill Burton wrote:
> "Geir Magnusson Jr." wrote:
> >
> >
> > Hm.  There is another way :  Note that with 1.1 (yes, take yesterdays or
> > tonights nightly - forget the 5/14 :) there is another handleRequest()
> > method
> >
> >   handleRequest( HttpServletRequest, HttpServletREsponse, Context)
> 
> Okay.  This is much better.  I was about to write and complain about the
> lack of flexibility in the 1.0.1 VelocityServlet.  It looks like I can now
> use it without resorting to hacks.

If you ever find yourself resorting to hacks, shout.  Either we screwed
up and did something goofy, or you are off in the trees.  :)

Either way, someone will learn something.

geir

-- 
Geir Magnusson Jr.                           geirm@optonline.net
System and Software Consulting
Developing for the web?  See http://jakarta.apache.org/velocity/
"still climbing up to the shoulders..."

Re: Introspection problems

Posted by Bill Burton <bi...@progress.com>.
Hello,

"Geir Magnusson Jr." wrote:
> 
> The rules for class fields ('properties' isn't quite right...) is that
> we don't touch them.  Use the 'FieldMethodizer' which enables easy
> access.

Okay, that's good to know. In my case, I'm always using accessor methods.

> > I should also note that I'm calling Velocity.evaluate() in an overridden
> > mergeTemplate method.  This is necessary because the template is being
> > read out of a database through a high level API.  I can't create a
> > resource to read the database because this high level API only exists in
> > the context of a request.
> 
> Hm.  There is another way :  Note that with 1.1 (yes, take yesterdays or
> tonights nightly - forget the 5/14 :) there is another handleRequest()
> method
> 
>   handleRequest( HttpServletRequest, HttpServletREsponse, Context)

Okay.  This is much better.  I was about to write and complain about the
lack of flexibility in the 1.0.1 VelocityServlet.  It looks like I can now
use it without resorting to hacks.

> which allows you to handle the request any way you wish, and then return
> null instead of a template, indicating that you completely handled the
> request.  This seems to be a more straightforward approach than
> mergeTemplate.  Your choice, tho...
> 
> Again, sorry about the 5/14 nightly scew up.

No problem.  When I saw some of the tests fail, I wasn't expecting much
nor did I spend much time with it.  

Thanks for your feedback,
-Bill

Re: Introspection problems

Posted by "Geir Magnusson Jr." <ge...@optonline.net>.
Bill Burton wrote:
> 
> Hello,
> 
> I'm just starting to look at Velocity.  Wrote a servlet that extends
> VelocityServlet.  However, I'm running into some problems where properties
> are not being recognized and evaluated.  For instance:
> 
>   pagename parameter = ${req.Parameter.pagename}      <-- fails
>                   or   $req.parameter.pagename        <-- fails
>                   or   $req.getParameter("pagename")  <-- works in 1.0.1
> but fails in 5-14 nighly
>   req.getServlet() = $req.servlet or $req.Servlet or $req.getServlet() <--
> all fail

I screwed things up royally however, as jon noted, the first two won't
work either way.


> The log shows:
> Mon May 14 14:43:59 EDT 2001   [warn]
> org.apache.velocity.runtime.exception.ReferenceException: reference :
> template = ICS.Read [line 17,column 24] : ${req.Parameter.pagename} is not
> a valid reference.
> Mon May 14 14:43:59 EDT 2001   [warn]
> org.apache.velocity.runtime.exception.ReferenceException: reference :
> template = ICS.Read [line 18,column 24] : $req.parameter.pagename is not a
> valid reference.
> Mon May 14 14:43:59 EDT 2001   [warn]
> org.apache.velocity.runtime.exception.ReferenceException: reference :
> template = ICS.Read [line 20,column 21] : $req.servlet is not a valid
> reference.
> Mon May 14 14:43:59 EDT 2001   [warn]
> org.apache.velocity.runtime.exception.ReferenceException: reference :
> template = ICS.Read [line 20,column 37] : $req.Servlet is not a valid
> reference.
> Mon May 14 14:43:59 EDT 2001   [warn]
> org.apache.velocity.runtime.exception.ReferenceException: reference :
> template = ICS.Read [line 20,column 53] : $req.getServlet() is not a valid
> reference.
> 
> Is there any debugging or logging that can be turned on to help debug
> this?
> 
> In addition, I'm adding a couple of my own objects to the Velocity
> context.  On one of them introspection works on methods only, not
> properties.  On the other object, introspection doesn't work at all.

Yah, that would be me on the second one.  I apologize.

The rules for class fields ('properties' isn't quite right...) is that
we don't touch them.  Use the 'FieldMethodizer' which enables easy
access.
 
> I should also note that I'm calling Velocity.evaluate() in an overridden
> mergeTemplate method.  This is necessary because the template is being
> read out of a database through a high level API.  I can't create a
> resource to read the database because this high level API only exists in
> the context of a request.

Hm.  There is another way :  Note that with 1.1 (yes, take yesterdays or
tonights nightly - forget the 5/14 :) there is another handleRequest()
method

  handleRequest( HttpServletRequest, HttpServletREsponse, Context)

which allows you to handle the request any way you wish, and then return
null instead of a template, indicating that you completely handled the
request.  This seems to be a more straightforward approach than
mergeTemplate.  Your choice, tho...

Again, sorry about the 5/14 nightly scew up.  

geir

-- 
Geir Magnusson Jr.                           geirm@optonline.net
System and Software Consulting
Developing for the web?  See http://jakarta.apache.org/velocity/
"still climbing up to the shoulders..."

Re: Introspection problems

Posted by "Geir Magnusson Jr." <ge...@optonline.net>.
bob mcwhirter wrote:
> 
> Just a quick question for clarification.
> 
> Does you object truly need to implement Map?  Or does having a
> method matching the signature
> 
>         public Object put(Object key, Object value)
> 
> suffice, since we're using introspection, and all.
> 
>         -bob
> 

You would have to implement Map for a #set( $foo.property = <value>),
because right now, the introspection is

  setProperty( value )

or
  setproperty( value )

or 

  put( property, value )   iff  Map


but it isn't a bad idea to accept a put( String, Object ) as well.

geir

-- 
Geir Magnusson Jr.                           geirm@optonline.net
System and Software Consulting
Developing for the web?  See http://jakarta.apache.org/velocity/
"still climbing up to the shoulders..."

Re: Introspection problems

Posted by bob mcwhirter <bo...@werken.com>.
Just a quick question for clarification.

Does you object truly need to implement Map?  Or does having a
method matching the signature

	public Object put(Object key, Object value)

suffice, since we're using introspection, and all.

	-bob

On Wed, 16 May 2001, Geir Magnusson Jr. wrote:

> Bill Burton wrote:
> > 
> > > > Then, I tried to set a value something like:
> > > >     #set($breakfast_omlet.cheeze = "swiss")
> > > > which failed with an error in the log:
> > > >     [error] ASTReference : cannot find cheeze as settable property or key
> > > > to Map in template
> > > >
> > > > So, I guess my Omlet object needs to implement a Map or, can I get away
> > > > with less?
> > >
> > > A Map would do it, as would a setCheeze(String) method.
> > 
> > Okay.  In this case cheeze is the key and swiss is the value.  I'm trying
> > to get
> > #set($breakfast_omlet.cheeze = "swiss")
> > to execute:
> > omletInstance.put("cheeze", "swiss") just like you can do with a HashMap.
> > 
> > I looked at what it might take to support a Map interface by having my
> > Omlet class extend AbstractMap but then I would have to implement entrySet
> > and keySet methods and so on.  It's just way beyond the scope (and time) I
> > can afford to solve such a simple problem.
> 
> Velocity doesn't care about the entrySet and keySet methods, so just
> stub them.  It will care about values() if you want to iterate over it
> in #foreach() - if you aren't going to iterate, stub that too.
> 
> > After poking around the Velocity source a bit, I found in the
> > runtime/parser/node/ASTReference class this comment and code:
> >             /*
> >              *  right now, we only support the Map interface
> >              */
> > 
> >             if (result instanceof Map)
> >             {
> >                 try
> >                 {
> >                     ((Map) result).put(identifier, value);
> >                 }
> >             ...
> > 
> > So, clearly, .put(key, value) only works if the underlying object
> > implements Map.  But the GetExecutor class supports a .get(key) method
> > implemented by any class which is immensely convenient.  It seems to me
> > doing the same thing for .put(key, value) would also be beneficial in a
> > similar manner.
> 
> That's a good observation...
>  
> > 
> > The third party API I'm dealing with has a very simple way of retrieving a
> > page from a database but the catch is the context of this API is always
> > established from that of the HTTPServletRequest/Response.  There is no way
> > it can be called from outside a request.  Since it's not possible to pass
> > the Velocity context through the Runtime.getTemplate method down to the
> > ResourceManager and ultimately to a custom ResourceLoader, I can't call
> > this API from there.
> 
> Well... [ disclaimer : off the top of my head half way through first cup
> of coffee], you could take advantage of the fact that all of Velocity's
> activities on your behalf happen on your thread, you could make a
> Singleton 'BlargCache', and place the request/response/whatever into it
> associated with your thread.  Then, your loader could pick it out of the
> BlargCache via the thread reference. 
> 
> Now, this is fancy - besides the BlargCache, you would need a custom
> loader.
> 
> Is there no way you could make a 'context tool' to do this and access it
> from within a template?  Your tool can 'recursivly' use velocity via the
> org.apache.velocity.app.Velocity class if you needed to, which gives you
> supported access to the template engine for processing Strings and
> Readers.  Velocity would have no problem being called recursively like
> that. 
> 
> Or, just use the o.a.v.app.Velocity class from within the Servlet - punt
> on the normal 'return a Template' model.
> 
> > Right now I'm only prototyping something as proof of concept.  My goal is
> > to show how much easier Velocity might be to use over JSP with this third
> > party product.  Then maybe they'll consider supporting it.  Or, if not, at
> > least providing a better API in their product so it would be easier to add
> > Velocity support.
> 
> :)
> 
> Best of luck.
> 
> geir 
> 
> -- 
> Geir Magnusson Jr.                           geirm@optonline.net
> System and Software Consulting
> Developing for the web?  See http://jakarta.apache.org/velocity/
> "still climbing up to the shoulders..."
> 


Re: Introspection problems

Posted by "Geir Magnusson Jr." <ge...@optonline.net>.
Bill Burton wrote:
> 
> > > Then, I tried to set a value something like:
> > >     #set($breakfast_omlet.cheeze = "swiss")
> > > which failed with an error in the log:
> > >     [error] ASTReference : cannot find cheeze as settable property or key
> > > to Map in template
> > >
> > > So, I guess my Omlet object needs to implement a Map or, can I get away
> > > with less?
> >
> > A Map would do it, as would a setCheeze(String) method.
> 
> Okay.  In this case cheeze is the key and swiss is the value.  I'm trying
> to get
> #set($breakfast_omlet.cheeze = "swiss")
> to execute:
> omletInstance.put("cheeze", "swiss") just like you can do with a HashMap.
> 
> I looked at what it might take to support a Map interface by having my
> Omlet class extend AbstractMap but then I would have to implement entrySet
> and keySet methods and so on.  It's just way beyond the scope (and time) I
> can afford to solve such a simple problem.

Velocity doesn't care about the entrySet and keySet methods, so just
stub them.  It will care about values() if you want to iterate over it
in #foreach() - if you aren't going to iterate, stub that too.

> After poking around the Velocity source a bit, I found in the
> runtime/parser/node/ASTReference class this comment and code:
>             /*
>              *  right now, we only support the Map interface
>              */
> 
>             if (result instanceof Map)
>             {
>                 try
>                 {
>                     ((Map) result).put(identifier, value);
>                 }
>             ...
> 
> So, clearly, .put(key, value) only works if the underlying object
> implements Map.  But the GetExecutor class supports a .get(key) method
> implemented by any class which is immensely convenient.  It seems to me
> doing the same thing for .put(key, value) would also be beneficial in a
> similar manner.

That's a good observation...
 
> 
> The third party API I'm dealing with has a very simple way of retrieving a
> page from a database but the catch is the context of this API is always
> established from that of the HTTPServletRequest/Response.  There is no way
> it can be called from outside a request.  Since it's not possible to pass
> the Velocity context through the Runtime.getTemplate method down to the
> ResourceManager and ultimately to a custom ResourceLoader, I can't call
> this API from there.

Well... [ disclaimer : off the top of my head half way through first cup
of coffee], you could take advantage of the fact that all of Velocity's
activities on your behalf happen on your thread, you could make a
Singleton 'BlargCache', and place the request/response/whatever into it
associated with your thread.  Then, your loader could pick it out of the
BlargCache via the thread reference. 

Now, this is fancy - besides the BlargCache, you would need a custom
loader.

Is there no way you could make a 'context tool' to do this and access it
from within a template?  Your tool can 'recursivly' use velocity via the
org.apache.velocity.app.Velocity class if you needed to, which gives you
supported access to the template engine for processing Strings and
Readers.  Velocity would have no problem being called recursively like
that. 

Or, just use the o.a.v.app.Velocity class from within the Servlet - punt
on the normal 'return a Template' model.

> Right now I'm only prototyping something as proof of concept.  My goal is
> to show how much easier Velocity might be to use over JSP with this third
> party product.  Then maybe they'll consider supporting it.  Or, if not, at
> least providing a better API in their product so it would be easier to add
> Velocity support.

:)

Best of luck.

geir 

-- 
Geir Magnusson Jr.                           geirm@optonline.net
System and Software Consulting
Developing for the web?  See http://jakarta.apache.org/velocity/
"still climbing up to the shoulders..."

Re: Introspection problems

Posted by Bill Burton <bi...@progress.com>.
Hello,

"Geir Magnusson Jr." wrote:
> > > > but fails in 5-14 nighly
> > > > req.getServlet() = $req.servlet or $req.Servlet or $req.getServlet() <--
> > > > all fail
> > >
> > > Right. Geir screwed up the build. It has been fixed in CVS now.
> >
> > Okay got it.  Now passes all the tests too :)
> 
> If ever it doesn't pass the testbed, run.  It's preferred if you give us
> a shout, but even if not, don't use.

Sure.

> > > > In addition, I'm adding a couple of my own objects to the Velocity
> > > > context.  On one of them introspection works on methods only, not
> > > > properties.
> > >
> > > Properties need to be wrapped in another object...take a look at:
> > >
> > > <http://jakarta.apache.org/cvsweb/index.cgi/jakarta-velocity/src/java/org/ap
> > > ache/velocity/app/FieldMethodizer.java?rev=1.3&content-type=text/vnd.viewcvs
> > > -markup>
> >
> > What I want to do rather, is to put a facade over a
> > $breakfast.getOmlet("cheese") method so it can be specified as
> > $breakfast.omlet.cheese.  The latter is much cleaner so I'd like to use it
> > when possible.
> 
> You wouldn't need a facade if getOmlet() returned an object that had a
> get(String) method.

Actually, the Omlet object _is_ the facade and was written solely for that
purpose.  I've implemented get, put and remove methods wrapped around the
accessor methods of a third party API, conceptually similar to
java.util.Properties.

> > I played around with this a bit and by creating an inner class Omlet
> > object to the Breakfast object with a get() method on Omlet, I could then
> > do something like: $breakfast_omlet.cheese and it worked.
> 
> An underline?

Because ctx.put("breakfast.omlet", omlet) doesn't work so I used
"breakfast_omlet" instead.

The reason for wanting to do this is to support a hierarchy so I could do
$breakfast.this, $breakfast.omlet.cheeze (
breakfast.getOmlet.get("cheeze") ).

> > Then, I tried to set a value something like:
> >     #set($breakfast_omlet.cheeze = "swiss")
> > which failed with an error in the log:
> >     [error] ASTReference : cannot find cheeze as settable property or key
> > to Map in template
> >
> > So, I guess my Omlet object needs to implement a Map or, can I get away
> > with less?
> 
> A Map would do it, as would a setCheeze(String) method.

Okay.  In this case cheeze is the key and swiss is the value.  I'm trying
to get 
#set($breakfast_omlet.cheeze = "swiss")
to execute:
omletInstance.put("cheeze", "swiss") just like you can do with a HashMap.

I looked at what it might take to support a Map interface by having my
Omlet class extend AbstractMap but then I would have to implement entrySet
and keySet methods and so on.  It's just way beyond the scope (and time) I
can afford to solve such a simple problem.

After poking around the Velocity source a bit, I found in the
runtime/parser/node/ASTReference class this comment and code:
            /*
             *  right now, we only support the Map interface
             */

            if (result instanceof Map)
            {
                try
                {
                    ((Map) result).put(identifier, value);
                }
            ...

So, clearly, .put(key, value) only works if the underlying object
implements Map.  But the GetExecutor class supports a .get(key) method
implemented by any class which is immensely convenient.  It seems to me
doing the same thing for .put(key, value) would also be beneficial in a
similar manner.

> > > > I should also note that I'm calling Velocity.evaluate() in an overridden
> > > > mergeTemplate method.  This is necessary because the template is being
> > > > read out of a database through a high level API.  I can't create a
> > > > resource to read the database because this high level API only exists in
> > > > the context of a request.
> > >
> > > Sounds kind of like a whack design to me...but whatever floats your boat.
> >
> > Quite whacko to be sure.  It shows how Titanic the design of this API is
> > that I'm having to interface with.  Now if I could optionally pass a
> > context object into the getTemplate method and be able to access it in a
> > custom resource, then I could use the mergeTemplate method and things
> > would be more standard at the servlet level.
> >
> 
> Hm?  Can you elaborate?

The third party API I'm dealing with has a very simple way of retrieving a
page from a database but the catch is the context of this API is always
established from that of the HTTPServletRequest/Response.  There is no way
it can be called from outside a request.  Since it's not possible to pass
the Velocity context through the Runtime.getTemplate method down to the
ResourceManager and ultimately to a custom ResourceLoader, I can't call
this API from there.

Right now I'm only prototyping something as proof of concept.  My goal is
to show how much easier Velocity might be to use over JSP with this third
party product.  Then maybe they'll consider supporting it.  Or, if not, at
least providing a better API in their product so it would be easier to add
Velocity support.

Thanks again for the help,
-Bill

Re: Introspection problems

Posted by "Geir Magnusson Jr." <ge...@optonline.net>.
Bill Burton wrote:
> 
> Hello,
> 
> Jon Stevens wrote:
> >
> > on 5/14/01 2:08 PM, "Bill Burton" <bi...@progress.com> wrote:
> >
> > > Hello,
> > >
> > > I'm just starting to look at Velocity.  Wrote a servlet that extends
> > > VelocityServlet.  However, I'm running into some problems where properties
> > > are not being recognized and evaluated.  For instance:
> > >
> > > pagename parameter = ${req.Parameter.pagename}      <-- fails
> > >                 or   $req.parameter.pagename        <-- fails
> >
> > Translates to: $req.getParameter().get("pagename")
> 
> Oh.  I completely misunderstood how the property introspection worked.  I
> thought I was following the ideas of the examples in the Users Guide but
> now that I go back and look again I don't know why I thought that would
> work.
> 
> > >                 or   $req.getParameter("pagename")  <-- works in 1.0.1
> >
> > Right.
> >
> > Of course those cases are going to fail. According to standard
> > bean/introspection rules, the only one that will work is the last one.
> 
> Okay.  It be helpful if some of the more involved examples in the User's
> Guide also showed the equivalent Java code that's called, particularly the
> monica and bill example.

Ok. That's good feedback.
 
> >
> > > but fails in 5-14 nighly
> > > req.getServlet() = $req.servlet or $req.Servlet or $req.getServlet() <--
> > > all fail
> >
> > Right. Geir screwed up the build. It has been fixed in CVS now.
> 
> Okay got it.  Now passes all the tests too :)

If ever it doesn't pass the testbed, run.  It's preferred if you give us
a shout, but even if not, don't use. 
 
> > > In addition, I'm adding a couple of my own objects to the Velocity
> > > context.  On one of them introspection works on methods only, not
> > > properties.
> >
> > Properties need to be wrapped in another object...take a look at:
> >
> > <http://jakarta.apache.org/cvsweb/index.cgi/jakarta-velocity/src/java/org/ap
> > ache/velocity/app/FieldMethodizer.java?rev=1.3&content-type=text/vnd.viewcvs
> > -markup>
> 
> What I want to do rather, is to put a facade over a
> $breakfast.getOmlet("cheese") method so it can be specified as
> $breakfast.omlet.cheese.  The latter is much cleaner so I'd like to use it
> when possible.

You wouldn't need a facade if getOmlet() returned an object that had a
get(String) method.
 
> I played around with this a bit and by creating an inner class Omlet
> object to the Breakfast object with a get() method on Omlet, I could then
> do something like: $breakfast_omlet.cheese and it worked.  

An underline?

> I also tried
> storing the Omlet object using the context name "breakfast.omlet" but then
> it didn't work.  If "." characters don't work for context names, shouldn't
> they be disallowed?

Probably :)

> Then, I tried to set a value something like:
>     #set($breakfast_omlet.cheeze = "swiss")
> which failed with an error in the log:
>     [error] ASTReference : cannot find cheeze as settable property or key
> to Map in template
> 
> So, I guess my Omlet object needs to implement a Map or, can I get away
> with less?

A Map would do it, as would a setCheeze(String) method.
 
> > >  On the other object, introspection doesn't work at all.
> >
> > Probably a permission scope issue. Make sure things are public.
> 
> Ah yes, that was it.
> 
> > > I should also note that I'm calling Velocity.evaluate() in an overridden
> > > mergeTemplate method.  This is necessary because the template is being
> > > read out of a database through a high level API.  I can't create a
> > > resource to read the database because this high level API only exists in
> > > the context of a request.
> >
> > Sounds kind of like a whack design to me...but whatever floats your boat.
> 
> Quite whacko to be sure.  It shows how Titanic the design of this API is
> that I'm having to interface with.  Now if I could optionally pass a
> context object into the getTemplate method and be able to access it in a
> custom resource, then I could use the mergeTemplate method and things
> would be more standard at the servlet level.
> 

Hm?  Can you elaborate?

geir


-- 
Geir Magnusson Jr.                           geirm@optonline.net
System and Software Consulting
Developing for the web?  See http://jakarta.apache.org/velocity/
"still climbing up to the shoulders..."

Re: Introspection problems

Posted by Bill Burton <bi...@progress.com>.
Hello,

Jon Stevens wrote:
> 
> on 5/14/01 2:08 PM, "Bill Burton" <bi...@progress.com> wrote:
> 
> > Hello,
> >
> > I'm just starting to look at Velocity.  Wrote a servlet that extends
> > VelocityServlet.  However, I'm running into some problems where properties
> > are not being recognized and evaluated.  For instance:
> >
> > pagename parameter = ${req.Parameter.pagename}      <-- fails
> >                 or   $req.parameter.pagename        <-- fails
> 
> Translates to: $req.getParameter().get("pagename")

Oh.  I completely misunderstood how the property introspection worked.  I
thought I was following the ideas of the examples in the Users Guide but
now that I go back and look again I don't know why I thought that would
work.

> >                 or   $req.getParameter("pagename")  <-- works in 1.0.1
> 
> Right.
>
> Of course those cases are going to fail. According to standard
> bean/introspection rules, the only one that will work is the last one.

Okay.  It be helpful if some of the more involved examples in the User's
Guide also showed the equivalent Java code that's called, particularly the
monica and bill example.

> 
> > but fails in 5-14 nighly
> > req.getServlet() = $req.servlet or $req.Servlet or $req.getServlet() <--
> > all fail
> 
> Right. Geir screwed up the build. It has been fixed in CVS now.

Okay got it.  Now passes all the tests too :)

> > In addition, I'm adding a couple of my own objects to the Velocity
> > context.  On one of them introspection works on methods only, not
> > properties.
> 
> Properties need to be wrapped in another object...take a look at:
> 
> <http://jakarta.apache.org/cvsweb/index.cgi/jakarta-velocity/src/java/org/ap
> ache/velocity/app/FieldMethodizer.java?rev=1.3&content-type=text/vnd.viewcvs
> -markup>

What I want to do rather, is to put a facade over a
$breakfast.getOmlet("cheese") method so it can be specified as
$breakfast.omlet.cheese.  The latter is much cleaner so I'd like to use it
when possible.

I played around with this a bit and by creating an inner class Omlet
object to the Breakfast object with a get() method on Omlet, I could then
do something like: $breakfast_omlet.cheese and it worked.  I also tried
storing the Omlet object using the context name "breakfast.omlet" but then
it didn't work.  If "." characters don't work for context names, shouldn't
they be disallowed?

Then, I tried to set a value something like:
    #set($breakfast_omlet.cheeze = "swiss")
which failed with an error in the log:
    [error] ASTReference : cannot find cheeze as settable property or key
to Map in template

So, I guess my Omlet object needs to implement a Map or, can I get away
with less?

> >  On the other object, introspection doesn't work at all.
> 
> Probably a permission scope issue. Make sure things are public.

Ah yes, that was it.

> > I should also note that I'm calling Velocity.evaluate() in an overridden
> > mergeTemplate method.  This is necessary because the template is being
> > read out of a database through a high level API.  I can't create a
> > resource to read the database because this high level API only exists in
> > the context of a request.
> 
> Sounds kind of like a whack design to me...but whatever floats your boat.

Quite whacko to be sure.  It shows how Titanic the design of this API is
that I'm having to interface with.  Now if I could optionally pass a
context object into the getTemplate method and be able to access it in a
custom resource, then I could use the mergeTemplate method and things
would be more standard at the servlet level.

Thanks for the feedback,
-Bill

Re: Introspection problems

Posted by Jon Stevens <jo...@latchkey.com>.
on 5/14/01 2:08 PM, "Bill Burton" <bi...@progress.com> wrote:

> Hello,
> 
> I'm just starting to look at Velocity.  Wrote a servlet that extends
> VelocityServlet.  However, I'm running into some problems where properties
> are not being recognized and evaluated.  For instance:
> 
> pagename parameter = ${req.Parameter.pagename}      <-- fails
>                 or   $req.parameter.pagename        <-- fails

Translates to: $req.getParameter().get("pagename")

>                 or   $req.getParameter("pagename")  <-- works in 1.0.1

Right.

Of course those cases are going to fail. According to standard
bean/introspection rules, the only one that will work is the last one.

> but fails in 5-14 nighly
> req.getServlet() = $req.servlet or $req.Servlet or $req.getServlet() <--
> all fail

Right. Geir screwed up the build. It has been fixed in CVS now.

> In addition, I'm adding a couple of my own objects to the Velocity
> context.  On one of them introspection works on methods only, not
> properties.

Properties need to be wrapped in another object...take a look at:

<http://jakarta.apache.org/cvsweb/index.cgi/jakarta-velocity/src/java/org/ap
ache/velocity/app/FieldMethodizer.java?rev=1.3&content-type=text/vnd.viewcvs
-markup>

>  On the other object, introspection doesn't work at all.

Probably a permission scope issue. Make sure things are public.

> I should also note that I'm calling Velocity.evaluate() in an overridden
> mergeTemplate method.  This is necessary because the template is being
> read out of a database through a high level API.  I can't create a
> resource to read the database because this high level API only exists in
> the context of a request.

Sounds kind of like a whack design to me...but whatever floats your boat.

-jon

-- 
If you come from a Perl or PHP background, JSP is a way to take
your pain to new levels. --Anonymous
<http://jakarta.apache.org/velocity/ymtd/ymtd.html>