CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-springframework--spring-context-support

Spring Framework integration support for caching (Caffeine, JCache), mail (JavaMail), scheduling (Quartz), and template engines (FreeMarker)

Pending
Overview
Eval results
Files

templates.mddocs/

FreeMarker Templates

Spring Context Support provides comprehensive FreeMarker template engine integration for server-side rendering. It offers factory beans for configuration, utilities for template processing, and Spring Resource-based template loading for both web and non-web contexts.

Capabilities

FreeMarker Configuration Factory

Factory for creating and configuring FreeMarker Configuration instances with Spring integration.

/**
 * Factory for creating FreeMarker Configuration instances with Spring integration
 */
public class FreeMarkerConfigurationFactory {
    
    /**
     * Set the location of the FreeMarker config file
     * @param resource the config file resource
     */
    public void setConfigLocation(Resource resource);
    
    /**
     * Set FreeMarker settings as Properties
     * @param settings the FreeMarker settings
     */
    public void setFreemarkerSettings(Properties settings);
    
    /**
     * Set FreeMarker variables (objects available in all templates)
     * @param variables map of variable names to objects
     */
    public void setFreemarkerVariables(Map<String, Object> variables);
    
    /**
     * Set the default encoding for templates
     * @param defaultEncoding the default encoding (e.g., "UTF-8")
     */
    public void setDefaultEncoding(String defaultEncoding);
    
    /**
     * Set the default charset for templates
     * @param defaultCharset the default charset
     */
    public void setDefaultCharset(Charset defaultCharset);
    
    /**
     * Set template loaders that will be used before default loaders
     * @param preTemplateLoaders template loaders to register first
     */
    public void setPreTemplateLoaders(TemplateLoader... preTemplateLoaders);
    
    /**
     * Set template loaders that will be used after default loaders
     * @param postTemplateLoaders template loaders to register last
     */
    public void setPostTemplateLoaders(TemplateLoader... postTemplateLoaders);
    
    /**
     * Set the template loader path (single path)
     * @param templateLoaderPath the template loader path
     */
    public void setTemplateLoaderPath(String templateLoaderPath);
    
    /**
     * Set multiple template loader paths
     * @param templateLoaderPaths array of template loader paths
     */
    public void setTemplateLoaderPaths(String... templateLoaderPaths);
    
    /**
     * Set the ResourceLoader for template loading
     * @param resourceLoader the ResourceLoader to use
     */
    public void setResourceLoader(ResourceLoader resourceLoader);
    
    /**
     * Set whether to prefer file system access for template loading
     * @param preferFileSystemAccess whether to prefer file system access
     */
    public void setPreferFileSystemAccess(boolean preferFileSystemAccess);
    
    /**
     * Create the FreeMarker Configuration instance
     * @return the configured Configuration
     * @throws IOException if configuration fails
     * @throws TemplateException if template configuration fails
     */
    public Configuration createConfiguration() throws IOException, TemplateException;
    
    /**
     * Get the ResourceLoader (available after ApplicationContext injection)
     * @return the ResourceLoader
     */
    protected ResourceLoader getResourceLoader();
}

Usage Examples:

@Configuration
public class FreeMarkerConfig {
    
    @Bean
    public FreeMarkerConfigurationFactory freeMarkerConfigurationFactory() {
        FreeMarkerConfigurationFactory factory = new FreeMarkerConfigurationFactory();
        factory.setTemplateLoaderPaths(
            "classpath:/templates/",
            "file:/opt/app/templates/"
        );
        factory.setDefaultEncoding("UTF-8");
        
        Properties settings = new Properties();
        settings.setProperty("number_format", "0.##");
        settings.setProperty("date_format", "yyyy-MM-dd");
        settings.setProperty("time_format", "HH:mm:ss");
        settings.setProperty("datetime_format", "yyyy-MM-dd HH:mm:ss");
        factory.setFreemarkerSettings(settings);
        
        // Global variables available in all templates
        Map<String, Object> variables = new HashMap<>();
        variables.put("app", applicationProperties);
        variables.put("utils", templateUtils);
        factory.setFreemarkerVariables(variables);
        
        return factory;
    }
    
