ResourceManager : unable to find resource 'emailTemplate.vm' in any resource loader

30,681

Solution 1

You are falling into a common pitfall when using velocity with spring : you place your templates in one location and use a resource loader that searches them in another place. So you have 2 common usages :

  • put templates in classpath (as you do) and use ClasspathResourceLoader

    resource.loader = class
    class.resource.loader.class = org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader
    

    it is simple with little dependencies, but it forces you to put templates in classpath ...

  • put templates under WEB-INF (as you would do for JSPs) and use WebappResourceLoader from velocity tools

    resource.loader=webapp
    webapp.resource.loader.class=org.apache.velocity.tools.view.WebappResourceLoader
    webapp.resource.loader.path=/WEB-INF/velocity/
    

    it is more natural for a template location, but you add a dependency on velocity tools.

And let spring manage dependencies but not instanciating via new ...

Solution 2

I had the same problem recently with karaf OSGi framework. In a CXF resource class (Login in this context) you have to initialize the Velocity Engine like this:

public Login() {
    /*  first, get and initialize an engine  */
    ve = new VelocityEngine();        
    ve.setProperty(RuntimeConstants.RESOURCE_LOADER, "classpath");
    ve.setProperty("classpath.resource.loader.class", ClasspathResourceLoader.class.getName());
    ve.init();
}

Then, in the web method, instantiate the template:

    /*  create a context and add data */
    synchronized (initLock) {
        if (loginTemplate == null) {
            loginTemplate = ve.getTemplate("templates/login.vm");
        }
    }
    VelocityContext context = new VelocityContext();

Unfortunately, it didn't work out to load the template immediately after the ve.init() call in the constructor.

Share:
30,681
user3691501
Author by

user3691501

Updated on July 09, 2022

