I am developing an application for OSGi with velocity template engine. It works great for loading my templates by file loader but now I have to implement this templates in my jar and load it as resources.
How can i made it work?
My Code:
ve = new VelocityEngine();
ve.setProperty(RuntimeConstants.RESOURCE_LOADER, "classpath");
ve.setProperty("classpath.resource.loader.class",
ClasspathResourceLoader.class.getName());
ve.setProperty("classpath.resource.loader.path", "/velocitytemplates");
ve.init();
ve.getTemplate("foo.vm");
This will throw an exception like
Unable to find resource 'index.vm'
Caused by:
org.apache.velocity.exception.ResourceNotFoundException: Unable to find resource 'index.vm'
Sadly Velocity is not that OSGi friendly. Therefore you cannot use the built in ClasspathResourceLoader and it is hard to add a custom developed ResourceLoader as well.
I suggest that you should get your template as a Reader in any of the ordinary ways and choose one of the following:
The first option can be used if you do not have to merge your templates very often so performance is not a key requirement.
Here is a sample for the second option where the created template object can be reused by calling the merge function on it (expecting that you already got a Reader to your vm file or resource):
RuntimeInstance runtimeInstance = new RuntimeInstance();
runtimeInstance.init();
SimpleNode simpleNode = runtimeInstance.parse(reader, "nameOfYourTemplateResource");
Template template = new Template();
simpleNode.init(new InternalContextAdapterImpl(new VelocityContext()), runtimeInstance);
template.setData(simpleNode);
template.merge(...);
...
To get a reader for the vm file in OSGi you should choose a class that is surely in the same bundle as your vm resource and call SameBundleClass.class.getResourceAsStream... You can transform your stream to writer with InputStreamReader than.
Please note that the example misses some try-catch-finally block.
Two things to verify
Make sure you set the classpath of the OSGi bundle via the MANIFEST.MF to include a dot:
Bundle-ClassPath: .
The dot means to include the root of the bundle in the class-loading hierarchy, where your folder "velocitytemplates" likely resides.
And you need to have the Velocity jar-files in the same bundle where your template-files reside, because otherwise you'll get classloading issues as Velocity would reside in a different bundle and thus would not see the "velocitytemplates" at all in its classpath.
ClasspathResourceLoader does not support setting a "path", as it uses the Classpath by definition, so either add "velocitytemplates" to the Classpath in the OSGi bundle (MANIFESt.MF) or reference the velocity templates with complete path, i.e. "velocitytemplates/index.vm"
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With