    @Bean
    public Configuration freeMarkerConfiguration() throws Exception {
        return freeMarkerConfigurationFactory().createConfiguration();
    }
}

FreeMarker Configuration Factory Bean

FactoryBean wrapper around FreeMarkerConfigurationFactory for easier Spring integration.

/**
 * FactoryBean wrapper around FreeMarkerConfigurationFactory
 */
public class FreeMarkerConfigurationFactoryBean extends FreeMarkerConfigurationFactory 
        implements FactoryBean<Configuration>, InitializingBean, ResourceLoaderAware {
    
    /**
     * Get the FreeMarker Configuration instance
     * @return the Configuration instance
     * @throws Exception if creation fails
     */
    @Override
    public Configuration getObject() throws Exception;
    
    /**
     * Get the object type
     * @return Configuration.class
     */
    @Override
    public Class<Configuration> getObjectType();
    
    /**
     * Check if this factory returns singletons
     * @return true (singleton)
     */
    @Override
    public boolean isSingleton();
    
    /**
     * Initialize the factory bean
     * @throws IOException if initialization fails
     * @throws TemplateException if template configuration fails
     */
    @Override
    public void afterPropertiesSet() throws IOException, TemplateException;
    
    /**
     * Set the ResourceLoader for template loading
     * @param resourceLoader the ResourceLoader
     */
    @Override
    public void setResourceLoader(ResourceLoader resourceLoader);
}

Usage Examples:

@Configuration
public class FreeMarkerFactoryBeanConfig {
    
    @Bean
    public FreeMarkerConfigurationFactoryBean freeMarkerConfigurationFactoryBean() {
        FreeMarkerConfigurationFactoryBean factoryBean = new FreeMarkerConfigurationFactoryBean();
        factoryBean.setTemplateLoaderPath("classpath:/templates/");
        factoryBean.setDefaultEncoding("UTF-8");
        
        Properties settings = new Properties();
        settings.setProperty("template_update_delay", "0"); // Development setting
        settings.setProperty("default_encoding", "UTF-8");
        settings.setProperty("output_encoding", "UTF-8");
        settings.setProperty("locale", "en_US");
        factoryBean.setFreemarkerSettings(settings);
        
        return factoryBean;
    }
}

Template Processing Utilities

Utility methods for processing FreeMarker templates in various contexts.

/**
 * Utility methods for processing FreeMarker templates
 */
public abstract class FreeMarkerTemplateUtils {
    
    /**
     * Process a FreeMarker template into a String
     * @param template the FreeMarker Template
     * @param model the template model (data)
     * @return the processed template as String
     * @throws IOException if template processing fails
     * @throws TemplateException if template has errors
     */
    public static String processTemplateIntoString(Template template, Object model) 
            throws IOException, TemplateException;
}

Usage Examples:

@Service
public class ReportService {
    
    @Autowired
    private Configuration freeMarkerConfiguration;
    
    public String generateReport(String templateName, Map<String, Object> data) {
        try {
            Template template = freeMarkerConfiguration.getTemplate(templateName + ".ftl");
            return FreeMarkerTemplateUtils.processTemplateIntoString(template, data);
        } catch (IOException | TemplateException e) {
            throw new RuntimeException("Failed to generate report", e);
        }
    }
    
    public String generateLocalizedReport(String templateName, Map<String, Object> data, Locale locale) {
        try {
            Template template = freeMarkerConfiguration.getTemplate(templateName + ".ftl", locale);
            return FreeMarkerTemplateUtils.processTemplateIntoString(template, data);
        } catch (IOException | TemplateException e) {
            throw new RuntimeException("Failed to generate localized report", e);
        }
    }
}

@RestController
public class TemplateController {
    
    @Autowired
    private ReportService reportService;
    
