Combining GAE, Apache Velocity and JQuery

If some of the earlier posts I used jQuery ajax posts to change the appearance of the user page. In this blog post I’m using Velocity to generate the html pages server-side.

Getting velocity up and running
To get started I placed the velocity-1.6.3.jar in the WEB-INF\lib folder.
The first tries of getting everything up and running were not successful. GAE does not allow to load templates with the out of the box available resource loaders. So I had to create my own. Most of the code I got from here.

public class velocityResourceLoader extends ResourceLoader {
	private Vector<String> paths = null;

	@Override
	public long getLastModified(Resource arg0) {
		return arg0.getLastModified();
	}

	@Override
	public InputStream getResourceStream(String template) throws ResourceNotFoundException {
		int size = paths.size();
		for (int i = 0; i < size; i++) {
			String path = paths.get(i);

			InputStream is = null;
			try {
				is = new FileInputStream(path +"/"+ template);
				return is;
			} catch (FileNotFoundException e) {
				//skip
			}
		}
		throw new ResourceNotFoundException(template);
	}

	@Override
	public void init(ExtendedProperties configuration) {
		paths = configuration.getVector("path");
	}

	@Override
	public boolean isSourceModified(Resource arg0) {
		return false;
	}
}
 

The method getResourceStream takes the argument template and tries to find the template in the path variable, that must be filled using a property.

Initializing Velocity

Next I created a singleton to set up and store the VelocityEngine. In this singleton I also added a function to find a template.

public final class VelocityEngineManager {
	public static final Logger log = Logger.getLogger(VelocityEngineManager.class.getName());
	static VelocityEngine engine = new VelocityEngine();
	static boolean init = false;

	public static void init(){
		if (!init) {
			//engine = new VelocityEngine();
			engine.setProperty("resource.loader", "file");
			engine.setProperty("file.resource.loader.class","jvdkamp.example.velocity.velocityResourceLoader");
			engine.setProperty("file.resource.loader.path","templates");
			engine.setProperty( RuntimeConstants.RUNTIME_LOG_LOGSYSTEM_CLASS, "org.apache.velocity.runtime.log.Log4JLogChute" );
			engine.setProperty("runtime.log.logsystem.log4j.logger", log.getName());
			try {
				engine.init();
				init=true;
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

	public static Template getTemplate(String template){
		try {
			return engine.getTemplate( template );
		} catch (ResourceNotFoundException e) {
			e.printStackTrace();
		} catch (ParseErrorException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}

		return null;
	}
}

In the servlet the following code is needed to load a template, determine if a user is signed in and based on that choose a template to load.

using Velocity templates

	public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
		PrintWriter out = resp.getWriter();
		resp.setContentType("text/html");

		HttpSession session = req.getSession(true);
		User user = (User) session.getAttribute("user");
		VelocityContext context = new VelocityContext();
		Template t = new Template();

		VelocityEngineManager.init();
		if ( user!=null) {
			t = VelocityEngineManager.getTemplate("main_newuser.html");
			context.put("username", user.getFullName());
		} else {
			t = VelocityEngineManager.getTemplate( "main_knownuser.html" );
			context.put("username", "No user logged on!");
		}
		StringWriter writer = new StringWriter();
		t.merge( context, writer );
		out.println(writer.toString());
		out.flush();
        out.close();
	}

The templates are written in plain HTML + javascript with two differences

1) The velocity parser doesn’t like it when you use $. combinations in the template. There is already a bug reported  for this , but the version I’m using doesn’t contain the fix yet. A workaround is to replace all $ tags with jQuery. So use “jQuery.ajax({” instead of “$.ajax({“.

2) Instead of retrieving dynamic information with ajax, the $ tags are used to set data service side. So the div in the html template showing the username looks like:

<div id="userfullname" class="outputTextArea">$username</div>

Other thoughts

The advantage of using this method are:

  • That you need less http gets/posts to the server.
  • The performance seems better, but that can also be because of my javascript skills.
  • The html files are smaller, less complex, because a lot can be done server-side.
  • Better separation of code and markup.

The disadvantages are:

  • There is more CPU load on the server.
  • There may be some limitation in velocity (maybe using FreeMarker can fix that)
  • No sure if caching can be a problem.
  • The page completely needs to be reloaded in case of a change (but of course ajax call still be used if necessary)

11 Responses to Combining GAE, Apache Velocity and JQuery

  1. Thank you for your example! Now if I can just figure out how to create a template from a value from the Datastore in GAE I will be set! Thank you very much for the great example!

  2. dummymael says:

    Great post! By any chance, have you tried using the VelocityViewServlet with Guice on GAE? I seem to be having problems with it… If I can’t figure it out I’ll just have to use your method 🙂

    • jvdkamp says:

      I haven’t tried that, but I could imagine that you can reuse the custom ResourceLoader also for the VelocityViewServlet classes

      • dummymael says:

        Well I just found out the solution and it’s not quite what I wanted + I need to enable sessions which is off by default on GAE… so I’m ditching VelocityViewServlet (only need a simple solution anyway). Thanks!

  3. Francisco says:

    Where do you put your templates (.vm’s ) in this example? I’ve been moving them around and i cant seem to make them load! If I could figure this out, this post would have been really helpfull =P

  4. Francisco says:

    Well, I’ll answer myself for future references… I was missing I needed to edit VelocityEngineManager class, so that in init(), my own velocityResourceLoader was loaded.

    Thanks! Great post!

  5. Peter says:

    Thanks! It worked like a charm and was exactly what I was looking for.

  6. […] but nothing showstopping as with many of the other PDF and template libraries. I’ve used Jurgen van de Kamp’s explanation and classes. It worked […]

  7. door says:

    Very shortly this web page will be famous among
    all blogging and site-building visitors, due to it’s good articles or
    reviews

  8. Rickey says:

    If some one needs to bbe updated with latest technologies therefore he must be visit this website
    and be up to ate everyday.

  9. Lilla says:

    I blog frequently and I seriously thank you for your information. Your article has really peaked my
    interest. I’m going to take a note of your website and keep checking for
    new details about once a week. I opted in for your RSS feed as
    well.

Leave a comment