Maven
jar
spring-mvc
tomcat-embedded

SprignMVC + Tomcat Embeddedで作成したAPをJar化し、起動する際のメモ

More than 1 year has passed since last update.

Spring Bootを使用せず、Spring MVCとTomcat Embeddedを使用し、Webアプリケーションを作成した際に発生した事象について、備忘録として記録する。

環境

・Spring MVC 4.3.2.RELEASE
・Tomcat Embedded 8.5.2
・Maven

事象

Webapp Runnerを参考に、AP起動時に一時ディレクトリにTomcatのベースディレクトリ作成、及び、Jarファイルの展開を実施後、web.xmlファイルをロードさせ、Springの起動時に以下の例外が発生。

application.log
ERROR org.springframework.web.servlet.DispatcherServlet - Context initialization failed
org.springframework.beans.factory.parsing.BeanDefinitionParsingException: Configuration problem: Unable to locate Spring NamespaceHandler for XML schema namespace [http://www.springframework.org/schema/mvc]
Offending resource: class path resource [WEB-INF/spring/appServlet/servlet-context-thymeleaf.xml]

    at org.springframework.beans.factory.parsing.FailFastProblemReporter.error(FailFastProblemReporter.java:70)
    at org.springframework.beans.factory.parsing.ReaderContext.error(ReaderContext.java:85)
    at org.springframework.beans.factory.parsing.ReaderContext.error(ReaderContext.java:80)
    at org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.error(BeanDefinitionParserDelegate.java:301)
    at org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.parseCustomElement(BeanDefinitionParserDelegate.java:1408)
    at org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.parseCustomElement(BeanDefinitionParserDelegate.java:1401)
    at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.parseBeanDefinitions(DefaultBeanDefinitionDocumentReader.java:172)
    at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.doRegisterBeanDefinitions(DefaultBeanDefinitionDocumentReader.java:142)
    at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.registerBeanDefinitions(DefaultBeanDefinitionDocumentReader.java:94)
    at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.registerBeanDefinitions(XmlBeanDefinitionReader.java:508)
    at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.doLoadBeanDefinitions(XmlBeanDefinitionReader.java:392)
    at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:336)
    at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:304)
    at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:181)
    at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:217)
    at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:188)
    at org.springframework.web.context.support.XmlWebApplicationContext.loadBeanDefinitions(XmlWebApplicationContext.java:125)
    at org.springframework.web.context.support.XmlWebApplicationContext.loadBeanDefinitions(XmlWebApplicationContext.java:94)
    at org.springframework.context.support.AbstractRefreshableApplicationContext.refreshBeanFactory(AbstractRefreshableApplicationContext.java:129)
    at org.springframework.context.support.AbstractApplicationContext.obtainFreshBeanFactory(AbstractApplicationContext.java:612)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:513)
    at org.springframework.web.servlet.FrameworkServlet.configureAndRefreshWebApplicationContext(FrameworkServlet.java:668)
    at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:634)
    at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:682)
    at org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:553)
    at org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:494)
    at org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:136)
    at javax.servlet.GenericServlet.init(GenericServlet.java:158)
    at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1194)
    at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1110)
    at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:1000)
    at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:4919)
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5229)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:152)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1405)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1395)
    at java.util.concurrent.FutureTask.run(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)

原因

Jar化する際に、「maven-assembly-plugin」プラグインを使用し、行っていたが、その際、META-INF内に格納される「spring.schemas」「spring.handlers」がSpringのJarに含まれているものと異なるため、スキーマ解決が出来ず、エラーが発生。

対処方法

「maven-shade-plugin」を使用し、以下の定義でJar化する。

pom.xml定義
<plugin>
    <artifactId>maven-shade-plugin</artifactId>
    <version>2.2</version>
    <executions>
        <execution>
            <phase>package</phase>
            <goals>
                <goal>shade</goal>
            </goals>
            <configuration>
                <transformers>
                    <transformer
                        implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                        <resource>META-INF/spring.handlers</resource>
                    </transformer>
                    <transformer
                        implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                        <resource>META-INF/spring.schemas</resource>
                    </transformer>
                </transformers>
            </configuration>
        </execution>
    </executions>
</plugin>

参考にしたサイト