3 Replies Latest reply on Jan 19, 2006 7:53 AM by jbaker_softcomms

    ClassLoading problems

    ereze

      Hi all,

      In my efforts to work work with velocity to generate tempalted emails,
      I got stuck with the classLoading problems, which I don't seem to pass.

      I get the followig error:

      " Unable to find resource 'resources.UserLoginInfo.vm' "

      I tried a more general test to just load a simple properties file
      and failed too...

       ClassLoader classLoader = this.getClass().getClassLoader();
      InputStream istream = classLoader.getResourceAsStream("resources.application.properties");
      


      Note: the resource name is with a dot "." resource.application.propperties.
      Now, it's strange cause the struts modules picks it up without any problem. Though here I called these lines from a method in one of my EJB entities. Anyway, in return I get null.

      My application is contains the Logic (and EJB module) and Web (web module). the UserLoginInfo.vm is located under the resources directory.

      Here is my Emailer.java:

      Code:

      /**
       * A utility class that provides API for sending
       * templated emails per application use case.
       * <p>The <code>Emailer</code> uses Velocity SDK to generate
       * the templated emails.
       *
       * @author Erez Efrati
       * @version $Revision:$ $Date:$
       */
      public class Emailer {
      
       /**
       * JNDI context for JavaMail sessions.
       */
       private static final String JNDI_JAVA_MAIL = "java:/Mail";
      
       /**
       * The content type of the HTML email messages.
       */
       private static final String HTML_CONTENT_TYPE = "text/html;charset=UTF-8";
      
       /**
       * The user-login-info email template resource name.
       */
       private static final String VM_USER_LOGIN_INFO_REMINDER
       = "resources.UserLoginInfo.vm";
      
       // Velocity variable names keys
       private static final String VMVAR_USER = "user";
       private static final String VMVAR_SUBJECT = "subject";
      
       /**
       * the engine instance
       */
       VelocityEngine m_engine = new VelocityEngine ();
      
       // ------------------------------------------------------ Private Methods
      
      
       /**
       * Configures the engine to use classpath to find templates
       *
       * @param engine the engine to configure
       * @throws Exception thrown if an errors occures
       */
       private void configure (VelocityEngine engine) throws Exception
       {
       Properties props = new Properties ();
       props.setProperty (VelocityEngine.RESOURCE_LOADER, "classpath");
       props.setProperty ("classpath." + VelocityEngine.RESOURCE_LOADER + ".class",
       ClasspathResourceLoader.class.getName());
       m_engine.init (props);
       }
      
      
       /**
       * Creates a Velocity context
       */
       private VelocityContext createContext()
       {
       VelocityContext ctx = new VelocityContext ();
       return ctx;
       }
      
       /**
       * Retreives a new JavaMail Mime message
       *
       * @return
       * @throws NamingException
       */
       private MimeMessage createMimeMessage() throws NamingException
       {
       Context initCtx = new InitialContext ();
       Session session = (Session)initCtx.lookup (JNDI_JAVA_MAIL);
       MimeMessage message = new MimeMessage (session);
       return message;
       }
      
       // ------------------------------------------------------ Public Methods
      
       /**
       * Default constructor, configures the velocity engine.
       *
       * @throws Exception, if an error occures
       */
       public Emailer () throws Exception
       {
       configure (m_engine);
       }
      
      
       /**
       * Sends an email to the specified <code>user</code> containing
       * his login information which includes his username and password.
       *
       * @param user
       * @throws Exception
       */
       public void sendUserLoginInfo (User user) throws Exception
       {
       // retrieve the email template
       Template template = m_engine.getTemplate (VM_USER_LOGIN_INFO_REMINDER);
      
       // prepare the context and store data objects in it
       VelocityContext ctx = createContext ();
       ctx.put (VMVAR_USER, user);
      
       // merge the template
       StringWriter writer = new StringWriter ();
       template.merge (ctx, writer);
       writer.close ();
      
       // retrieve the message subject and text. The subject
       // is formulated as part of the email velocity template.
       StringBuffer text = writer.getBuffer();
       String subject = (String)ctx.get (VMVAR_SUBJECT);
      
       // create a new message to work with
       MimeMessage message = createMimeMessage ();
      
       // retrieve the user's email address
       String to = user.getEmail ();
      
       String from = App.getSupportEmailAddress ();
       message.setFrom (new InternetAddress (from));
       message.addRecipient (Message.RecipientType.TO,
       new InternetAddress (to));
      
       // set the subject and content
       message.setSubject (subject);
       message.setContent (text, HTML_CONTENT_TYPE);
      
       // Send message
       Transport.send (message);
      
       }
      
      





      Why doesn't it work? What am I missing?

      One more thing I maybe should point out as well - The emailer
      is called from my 'UserServiceBean' which is a stateless Session bean.
      I hope this is valid, is it?

      I would really appreciate any help here.

      Thanks in advance,

      Erez


        • 1. Re: ClassLoading problems
          jae77

          when you create your deployment archive, where does that file exist?

          is it at the root level, is it in a sub-directory? if it's in a sub-directory, you need to specify that as part of the resource's location.

          ie: if the file lived in "lib", you would have to say

          ClassLoader classLoader = this.getClass().getClassLoader();
          InputStream istream = classLoader.getResourceAsStream("lib/resources.application.properties");
          


          • 2. Re: ClassLoading problems
            jbaker_softcomms

            Did this ever get resolved?

            I am having what I think is a similar problem. I have my template somewhere it should load. I believe it should as other properties files get loaded fine. However, I believe the difference is that the properties are loaded via the context class loader but I can't see a way to configure velocity to use this which I know works from an EJB inside jBoss.

            • 3. Re: ClassLoading problems
              jbaker_softcomms

              Found the solution.

              I created another resource loader that uses the context classloader that jboss likes then configured velocity to use my loader. I simply copied velocity's ClassPathResourceLoader and changed the line

              ClassLoader classLoader = this.getClass().getClassLoader();

              to

              ClassLoader classLoader = Thread.currentThread().getContextClassLoader()

              All is fine now.. can find templates inside the EJB jar.