    @GetMapping("/reports/{type}")
    public ResponseEntity<String> generateReport(@PathVariable String type) {
        Map<String, Object> data = new HashMap<>();
        data.put("reportDate", new Date());
        data.put("title", "Monthly Report");
        data.put("items", getReportItems());
        
        String html = reportService.generateReport(type, data);
        
        return ResponseEntity.ok()
            .contentType(MediaType.TEXT_HTML)
            .body(html);
    }
}

Spring Template Loader

FreeMarker TemplateLoader implementation that loads templates from Spring Resource locations.

/**
 * FreeMarker TemplateLoader that loads templates from Spring Resource locations
 */
public class SpringTemplateLoader implements TemplateLoader {
    
    /**
     * Create a SpringTemplateLoader with a ResourceLoader and template path
     * @param resourceLoader the ResourceLoader to use
     * @param templateLoaderPath the base path for templates
     */
    public SpringTemplateLoader(ResourceLoader resourceLoader, String templateLoaderPath);
    
    /**
     * Find a template source
     * @param name the template name
     * @return the template source object
     * @throws IOException if template loading fails
     */
    @Override
    public Object findTemplateSource(String name) throws IOException;
    
    /**
     * Get the last modified time of a template
     * @param templateSource the template source
     * @return the last modified time
     */
    @Override
    public long getLastModified(Object templateSource);
    
    /**
     * Get a Reader for the template content
     * @param templateSource the template source
     * @param encoding the character encoding
     * @return a Reader for the template
     * @throws IOException if reading fails
     */
    @Override
    public Reader getReader(Object templateSource, String encoding) throws IOException;
    
    /**
     * Close a template source
     * @param templateSource the template source to close
     * @throws IOException if closing fails
     */
    @Override
    public void closeTemplateSource(Object templateSource) throws IOException;
}

Advanced Configuration Examples

Complete configuration examples for different use cases.

@Configuration
public class AdvancedFreeMarkerConfig {
    
    /**
     * Configuration for web applications with multiple template locations
     */
    @Bean
    @Profile("web")
    public FreeMarkerConfigurationFactoryBean webFreeMarkerConfig() {
        FreeMarkerConfigurationFactoryBean factoryBean = new FreeMarkerConfigurationFactoryBean();
        
        // Multiple template locations
        factoryBean.setTemplateLoaderPaths(
            "classpath:/templates/",           // Built-in templates
            "classpath:/templates/mail/",      // Email templates
            "file:/opt/app/custom-templates/"  // Custom templates
        );
        
        factoryBean.setDefaultEncoding("UTF-8");
        factoryBean.setPreferFileSystemAccess(false); // For WAR deployment
        
        Properties settings = new Properties();
        // Development settings
        settings.setProperty("template_update_delay", "0");
        settings.setProperty("template_exception_handler", "html_debug");
        // Production settings would use:
        // settings.setProperty("template_update_delay", "60000");
        // settings.setProperty("template_exception_handler", "ignore");
        
        settings.setProperty("default_encoding", "UTF-8");
        settings.setProperty("output_encoding", "UTF-8");
        settings.setProperty("auto_flush", "true");
        settings.setProperty("url_escaping_charset", "UTF-8");
        
        factoryBean.setFreemarkerSettings(settings);
        
        // Global variables
        Map<String, Object> variables = new HashMap<>();
        variables.put("contextPath", "${request.contextPath}");
        variables.put("springMacroRequestContext", new RequestContextHashModel());
        factoryBean.setFreemarkerVariables(variables);
        
        return factoryBean;
    }
    
