You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@velocity.apache.org by Matt Raible <ma...@raibledesigns.com> on 2003/09/27 23:47:30 UTC

WebappLoader and Velocimacros

I'm trying to enhance struts-menu (http://sf.net/projects/struts-menu),
demo at http://raibledesigns.com/struts-menu to allow for Velocity
Templates.  I've got most of it working, but I'm having a few issues.

I've added the #local declaration to my velocity-1.4-dev.jar and
everything is working fine there.  I have the template below that also
works great.  However, since the #eval macro and the #displayMenu macro
will likely be the same for all menus, I thought I'd put them in a
global library.  To do this, I declared the following in my
velocity.properties file:

velocimacro.library = macros.vm
velocimacro.library.autoreload = true
velocimacro.context.localscope = true

# allow users to modify displayMenu and eval macros in their local
templates
velocimacro.permissions.allow.inline.to.replace.global = true 
velocimacro.permissions.allow.inline.local.scope = false

And then I moved these two macros to macros.vm.  This actually works
with the template below.  

FIRST QUESTION:  Why do I have to reload this webapp every time I change
the template?  I've turned off caching on all my loaders.  I'd love for
these template to be live JSPs (at least for development) where I can
redeploy, refresh in browser, and can view my changes.

SECOND QUESTION:  I have a 2nd template that is similar to the one
below, but it as a different #menuItem macro - with
$displayer.getMessage($menu.title), rather than simply $menu.title.  If
I have all macros in the same template (no library), this works fine,
but with a global library, I get:

WARN - SimpleLog4JLogSystem.logVelocityMessage(172) |
org.apache.velocity.runtime.exception.Referenc
eException: reference : template = /table.html [line 9,column 5] :
$displayer.getMessage($menu.title
) is not a valid reference.

## Evaluates other macros.
#macro(eval $_macro)$_macro#end

#macro( displayMenu $menu $level )
  #if ($menu.components.size() > 0)
    ## display top menu
    #menuItem($menu $level)
    #foreach ($menu in $menu.components)
      #local ($menu $level)
        #set ($level = $level+1)
        #if ($menu.components.size() > 0) 
          #eval("#displayMenu($menu $level)")
        #else
          #menuItem($menu $level)
        #end
      #end
    #end
  #else
    #menuItem($menu $level)
  #end
#end
  
#macro( menuItem $menu $level )
  #foreach ($i in [0..$level])
      
  #end
  #if ($menu.url) 
    <a href="$menu.url" title="$menu.title">
        $menu.title</a>
  #else 
    $menu.title
  #end
  <br />
#end

#displayMenu($menu 0)

THIRD QUESTION: There seems to be an issue when you have two menus
(menu:useMenuDisplayer tag) on one page (each using different
templates). The second menu seems to try and use parts of the first
table's template - very strange.

LAST QUESTION: I'm using a custom WebappResourceLoader (from Roller,
source = http://tinyurl.com/ow5d) that supposedly borrows heavily from
org.apache.velocity.tools.view.servlet.WebappLoader.  I'd rather just
use the one in Velocity, but I can't seem to get it to work. The one in
Roller is initialized with one simple call:
WebappResourceLoader.setServletContext(pageContext.getServletContext());


Thanks for any help offered.

Matt




Re: WebappLoader and Velocimacros

Posted by Nathan Bubna <na...@esha.com>.
Matt Raible said:
> Sorry for the inappropriate e-mail.

aw, i wouldn't call it inappropriate, just not very helpful.  :)

> I got all my issues fixed.  Here's how:
>
> 1.  I changed to use the WebappLoader from Velocity (by copying code
> from the VelocityViewServlet) and now everything refreshes as expected.
...

sweet.  i'm glad to hear it.  your code looks good to me.

> Thanks for the tip, this is exactly what I was looking for.
>
> 2.  Duh, it wasn't a valid reference.

:)

> 3.  The new WebappLoader seems to have fixed this problem as well.
>
> 4.  Got the Velocity WebappLoader to work, so this is not an issue.
>
> Thanks for responding to my question.

you're welcome!  and if/when struts-menu is ready-to-go for VelocityStruts
users, be sure to let us know over here.  i'm curious about it. :)

Nathan Bubna
nathan@esha.com


---------------------------------------------------------------------
To unsubscribe, e-mail: velocity-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: velocity-user-help@jakarta.apache.org


Re: WebappLoader and Velocimacros

Posted by Matt Raible <ma...@raibledesigns.com>.
Sorry for the inappropriate e-mail.  I got all my issues fixed.  Here's  
how:

