[ 
https://issues.apache.org/jira/browse/VELOCITY-817?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16016428#comment-16016428
 ] 

Mark S commented on VELOCITY-817:
---------------------------------

To give you a couple of possible use case examples
* A system user configures a custom email alert that will be sent to an email 
list.
* A system user sends an email to to a customer list using 5 different email 
templates which are dynamically chosen depending on the customer profile.
* A system user has an online store and configures a custom welcome message 
depending on a customer profile and context.

Also, while it has been over 5 years since I contributed this code, I am pretty 
sure that the cache size is set with the following command.
{code}
  p.setProperty( RuntimeConstants.RESOURCE_MANAGER_DEFAULTCACHE_SIZE, "100" );
{code}

> Dynamic Templates with Caching
> ------------------------------
>
>                 Key: VELOCITY-817
>                 URL: https://issues.apache.org/jira/browse/VELOCITY-817
>             Project: Velocity
>          Issue Type: Improvement
>          Components: Engine
>    Affects Versions: 1.7
>            Reporter: Mark S
>              Labels: performance
>   Original Estimate: 2h
>  Remaining Estimate: 2h
>
> I thought I would share the following code with the Apache Velocity community.
> Problem Description:  I wanted to use Dynamic Templates though I found the 
> following had massive performance implications.
> {code:title=Velocity Call Snippet|borderStyle=solid}
> String template = "message.to:  $\{message.to} ";
> StringWriter velocityWriter = new StringWriter();
> velocityEngine.evaluate( velocityContext, velocityWriter, "LOG", template );
> return velocityWriter.toString();
> {code}
> As such, I needed an alternate solution and guessed that if I could cache the 
> Velocity templates used I could see big performance gains.
> I initially looked to the 
> org.apache.velocity.runtime.resource.loader.StringResourceLoader class to 
> solve my problems.   The StringResourceLoader class requires an instance of 
> the StringResourceRepository class, and the only implementation of 
> StringResourceRepository is StringResourceRepositoryImpl.  Unfortunately, 
> since the number of unique templates will grow over time, in time the 
> StringResourceRepositoryImpl.resources Map will cause an out of memory error.
> Why doesn't StringResourceRepositoryImpl use a cache with a maximum size?  Is 
> a cache even needed as the Velocity ResourceCacheImpl will cache Templates?
> +++++++++++++++++++++++++++++++++++++
> In the end I settled on the following solution.  From my tests using YourKit 
> Java Profiler I invoked the static Velocity wrapping method 100,000 times, 
> and discovered a performance difference of around 75 fold (146,937ms vs 
> 1,981ms).
> Below is my solution.  Feedback appreciated.
> +++++++++++++++++++++++++++++++++++++ 
> {code:title=Velocity Engine Setup Snippet|borderStyle=solid}
> Properties p = new Properties();
> p.setProperty( RuntimeConstants.INPUT_ENCODING, DEFAULT_ENCODING );
> p.setProperty( RuntimeConstants.OUTPUT_ENCODING, DEFAULT_ENCODING );
> p.setProperty( RuntimeConstants.RESOURCE_MANAGER_CLASS,
>        "org.apache.velocity.runtime.resource.ResourceManagerImpl" );
> p.setProperty( RuntimeConstants.RESOURCE_MANAGER_CACHE_CLASS,
>        "org.apache.velocity.runtime.resource.ResourceCacheImpl" );
> p.setProperty( RuntimeConstants.RESOURCE_MANAGER_DEFAULTCACHE_SIZE, "100" );
> p.setProperty( RuntimeConstants.RESOURCE_LOADER, "string" );
> p.setProperty( "string.resource.loader.class",
>        "custom.SimpleStringResourceLoader" );
> p.setProperty( "string.resource.loader.encoding", DEFAULT_ENCODING );
> p.setProperty( "string.resource.loader.cache", Boolean.TRUE.toString() );
> p.setProperty( "string.resource.loader.modificationCheckInterval", "-1" );
> VelocityEngine engine = new VelocityEngine( p );
> engine.init();
> {code}
> {code:title=Velocity Call Snippet|borderStyle=solid}
> String template = "message.to:  ${message.to} ";
> StringWriter velocityWriter = new StringWriter();
> Template veTemplate = velocityEngine.getTemplate( template );
> veTemplate.merge( velocityContext, velocityWriter );
> return velocityWriter.toString();
> {code}
> {code:title=Velocity Supporting Class Snippet|borderStyle=solid}
> package custom;
> import java.io.ByteArrayInputStream;
> import java.io.InputStream;
> import java.io.UnsupportedEncodingException;
> import java.util.concurrent.atomic.AtomicLong;
> import org.apache.commons.collections.ExtendedProperties;
> import org.apache.velocity.exception.VelocityException;
> import org.apache.velocity.runtime.resource.Resource;
> import org.apache.velocity.runtime.resource.loader.ResourceLoader;
> import org.apache.velocity.runtime.resource.util.StringResource;
> public class SimpleStringResourceLoader extends ResourceLoader
> {
>     protected static int classMetricsLevel;
>     protected static AtomicLong totalClassInstancesCreatedCount;
>     protected static AtomicLong totalStringsGeneratedCount;
>     static {
>         classMetricsLevel = 1;
>         totalClassInstancesCreatedCount = new AtomicLong();
>         totalStringsGeneratedCount = new AtomicLong();
>     }
>     protected String encoding;
>     public SimpleStringResourceLoader()
>     {
>         if ( classMetricsLevel > 0 )
>         {
>             totalClassInstancesCreatedCount.incrementAndGet();
>         }
>         this.encoding = "UTF-8";
>     }
>     @Override
>     public void init( ExtendedProperties paramExtendedProperties )
>     {
>         String paramEncoding = paramExtendedProperties.getString( "encoding" 
> );
>         if ( null != encoding && encoding.trim().length() > 0 )
>         {
>             this.encoding = paramEncoding;
>         }
>     }
>     @Override
>     public InputStream getResourceStream( String contents )
>     {
>         if ( classMetricsLevel > 1 )
>         {
>             totalStringsGeneratedCount.incrementAndGet();
>         }
>         StringResource resource = new StringResource( contents, encoding );
>         byte[] byteArray = null;
>         try
>         {
>             byteArray = resource.getBody().getBytes( resource.getEncoding() );
>             return new ByteArrayInputStream( byteArray );
>         }
>         catch ( UnsupportedEncodingException ue )
>         {
>             throw new VelocityException( "Failed to convert contents to 
> String "
>                     + resource.getEncoding(), ue );
>         }
>     }
>     @SuppressWarnings( "unused" )
>     @Override
>     public boolean isSourceModified( Resource paramResource )
>     {
>         return false;
>     }
>     @SuppressWarnings( "unused" )
>     @Override
>     public long getLastModified( Resource paramResource )
>     {
>         return 0;
>     }
>     public String getEncoding()
>     {
>         return encoding;
>     }
>     public void setEncoding( String encoding )
>     {
>         this.encoding = encoding;
>     }
>     public static int getClassMetricsLevel()
>     {
>         return classMetricsLevel;
>     }
>     public static void setClassMetricsLevel( int classMetricsLevel )
>     {
>         SimpleStringResourceLoader.classMetricsLevel = classMetricsLevel;
>     }
>     public static void setTotalClassInstancesCreatedCount( long counterValue )
>     {
>         SimpleStringResourceLoader.totalClassInstancesCreatedCount.getAndSet( 
> counterValue );
>     }
>     public static long getTotalClassInstancesCreatedCount()
>     {
>         return 
> SimpleStringResourceLoader.totalClassInstancesCreatedCount.get();
>     }
>     public static void setTotalStringsGeneratedCount( long counterValue )
>     {
>         SimpleStringResourceLoader.totalStringsGeneratedCount.getAndSet( 
> counterValue );
>     }
>     public static long getTotalStringsGeneratedCount()
>     {
>         return SimpleStringResourceLoader.totalStringsGeneratedCount.get();
>     }
>     @Override
>     public String toString()
>     {
>         return "SimpleStringResourceLoader [encoding=" + encoding + "]";
>     }
> }
> {code}



--
This message was sent by Atlassian JIRA
(v6.3.15#6346)

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@velocity.apache.org
For additional commands, e-mail: dev-h...@velocity.apache.org

Reply via email to