[Building Sakai] Using spring-mvc and free marker templates in a sakai tool

Jim Eng jimeng at umich.edu
Mon Jul 22 11:37:00 PDT 2013


BTW, freemarker.cache.TemplateLoader (the missing class) is an interface defined in the freemarker jar.  As I understand it, the freemarker jar provides various implementations, but it's possible that the actual implementation is determined by classes in the spring-context-support jar, which is in shared.  

Jim



On Jul 22, 2013, at 2:17 PM, Jim Eng <jimeng at umich.edu> wrote:

> I'm having a problem.  I hope someone has a suggestion.  I am trying to write a sakai tool that will use freemarker templates to render views.  I have defined web.xml to use the sakai ToolListener and ContextListener to get requests within the site.  I am using sakai's RequestFilter to supply various context variables.  With that servlet defined by web.xml, I am trying to use freemarker's view resolver to find templates.  That all looks good to me, but when I deploy the tool into sakai, if fails with an error message saying a critical freemarker class cannot be found.  
> 
> I think the problem is with the class loader.  Some of the required spring support is in shared, and (of course) my app is in web apps.  
> 
> I will show web.xml [1], the servlet file [2] and the error message from catalina.out when I try to load the first page [3].  I'll also show what's in the webapp war's /WEB-INF/lib/ folder [4].
> 
> I'd be glad to post other info or send it privately to avoid spamming this list.
> 
> Suggestions appreciated.  
> 
> Jim
>   
> 
> [1] web.xml:
> 
> <?xml version="1.0" encoding="ISO-8859-1"?>
> <web-app xmlns="http://java.sun.com/xml/ns/j2ee"
> 	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
> 	 xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
> 	 version="2.4">
> 
> 	<display-name>Files</display-name>
> 	
> 	<!-- Sakai Request Filter -->
> 	<filter>
> 		<filter-name>sakai.request</filter-name>
> 		<filter-class>org.sakaiproject.util.RequestFilter</filter-class>
> 		<!-- If you need to do uploads you will need this 
> 		<init-param>
> 			<param-name>upload.enabled</param-name>
> 			<param-value>true</param-value>
> 		</init-param>
> 		-->
> 	</filter>
> 	
> 	<filter-mapping>
> 		<filter-name>sakai.request</filter-name>
> 		<servlet-name>repo-tool</servlet-name>
> 		<dispatcher>REQUEST</dispatcher>
> 		<dispatcher>FORWARD</dispatcher>
> 		<dispatcher>INCLUDE</dispatcher>
> 	</filter-mapping>
> 	
> 	<!--  This application's servlet class -->
> 	<servlet>
> 		<servlet-name>repo-tool</servlet-name>
> 		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
> 		<init-param>
> 			<param-name>main-page</param-name>
> 			<param-value>/index.html</param-value>
> 		</init-param>
> 		<load-on-startup>1</load-on-startup>
> 	</servlet>
> 		
> 	<!-- Sakai Tool Listener -->
> 	<listener>
> 		<listener-class>org.sakaiproject.util.ToolListener</listener-class>
> 	</listener>
> 	
> 	<!-- Sakai Spring Listener -->
> 	<listener>
> 		<listener-class>org.sakaiproject.util.ContextLoaderListener</listener-class>
> 	</listener>
> 	
> </web-app>
> 
> [2] repo-tool-servlet.xml:
> 
> <?xml version="1.0" encoding="UTF-8"?>
> <beans xmlns="http://www.springframework.org/schema/beans"
>     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
>     xmlns:p="http://www.springframework.org/schema/p"
>     xmlns:context="http://www.springframework.org/schema/context"
>     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd                http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
> 
> 	<bean id="templateLoader" class="org.sakaiproject.repo.ftl.RepoTemplateLoader"> 
> 	</bean>
> 	
>     <!-- freemarker config -->
>     <bean id="freemarkerConfig" class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
>       <property name="templateLoaderPath" value="/WEB-INF/ftl"/>
>     </bean>
>      
>     <!--
>       View resolvers can also be configured with ResourceBundles or XML files. If you need
>       different view resolving based on Locale, you have to use the resource bundle resolver.
>     -->
>     <bean id="viewResolver" class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">
>       <property name="cache" value="true"/>
>       <property name="prefix" value=""/>
>       <property name="suffix" value=".ftl"/>
>     </bean>
>  
>  
>   <context:component-scan
>         base-package="org.sakaiproject.repo.tool" />
>           
> </beans>
> 
> [3] Beginning of stack trace when trying to get to first page in the app:
> 
> org.sakaiproject.portal.api.PortalHandlerException: org.sakaiproject.tool.api.ToolException: javax.servlet.ServletException: Servlet.init() for servlet repo-tool threw exception
>     at org.sakaiproject.portal.charon.SkinnableCharonPortal.doGet(SkinnableCharonPortal.java:900)
> caused by: org.sakaiproject.tool.api.ToolException: javax.servlet.ServletException: Servlet.init() for servlet repo-tool threw exception
>     at org.sakaiproject.portal.charon.SkinnableCharonPortal.forwardTool(SkinnableCharonPortal.java:1494)
> caused by: javax.servlet.ServletException: Servlet.init() for servlet repo-tool threw exception
>     at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1147)
> caused by: java.lang.NoClassDefFoundError: freemarker/cache/TemplateLoader
>     at java.lang.Class.privateGetDeclaredConstructors(Class.java:2437)
> caused by: java.lang.ClassNotFoundException: freemarker.cache.TemplateLoader
>     at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
>     at java.security.AccessController.doPrivileged(Native Method)
>     at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
>     at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
>     at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
>     at java.lang.Class.getDeclaredConstructors0(Native Method)
>     at java.lang.Class.privateGetDeclaredConstructors(Class.java:2437)
>     at java.lang.Class.getDeclaredConstructors(Class.java:1863)
>     at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.determineCandidateConstructors(AutowiredAnnotationBeanPostProcessor.java:230)
>     at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.determineConstructorsFromBeanPostProcessors(AbstractAutowireCapableBeanFactory.java:972)
>     at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:945)
>     at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:487)
>     at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:458)
>     at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:295)
>     at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223)
>     at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:292)
>     at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
>     at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:626)
>     at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:932)
>     at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:479)
>     at org.springframework.web.servlet.FrameworkServlet.configureAndRefreshWebApplicationContext(FrameworkServlet.java:651)
>     at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:599)
>     at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:665)
>     at org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:518)
>     at org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:459)
>     at org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:136)
>     at javax.servlet.GenericServlet.init(GenericServlet.java:160)
>     at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1228)
>     at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1147)
>     at org.apache.catalina.core.StandardWrapper.allocate(StandardWrapper.java:836)
>     at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:657)
> 
> 
> [4] jars in /WEB-INF/lib:
> 
> $ ls -la ../webapps/repo/WEB-INF/lib/
> total 4968
> drwxr-xr-x  10 jimeng  staff     340 Jul 22 14:03 .
> drwxr-xr-x   9 jimeng  staff     306 Jul 22 14:03 ..
> -rw-r--r--   1 jimeng  staff   73098 May 23  2012 commons-codec-1.5.jar
> -rw-r--r--   1 jimeng  staff  931168 Jun 25 19:23 freemarker-2.3.19.jar
> -rw-r--r--   1 jimeng  staff   20682 May 23  2012 jstl-1.1.2.jar
> -rw-r--r--   1 jimeng  staff  367444 May 23  2012 log4j-1.2.14.jar
> -rw-r--r--   1 jimeng  staff    8391 Jun 25 19:20 sakai-jsp-adapter-0.10-K1.jar
> -rw-r--r--   1 jimeng  staff   93500 Jul 19 13:58 sakai-kernel-util-1.4.0-20130718.171752-155.jar
> -rw-r--r--   1 jimeng  staff  636659 Jul  5 12:33 spring-webmvc-3.2.3.RELEASE.jar
> -rw-r--r--   1 jimeng  staff  393259 May 23  2012 standard-1.1.2.jar
> $
> 
> 
> 

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://collab.sakaiproject.org/pipermail/sakai-dev/attachments/20130722/b2060624/attachment.html 


More information about the sakai-dev mailing list