Comments

  • user3691501
    user3691501 almost 2 years

    I am doing an application in springs with maven. i wrote all properties in app.properties file

    file structure is like this

                             src/main/resource
    
                                 |_
                                 |   templates
                                 |        |_mytempaltefile.vm    
                                 |_ app.properties         
    

    i gave the path(absloute) in app.property

    app.properties file

    template.base.path=D\:/SVN/trunk/tfbdirect/src/main/resources/templates
    

    utilities-spring.xml

    <bean id="velocityEngine"
        class="org.springframework.ui.velocity.VelocityEngineFactoryBean">
        <property name="velocityProperties">
            <props>
                <prop key="resource.loader">file</prop>
                <prop key="file.resource.loader.class">
                    org.apache.velocity.runtime.resource.loader.FileResourceLoader
                </prop>
                <prop key="file.resource.loader.path">${template.base.path}</prop>
                <prop key="file.resource.loader.cache">false</prop>
            </props>
           </property>
    </bean>
    

    my class

     import java.util.HashMap;
     import java.util.Map;
     import org.apache.velocity.app.VelocityEngine;
     import org.springframework.ui.velocity.VelocityEngineUtils;
     import com.providerpay.tfbdirect.service.mail.MailSenderService;
    
     public class LoginServiceImpl implements ILoginService{
    
    /**
     * Injected through Spring IOC
     */
    ILoginDAO loginDAO;
    ClaimRuleProcessServiceImpl claimRuleProcessServiceImpl;
    PlatformTransactionManager txmanager;
    
    //IForgotPasswordDAO forgotPasswordDAO;
    
    private VelocityEngine velocityEngine;
    
    private String appURL;
    private MailSenderService mailSenderService;
    
    
    
    
    TFBLogger log = TFBLoggerFactory.getLogger(RuleServer.class);
    
    
    
    public String getAppURL() {
        return appURL;
    }
    
    public void setAppURL(String appURL) {
        this.appURL = appURL;
    }
    
    public MailSenderService getMailSenderService() {
        return mailSenderService;
    }
    
    public VelocityEngine getVelocityEngine() {
        return velocityEngine;
    }
    
    
    public void setVelocityEngine(VelocityEngine velocityEngine) {
        this.velocityEngine = velocityEngine;
    }
    
    public void setMailSenderService(MailSenderService mailSenderService) {
        this.mailSenderService = mailSenderService;
    }
    
    public ILoginDAO getLoginDAO() {
        return loginDAO;
    }
    public void setLoginDAO(ILoginDAO loginDAO) {
        this.loginDAO = loginDAO;
    }
    public ClaimRuleProcessServiceImpl getClaimRuleProcessServiceImpl() {
        return claimRuleProcessServiceImpl;
    }
    public void setClaimRuleProcessServiceImpl(
            ClaimRuleProcessServiceImpl claimRuleProcessServiceImpl) {
        this.claimRuleProcessServiceImpl = claimRuleProcessServiceImpl;
    }   
    public void setTxmanager(PlatformTransactionManager txmanager) {
        this.txmanager = txmanager;
    }
    
    
    
    /**
     * Validates Login
     * @param loginView
     * @return
     */
    public boolean isValidLogin(LoginView loginView) {
    
        /* create tx definition object */
        DefaultTransactionDefinition paramTransactionDefinition = new     DefaultTransactionDefinition();
        TransactionStatus status = txmanager.getTransaction(paramTransactionDefinition );
        boolean result = false;
    
        try{
            LoginEntity loginEntity = BeanMapper.INSTANCE.viewToEntityMapper(loginView);
            Feedback feedback = claimRuleProcessServiceImpl.validateClaimEligibility(loginEntity);
            log.info( "Rule executed was " +feedback.getAll());
    
            for (FeedbackMessage feedbackmessaage :feedback.getAll())
            {
                log.info("\n--------------");
                log.info(feedbackmessaage.getRuleCd());
                log.info(feedbackmessaage.getMessage());
                log.info(feedbackmessaage.getSeverity().getName());
                log.info("\n--------------");
            }
    
            result = loginDAO.isValidLogin(loginEntity);
            log.debug("result = {}", result);
    
            txmanager.commit(status);
    
        }catch(Exception e){
            txmanager.rollback(status);
            throw new TfbException("Error occured while validating login credentials");
        }
    
        return result; 
    }
    
    
    
    
    @Autowired
    VelocityEngine velocityengine;
    public boolean mailResetLink(LoginView loginView) {
    
        String toEmailAddress;
        LoginEntity loginEntity = BeanMapper.INSTANCE.viewToEntityMapper(loginView);
    
        /* getting user Email from DAO*/
        toEmailAddress = loginDAO.getEmailByUsername(loginEntity);
    
        if(toEmailAddress != null && toEmailAddress.trim().length() > 0)
        {
            Map<String, Object> model = new HashMap<String, Object>();
            model.put("user", loginEntity);
            model.put("appURL", appURL);
            String body = VelocityEngineUtils.mergeTemplateIntoString(velocityEngine, "emailTemplate.vm","UTF-8", model);
    
            mailSenderService.sendMail("from mail", toEmailAddress, "Password Reset Link",body);
    
    
        }
        else
        {
            return false;
        }
        return true;
    }
    
    public boolean resetPassword(LoginView loginView) 
    {
    
        LoginEntity loginEntity = BeanMapper.INSTANCE.viewToEntityMapper(loginView);
    
        return loginDAO.resetPassword(loginEntity);
    }
    }
    

    every thing fine but i need to change the absolute path to relative path.. i tried many ways.

    i tried like following

    template.base.path=/templates/
    

    but still getting below error .

    ResourceManager : unable to find resource 'emailTemplate.vm' in any resource loader.

    can any one help me..

    Thanks in advance

  • Serge Ballesta
    Serge Ballesta almost 10 years
    If using spring, avoid instanciating by new beans that should be injected in other beans or which should receive other beans by spring IOC because it will not work ...
  • user3691501
    user3691501 almost 10 years
    Hi serge i added the code what you told top of the method but i am getting the same error only @Autowired VelocityEngine velocityEngine;
  • Torsten N.
    Torsten N. about 8 years
    When using either option with Spring Boot, would you put these configurations into application.properties? I'm having trouble getting any class loader to work, doesn't seem to matter which folder I put my templates in.
  • ZhaoGang
    ZhaoGang almost 4 years
    how to config that in a yaml config file?