1.  I changed to use the WebappLoader from Velocity (by copying code  
from the VelocityViewServlet) and now everything refreshes as expected.  
  Here's the code I'm now using:

	/**
	 * Key used to access the ServletContext in
	 * the Velocity application attributes.
	 */
	public static final String SERVLET_CONTEXT_KEY =  
ServletContext.class.getName();
	
     //~ Methods  
================================================================

     public void init(PageContext pageContext, MenuDisplayerMapping  
mapping) {
         super.init(pageContext, mapping);
         this.pageContext = pageContext;

		// MR: Copied from VelocityViewServlet to initialize WebappLoader
		Velocity.setApplicationAttribute(SERVLET_CONTEXT_KEY,  
pageContext.getServletContext());

		// default to servletlogger, which logs to the servlet engines log
		Velocity.setProperty(RuntimeConstants.RUNTIME_LOG_LOGSYSTEM_CLASS,
							 ServletLogger.class.getName());

		// by default, load resources with webapp resource loader
		Velocity.setProperty(RuntimeConstants.RESOURCE_LOADER, "webapp");
		Velocity.setProperty("webapp.resource.loader.class",  
WebappLoader.class.getName());

		// now all is ready - init Velocity
         try {
             ResourceBundle rb = ResourceBundle.getBundle("velocity");

             Properties props = new Properties();

             for (Enumeration keys = rb.getKeys();  
keys.hasMoreElements();) {
                 String key = (String) keys.nextElement();
                 props.put(key, rb.getString(key));
             }

             // only initialized the first time it's called, from:
             //	http://jakarta.apache.org/velocity/developer-guide.html
             //	it's ignored for subsequent calls
             Velocity.init(props);
         } catch (Exception e) {
             log.error("Error initializing Velocity: " + e.getMessage());
             e.printStackTrace();
         }
     }

Thanks for the tip, this is exactly what I was looking for.

2.  Duh, it wasn't a valid reference.

3.  The new WebappLoader seems to have fixed this problem as well.

4.  Got the Velocity WebappLoader to work, so this is not an issue.

Thanks for responding to my question.

Matt

On Tuesday, September 30, 2003, at 12:22 PM, Nathan Bubna wrote:

