Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the correct way to get a template in FTL/spring when not in a web Servlet

We are currently using a sync. web call to send emails. This was done as a quick fix to prove out some basic functionality, but now we need to send the e-mails async. I have the everything pretty much reworked to queue up jobs and then send the emails, but I've run in to one issue. We use FTL for our email templates and before we were passing the servlet context to FTL to get the template folder. Since we are now doing this in a queued job that get's processed by a Spring @Scheduled job, we no longer have access to the web servlet. I've been researching and playing around for awhile now, but I haven't seem to come up with a way that will actually work.

I have a feeling there is some super simple way to get

The code that did the work before looked similar to this:

@PUT
@Produces(MediaType.APPLICATION_JSON)
@Path("someStuffHere")
@Transactional
public function someWebServiceCall(@Context javax.servlet.http.HttpServletRequest req)
{
    SomeStuff foo = gotSomeStuff();
    sendEmail(req.getServlet(), foo);
}

public sendEmail(Servlet context, SomeStuff foo) //<-- lives in another class somewhere, just showing how FTL uses the servlet
{
    Configuration cfg = new Configuration();
    cfg.setServletContextForTemplateLoading(context,"communicationTemplates/email");
}

The new code now looks something like this:

public class someClass
{
    @Autowired
    private SomeRepo someRepo;
@Scheduled(cron = "* */2 * * * ?")
    public void sendAnyOutstandingStuffEmails()
    {
        SomeStuff foo = someRepo.getStuff();
        sendEmail(/*how to get context, or a resource so FTL can get the template folder*/, foo)
    }
like image 263
Zipper Avatar asked Jan 31 '26 12:01

Zipper


1 Answers

Even though this post is quite old and the author has given another solution a try, it is not necessary to have a servlet context instance in order to load templates. The freemarker documentation states:

Built-in template loaders

You can set up three template loading methods in the Configuration using the following convenience methods. (Each method will create a template loader object internally and set up the Configuration instance to use that.)

void setDirectoryForTemplateLoading(File dir);   

or

void setClassForTemplateLoading(Class cl, String prefix);   

or

void setServletContextForTemplateLoading(Object servletContext, String path);

http://freemarker.org/docs/pgui_config_templateloading.html

So in this case it should have been possible to configure freemarker to use the ClassLoader (option 2) by naming a class that is on the same level as the templates or to use this class as root node for navigating to the template using relative paths.

like image 97
Florian Avatar answered Feb 02 '26 02:02

Florian



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!