    /**
     * Configuration for standalone/batch applications
     */
    @Bean
    @Profile("batch")
    public FreeMarkerConfigurationFactoryBean batchFreeMarkerConfig() {
        FreeMarkerConfigurationFactoryBean factoryBean = new FreeMarkerConfigurationFactoryBean();
        
        factoryBean.setTemplateLoaderPaths(
            "classpath:/batch-templates/",
            "file:/data/templates/"
        );
        
        factoryBean.setDefaultEncoding("UTF-8");
        factoryBean.setPreferFileSystemAccess(true); // Better performance for file system
        
        Properties settings = new Properties();
        settings.setProperty("template_update_delay", "300000"); // 5 minutes
        settings.setProperty("template_exception_handler", "rethrow");
        settings.setProperty("arithmetic_engine", "bigdecimal");
        settings.setProperty("number_format", "0.####");
        settings.setProperty("boolean_format", "yes,no");
        
        factoryBean.setFreemarkerSettings(settings);
        
        return factoryBean;
    }
    
    /**
     * Service for template-based document generation
     */
    @Service
    public static class DocumentGenerationService {
        
        @Autowired
        private Configuration freeMarkerConfiguration;
        
        public void generateDocument(String templateName, Map<String, Object> data, OutputStream output) 
                throws IOException, TemplateException {
            
            Template template = freeMarkerConfiguration.getTemplate(templateName);
            
            try (Writer writer = new OutputStreamWriter(output, StandardCharsets.UTF_8)) {
                template.process(data, writer);
                writer.flush();
            }
        }
        
        public void generatePdfReport(String templateName, Map<String, Object> data, String outputPath) 
                throws IOException, TemplateException {
            
            // Generate HTML from template
            String html = generateHtmlFromTemplate(templateName, data);
            
            // Convert to PDF (using a library like Flying Saucer or similar)
            convertHtmlToPdf(html, outputPath);
        }
        
        private String generateHtmlFromTemplate(String templateName, Map<String, Object> data) 
                throws IOException, TemplateException {
            
            Template template = freeMarkerConfiguration.getTemplate(templateName);
            return FreeMarkerTemplateUtils.processTemplateIntoString(template, data);
        }
    }
}

Template Context Integration

Integration with Spring's web context and request handling.

/**
 * Utility methods for integrating FreeMarker with Spring web contexts
 */
public abstract class RequestContextUtils {
    
    /**
     * Get the current request context for use in templates
     * @param request the HTTP request
     * @param response the HTTP response  
     * @param servletContext the servlet context
     * @return RequestContext for template use
     */
    public static RequestContext getRequestContext(HttpServletRequest request, 
            HttpServletResponse response, ServletContext servletContext);
}

/**
 * Hash model for exposing Spring RequestContext in FreeMarker templates
 */
public class RequestContextHashModel implements TemplateHashModel {
    
    /**
     * Create a RequestContextHashModel for the current request
     */
    public RequestContextHashModel();
    
    /**
     * Create a RequestContextHashModel for a specific request
     * @param request the HTTP request
     * @param response the HTTP response
     */
    public RequestContextHashModel(HttpServletRequest request, HttpServletResponse response);
    
    @Override
    public TemplateModel get(String key) throws TemplateModelException;
    
    @Override
    public boolean isEmpty() throws TemplateModelException;
}

Integration with Spring Boot

For Spring Boot applications, FreeMarker auto-configuration is available:

spring:
  freemarker:
    template-loader-path: classpath:/templates/
    suffix: .ftl
    cache: true
    charset: UTF-8
    check-template-location: true
    content-type: text/html
    expose-request-attributes: false
    expose-session-attributes: false
    expose-spring-macro-helpers: true
    prefer-file-system-access: true
    settings:
      template_update_delay: 0
      default_encoding: UTF-8
      output_encoding: UTF-8
      locale: en_US
      date_format: yyyy-MM-dd
      time_format: HH:mm:ss
      datetime_format: yyyy-MM-dd HH:mm:ss

The Spring Context Support FreeMarker integration provides the foundation for this auto-configuration and can be used directly in non-Boot applications or for advanced customization scenarios.

Install with Tessl CLI

npx tessl i tessl/maven-org-springframework--spring-context-support

docs

caching.md

index.md

mail.md

scheduling.md

templates.md

tile.json