> Matt Raible said:
>> I'm trying to enhance struts-menu  
>> (http://sf.net/projects/struts-menu),
>> demo at http://raibledesigns.com/struts-menu to allow for Velocity
>> Templates.  I've got most of it working, but I'm having a few issues.
>
> i'll see if i can give a few answers...
>
>> I've added the #local declaration to my velocity-1.4-dev.jar and
>> everything is working fine there.  I have the template below that also
>> works great.  However, since the #eval macro and the #displayMenu  
>> macro
>> will likely be the same for all menus, I thought I'd put them in a
>> global library.  To do this, I declared the following in my
>> velocity.properties file:
>>
>> velocimacro.library = macros.vm
>> velocimacro.library.autoreload = true
>> velocimacro.context.localscope = true
>>
>> # allow users to modify displayMenu and eval macros in their local
>> templates
>> velocimacro.permissions.allow.inline.to.replace.global = true
>> velocimacro.permissions.allow.inline.local.scope = false
>>
>> And then I moved these two macros to macros.vm.  This actually works
>> with the template below.
>>
>> FIRST QUESTION:  Why do I have to reload this webapp every time I  
>> change
>> the template?  I've turned off caching on all my loaders.  I'd love  
>> for
>> these template to be live JSPs (at least for development) where I can
>> redeploy, refresh in browser, and can view my changes.
>
> uh, first off, these are Velocity templates, not JSPs.  they're two  
> different
> things that will stay different.
>
> second, i believe the 'velocimacro.library.autoreload = true' is not  
> working
> because the WebappLoader does not presently have functioning
> isSourceModified() and getLastModified() methods.  the Servlet API  
> does not
> have any easy way to implement these.  at one point, i looked into how  
> it
> could be done, and i remember that i thought it could be, but i never  
> went
> through with it or tested it.  i'm just too busy right now.  if you or  
> someone
> else needs it anytime soon, then they'll need to step up with a patch.  
>  this
> is open source; the person with the itch should do the scratching.
>
> or alternately, you could try using the FileResourceLoader (not  
> incredibly
> easy or portable in a web environment).
>
>> SECOND QUESTION:  I have a 2nd template that is similar to the one
>> below, but it as a different #menuItem macro - with
>> $displayer.getMessage($menu.title), rather than simply $menu.title.   
>> If
>> I have all macros in the same template (no library), this works fine,
>> but with a global library, I get:
>>
>> WARN - SimpleLog4JLogSystem.logVelocityMessage(172) |
>> org.apache.velocity.runtime.exception.Referenc
>> eException: reference : template = /table.html [line 9,column 5] :
>> $displayer.getMessage($menu.title
>> ) is not a valid reference.
>
> if it's not a valid reference, then it's not a valid reference.   
> without
> knowing what the $displayer or $menu references are (or are supposed  
> to be),
> how can we help you?  you seem to assume that some here is familiar  
> with your
> code or is willing to take the time to look through all of it to find  
> the
> relevant parts.  i have to warn you, that's not likely to happen.
>
>> ## Evaluates other macros.
>> #macro(eval $_macro)$_macro#end
>>
>> #macro( displayMenu $menu $level )
>>   #if ($menu.components.size() > 0)
>>     ## display top menu
>>     #menuItem($menu $level)
>>     #foreach ($menu in $menu.components)
>>       #local ($menu $level)
>>         #set ($level = $level+1)
>>         #if ($menu.components.size() > 0)
>>           #eval("#displayMenu($menu $level)")
>>         #else
>>           #menuItem($menu $level)
>>         #end
>>       #end
>>     #end
>>   #else
>>     #menuItem($menu $level)
>>   #end
>> #end
>>
>> #macro( menuItem $menu $level )
>>   #foreach ($i in [0..$level])
>>
>>   #end
>>   #if ($menu.url)
>>     <a href="$menu.url" title="$menu.title">
>>         $menu.title</a>
>>   #else
>>     $menu.title
>>   #end
>>   <br />
>> #end
>>
>> #displayMenu($menu 0)
>
> thanks, but i'm not sure what these have to do with your questions (or  
> which
> question they're about).
>
>> THIRD QUESTION: There seems to be an issue when you have two menus
>> (menu:useMenuDisplayer tag) on one page (each using different
>> templates). The second menu seems to try and use parts of the first
>> table's template - very strange.
>
> yep, sounds strange.  but i don't know what anything about these menus  
> or
> where they are getting their templates from.  i've never used  
> struts-menu
> before.
>
>> LAST QUESTION: I'm using a custom WebappResourceLoader (from Roller,
>> source = http://tinyurl.com/ow5d) that supposedly borrows heavily from
>> org.apache.velocity.tools.view.servlet.WebappLoader.  I'd rather just
>> use the one in Velocity, but I can't seem to get it to work.  The one  
>> in
>> Roller is initialized with one simple call:
>> WebappResourceLoader.setServletContext(pageContext.getServletContext() 
>> );
>
> that's a shame.  but just telling us "i can't get it to work" doesn't  
> help us
> help you.  you're practically begging to be referred to the "How to  
> Ask Smart
> Questions" document here.  :)
>
> now, if you couldn't get to the WebappLoader to work, then why wasn't  
> this
> your first question?  if you are using Roller's derivative of the
> WebappLoader, then ask them about your loader issues.
>
> also, why are you telling us how the Roller one works? how is that  
> relevant
> here? if you're having trouble with our WebappLoader, you should tell  
> us how
> you are trying to use our WebappLoader, not theirs.  a suggestion:   
> look at
> how the VelocityViewServlet (in the VelocityTools' CVS or source  
> distribution)
> uses the WebappLoader for an example of how to make it work.
>
> Nathan Bubna
> nathan@esha.com
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: velocity-user-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: velocity-user-help@jakarta.apache.org

Re: WebappLoader and Velocimacros

Posted by Nathan Bubna <na...@esha.com>.
Matt Raible said:
> I'm trying to enhance struts-menu (http://sf.net/projects/struts-menu),
> demo at http://raibledesigns.com/struts-menu to allow for Velocity
> Templates.  I've got most of it working, but I'm having a few issues.

i'll see if i can give a few answers...

> I've added the #local declaration to my velocity-1.4-dev.jar and
> everything is working fine there.  I have the template below that also
> works great.  However, since the #eval macro and the #displayMenu macro
> will likely be the same for all menus, I thought I'd put them in a
> global library.  To do this, I declared the following in my
> velocity.properties file:
>
> velocimacro.library = macros.vm
> velocimacro.library.autoreload = true
> velocimacro.context.localscope = true
>
> # allow users to modify displayMenu and eval macros in their local
> templates
> velocimacro.permissions.allow.inline.to.replace.global = true
> velocimacro.permissions.allow.inline.local.scope = false
>
> And then I moved these two macros to macros.vm.  This actually works
> with the template below.
>
> FIRST QUESTION:  Why do I have to reload this webapp every time I change
> the template?  I've turned off caching on all my loaders.  I'd love for
> these template to be live JSPs (at least for development) where I can
> redeploy, refresh in browser, and can view my changes.

uh, first off, these are Velocity templates, not JSPs.  they're two different
things that will stay different.

second, i believe the 'velocimacro.library.autoreload = true' is not working
because the WebappLoader does not presently have functioning
isSourceModified() and getLastModified() methods.  the Servlet API does not
have any easy way to implement these.  at one point, i looked into how it
could be done, and i remember that i thought it could be, but i never went
through with it or tested it.  i'm just too busy right now.  if you or someone
else needs it anytime soon, then they'll need to step up with a patch.  this
is open source; the person with the itch should do the scratching.

or alternately, you could try using the FileResourceLoader (not incredibly
easy or portable in a web environment).

> SECOND QUESTION:  I have a 2nd template that is similar to the one
> below, but it as a different #menuItem macro - with
> $displayer.getMessage($menu.title), rather than simply $menu.title.  If
> I have all macros in the same template (no library), this works fine,
> but with a global library, I get:
>
> WARN - SimpleLog4JLogSystem.logVelocityMessage(172) |
> org.apache.velocity.runtime.exception.Referenc
> eException: reference : template = /table.html [line 9,column 5] :
> $displayer.getMessage($menu.title
> ) is not a valid reference.

if it's not a valid reference, then it's not a valid reference.  without
knowing what the $displayer or $menu references are (or are supposed to be),
how can we help you?  you seem to assume that some here is familiar with your
code or is willing to take the time to look through all of it to find the
relevant parts.  i have to warn you, that's not likely to happen.

> ## Evaluates other macros.
> #macro(eval $_macro)$_macro#end
>
> #macro( displayMenu $menu $level )
>   #if ($menu.components.size() > 0)
>     ## display top menu
>     #menuItem($menu $level)
>     #foreach ($menu in $menu.components)
>       #local ($menu $level)
>         #set ($level = $level+1)
>         #if ($menu.components.size() > 0)
>           #eval("#displayMenu($menu $level)")
>         #else
>           #menuItem($menu $level)
>         #end
>       #end
>     #end
>   #else
>     #menuItem($menu $level)
>   #end
> #end
>
> #macro( menuItem $menu $level )
>   #foreach ($i in [0..$level])
>
>   #end
>   #if ($menu.url)
>     <a href="$menu.url" title="$menu.title">
>         $menu.title</a>
>   #else
>     $menu.title
>   #end
>   <br />
> #end
>
> #displayMenu($menu 0)

thanks, but i'm not sure what these have to do with your questions (or which
question they're about).

> THIRD QUESTION: There seems to be an issue when you have two menus
> (menu:useMenuDisplayer tag) on one page (each using different
> templates). The second menu seems to try and use parts of the first
> table's template - very strange.

yep, sounds strange.  but i don't know what anything about these menus or
where they are getting their templates from.  i've never used struts-menu
before.

> LAST QUESTION: I'm using a custom WebappResourceLoader (from Roller,
> source = http://tinyurl.com/ow5d) that supposedly borrows heavily from
> org.apache.velocity.tools.view.servlet.WebappLoader.  I'd rather just
> use the one in Velocity, but I can't seem to get it to work.  The one in
> Roller is initialized with one simple call:
> WebappResourceLoader.setServletContext(pageContext.getServletContext());

that's a shame.  but just telling us "i can't get it to work" doesn't help us
help you.  you're practically begging to be referred to the "How to Ask Smart
Questions" document here.  :)

now, if you couldn't get to the WebappLoader to work, then why wasn't this
your first question?  if you are using Roller's derivative of the
WebappLoader, then ask them about your loader issues.

also, why are you telling us how the Roller one works? how is that relevant
here? if you're having trouble with our WebappLoader, you should tell us how
you are trying to use our WebappLoader, not theirs.  a suggestion:  look at
how the VelocityViewServlet (in the VelocityTools' CVS or source distribution)
uses the WebappLoader for an example of how to make it work.

Nathan Bubna
nathan@esha.com


---------------------------------------------------------------------
To unsubscribe, e-mail: velocity-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: velocity-user-help@jakarta.apache.org


Re: WebappLoader and Velocimacros

Posted by Nathan Bubna <na...@esha.com>.
Matt Raible said:
> I'm trying to enhance struts-menu (http://sf.net/projects/struts-menu),
> demo at http://raibledesigns.com/struts-menu to allow for Velocity
> Templates.  I've got most of it working, but I'm having a few issues.

i'll see if i can give a few answers...

> I've added the #local declaration to my velocity-1.4-dev.jar and
> everything is working fine there.  I have the template below that also
> works great.  However, since the #eval macro and the #displayMenu macro
> will likely be the same for all menus, I thought I'd put them in a
> global library.  To do this, I declared the following in my
> velocity.properties file:
>
> velocimacro.library = macros.vm
> velocimacro.library.autoreload = true
> velocimacro.context.localscope = true
>
> # allow users to modify displayMenu and eval macros in their local
> templates
> velocimacro.permissions.allow.inline.to.replace.global = true
> velocimacro.permissions.allow.inline.local.scope = false
>
> And then I moved these two macros to macros.vm.  This actually works
> with the template below.
>
> FIRST QUESTION:  Why do I have to reload this webapp every time I change
> the template?  I've turned off caching on all my loaders.  I'd love for
> these template to be live JSPs (at least for development) where I can
> redeploy, refresh in browser, and can view my changes.

uh, first off, these are Velocity templates, not JSPs.  they're two different
things that will stay different.

second, i believe the 'velocimacro.library.autoreload = true' is not working
because the WebappLoader does not presently have functioning
isSourceModified() and getLastModified() methods.  the Servlet API does not
have any easy way to implement these.  at one point, i looked into how it
could be done, and i remember that i thought it could be, but i never went
through with it or tested it.  i'm just too busy right now.  if you or someone
else needs it anytime soon, then they'll need to step up with a patch.  this
is open source; the person with the itch should do the scratching.

or alternately, you could try using the FileResourceLoader (not incredibly
easy or portable in a web environment).

> SECOND QUESTION:  I have a 2nd template that is similar to the one
> below, but it as a different #menuItem macro - with
> $displayer.getMessage($menu.title), rather than simply $menu.title.  If
> I have all macros in the same template (no library), this works fine,
> but with a global library, I get:
>
> WARN - SimpleLog4JLogSystem.logVelocityMessage(172) |
> org.apache.velocity.runtime.exception.Referenc
> eException: reference : template = /table.html [line 9,column 5] :
> $displayer.getMessage($menu.title
> ) is not a valid reference.

if it's not a valid reference, then it's not a valid reference.  without
knowing what the $displayer or $menu references are (or are supposed to be),
how can we help you?  you seem to assume that some here is familiar with your
code or is willing to take the time to look through all of it to find the
relevant parts.  i have to warn you, that's not likely to happen.

> ## Evaluates other macros.
> #macro(eval $_macro)$_macro#end
>
> #macro( displayMenu $menu $level )
>   #if ($menu.components.size() > 0)
>     ## display top menu
>     #menuItem($menu $level)
>     #foreach ($menu in $menu.components)
>       #local ($menu $level)
>         #set ($level = $level+1)
>         #if ($menu.components.size() > 0)
>           #eval("#displayMenu($menu $level)")
>         #else
>           #menuItem($menu $level)
>         #end
>       #end
>     #end
>   #else
>     #menuItem($menu $level)
>   #end
> #end
>
> #macro( menuItem $menu $level )
>   #foreach ($i in [0..$level])
>
>   #end
>   #if ($menu.url)
>     <a href="$menu.url" title="$menu.title">
>         $menu.title</a>
>   #else
>     $menu.title
>   #end
>   <br />
> #end
>
> #displayMenu($menu 0)

thanks, but i'm not sure what these have to do with your questions (or which
question they're about).

> THIRD QUESTION: There seems to be an issue when you have two menus
> (menu:useMenuDisplayer tag) on one page (each using different
> templates). The second menu seems to try and use parts of the first
> table's template - very strange.

yep, sounds strange.  but i don't know what anything about these menus or
where they are getting their templates from.  i've never used struts-menu
before.

> LAST QUESTION: I'm using a custom WebappResourceLoader (from Roller,
> source = http://tinyurl.com/ow5d) that supposedly borrows heavily from
> org.apache.velocity.tools.view.servlet.WebappLoader.  I'd rather just
> use the one in Velocity, but I can't seem to get it to work.  The one in
> Roller is initialized with one simple call:
> WebappResourceLoader.setServletContext(pageContext.getServletContext());

that's a shame.  but just telling us "i can't get it to work" doesn't help us
help you.  you're practically begging to be referred to the "How to Ask Smart
Questions" document here.  :)

now, if you couldn't get to the WebappLoader to work, then why wasn't this
your first question?  if you are using Roller's derivative of the
WebappLoader, then ask them about your loader issues.

also, why are you telling us how the Roller one works? how is that relevant
here? if you're having trouble with our WebappLoader, you should tell us how
you are trying to use our WebappLoader, not theirs.  a suggestion:  look at
how the VelocityViewServlet (in the VelocityTools' CVS or source distribution)
uses the WebappLoader for an example of how to make it work.

Nathan Bubna
nathan@esha.com