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

Jim Eng jimeng at umich.edu
Mon Jul 22 11:17:21 PDT 2013


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/6c8aa7cd/attachment.html 


More information about the sakai-dev mailing list