06 April 2019
Pour produire un fichier .war utilisable dans un serveur tomcat à partir d'une application Spring Boot, tout d'abord, préciser dans le .pom que l'on veut un .war comme package.
Comme indiqué dans de nombreux exemples sur le web, le .war ainsi produit n'est pas fonctionnel, puisqu'il n'y a pas de fichier web.xml de produit, et donc aucune servlet à démarrer.
D'après le bouquin "Spring Boot in action" de chez Manning, au chapritre 8, Il faut tout d'abord ajouter une configuration d'initialiazation.
En adaptant l'exemple fourni, cela donne le point suivant :
package fr.cst.rd.digitalCinemaAssetHandler;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
public class DigitalCinemaAssetHandlerServletInitializer extends SpringBootServletInitializer {
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(DigitalCinemaAssetHandlerApplication.class);
}
}
Note les dates de logs ne reflete pas l'odre des essais, puisque j'ai recommençé pour rédiger cette note.
[...]
avr. 06, 2019 3:57:28 PM org.apache.catalina.startup.ContextConfig processAnnotationsJar
GRAVE: Unable to process Jar entry [module-info.class] from Jar [jar:file:/C:/Users/hnl-bis/workspace/dicranum/target/digitalCinemaAssetHandler-0.0.3-SNAPSHOT/WEB-INF/lib/jaxb-api-2.3.1.jar!/] for annotations
org.apache.tomcat.util.bcel.classfile.ClassFormatException: Invalid byte tag in constant pool: 19
at org.apache.tomcat.util.bcel.classfile.Constant.readConstant(Constant.java:133)
[...]
En essayant de le charger dans le tomcat 7 de XAMPP erreur concernant la compatibilité du timecode, malgré le fait que la jvm utilisée soit java 8.
GRAVE: Unable to process Jar entry [META-INF/versions/9/module-info.class] from Jar [jar:file:/C:/dev/xampp/tomcat/webapps/digitalCinemaAssetHandler-0.0.2-SNAPSHOT/WEB-INF/lib/byte-buddy-1.9.7.jar!/] for annotations
org.apache.tomcat.util.bcel.classfile.ClassFormatException: Invalid byte tag in constant pool: 19
at org.apache.tomcat.util.bcel.classfile.Constant.readConstant(Constant.java:97)
at org.apache.tomcat.util.bcel.classfile.ConstantPool.<init>(ConstantPool.java:55)
at org.apache.tomcat.util.bcel.classfile.ClassParser.readConstantPool(ClassParser.java:175)
at org.apache.tomcat.util.bcel.classfile.ClassParser.parse(ClassParser.java:83)
at org.apache.catalina.startup.ContextConfig.processAnnotationsStream(ContextConfig.java:2071)
at org.apache.catalina.startup.ContextConfig.processAnnotationsJar(ContextConfig.java:1947)
at org.apache.catalina.startup.ContextConfig.processAnnotationsUrl(ContextConfig.java:1913)
at org.apache.catalina.startup.ContextConfig.processAnnotations(ContextConfig.java:1898)
at org.apache.catalina.startup.ContextConfig.webConfig(ContextConfig.java:1330)
at org.apache.catalina.startup.ContextConfig.configureStart(ContextConfig.java:889)
at org.apache.catalina.startup.ContextConfig.lifecycleEvent(ContextConfig.java:386)
at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:117)
at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:90)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5380)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:901)
at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:877)
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:649)
at org.apache.catalina.startup.HostConfig.deployWAR(HostConfig.java:1083)
at org.apache.catalina.startup.HostConfig$DeployWar.run(HostConfig.java:1879)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Il y a un problème binaire avec les bytecode.
Téléchargement d'un tomcat 9.
En plaçant la webapp :
06-Apr-2019 15:38:57.530 GRAVE [http-nio-8080-exec-1] org.apache.catalina.core.ApplicationContext.log HTMLManager: Erreur lors du démarrage de [/digitalCinemaAssetHandler-0.0.2-SNAPSHOT]
org.apache.catalina.LifecycleException: Echec de démarrage du composant [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/digitalCinemaAssetHandler-0.0.2-SNAPSHOT]]
at org.apache.catalina.util.LifecycleBase.handleSubClassException(LifecycleBase.java:441)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:198)
at org.apache.catalina.manager.ManagerServlet.start(ManagerServlet.java:1409)
at org.apache.catalina.manager.HTMLManagerServlet.start(HTMLManagerServlet.java:700)
at org.apache.catalina.manager.HTMLManagerServlet.doPost(HTMLManagerServlet.java:223)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:660)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.catalina.filters.CsrfPreventionFilter.doFilter(CsrfPreventionFilter.java:136)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:200)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:607)
at org.apache.catalina.valves.RequestFilterValve.process(RequestFilterValve.java:348)
at org.apache.catalina.valves.RemoteAddrValve.invoke(RemoteAddrValve.java:53)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:678)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:408)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:834)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1415)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Invocation of init method failed; nested exception is org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1745)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:576)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:498)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1083)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:853)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:546)
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:142)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:775)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:316)
at org.springframework.boot.web.servlet.support.SpringBootServletInitializer.run(SpringBootServletInitializer.java:157)
at org.springframework.boot.web.servlet.support.SpringBootServletInitializer.createRootApplicationContext(SpringBootServletInitializer.java:137)
at org.springframework.boot.web.servlet.support.SpringBootServletInitializer.onStartup(SpringBootServletInitializer.java:91)
at org.springframework.web.SpringServletContainerInitializer.onStartup(SpringServletContainerInitializer.java:171)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5139)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
... 32 more
Caused by: org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment]
at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:275)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:237)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:214)
at org.hibernate.id.factory.internal.DefaultIdentifierGeneratorFactory.injectServices(DefaultIdentifierGeneratorFactory.java:152)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.injectDependencies(AbstractServiceRegistryImpl.java:286)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:243)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:214)
at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.<init>(InFlightMetadataCollectorImpl.java:179)
at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:119)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:904)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:935)
at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:57)
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:365)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:390)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:377)
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:341)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1804)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1741)
... 51 more
Caused by: org.hibernate.HibernateException: Access to DialectResolutionInfo cannot be null when 'hibernate.dialect' not set
at org.hibernate.engine.jdbc.dialect.internal.DialectFactoryImpl.determineDialect(DialectFactoryImpl.java:100)
at org.hibernate.engine.jdbc.dialect.internal.DialectFactoryImpl.buildDialect(DialectFactoryImpl.java:54)
at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:137)
at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:35)
at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.initiateService(StandardServiceRegistryImpl.java:94)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:263)
... 68 more
En fait, il faut pouvoir charger bean Spring, les annotations, etc. Il faut donc que le point d'entrée le permette...
Lorsque l'application est servie depuis un .war, les chemins ne fonctionnent plus, il faut les corriger avec le mécanisme de templates.
=> Cela fonctionne correctemetn pour les éléments dynamiques.
Par exemple :
<a class="nav-link" href="#" th:href="@{/ajax/cpl}" >CPL<span class="sr-only" th:if="${module == 'cpl'}">(current)</span></a>
est correctement substitué en :
<a class="nav-link" href="/digitalCinemaAssetHandler-0.0.17-SNAPSHOT/ajax/cpl" >CPL<span class="sr-only">(current)</span></a>
Par contre les éléments statiques ne sont pas correctement substitués.
<img src="images/dicranum-inverse.svg" alt="logo" height="32px" width="32px" th:src="@{~/images/dicranum-inverse.svg}">
Est substitué en :
<img src="/images/dicranum-inverse.svg" alt="logo" height="32px" width="32px">
Pourtant, le resources est correctement servie en :
http://localhost:8080/digitalCinemaAssetHandler-0.0.17-SNAPSHOT/images/dicranum-inverse.svg
Un problème de template ?
Dans un certains nombre de problèmes rencontrés sur les forums, le problème est que le contenu du répertoire /src/main/resources/static n'est pas servi, ou que les pages publiques n'ont pas été rangées à cet endroit. Ce n'est pas mon problème.
En fait, il s'agissait plus d'un problème de de template :
Il faut écrire :
th:src="@{/images/dicranum-inverse.svg}"
et non
th:src="@{~/images/dicranum-inverse.svg}"
J'ai à un moment remplaçé la configuration par extension d'interface :
package fr.cst.rd.digitalCinemaAssetHandler.webgui;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class MvcConfiguration implements WebMvcConfigurer {
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("home");
}
}
Par une configuration par extension d'adapter, pour palier à la situation précédente avant de comprendre qu'il s'agissait des templates.
package fr.cst.rd.digitalCinemaAssetHandler.webgui;
import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MvcConfigurer extends WebMvcAutoConfiguration
{
}
Mais cela n'apportait rien. Je le garde dans les notes just in case.
Comme il y a une instruction repackage dans le .pom, le .war est renomé .war.original, et la version repackage
* SO : why spring boot generate jar or war file with .original extention?
Cette action doit apparaitre dans le parent .pom.
21-Apr-2019 08:56:59.845 INFOS [ContainerBackgroundProcessor[StandardEngine[Catalina]]] org.apache.catalina.webresources.Cache.backgroundProcess The background cache eviction process was unable to free [10] percent of the cache for Context [/digitalCinemaAssetHandler-0.0.17-bis-SNAPSHOT] - consider increasing the maximum size of the cache. After eviction approximately [9,454] KB of data remained in the cache.
A explorer ...
Il faut créer un nouveau service :
Ajouter dans server.xml (tomcat8.0.53) :
<Service name="QuousqueService">
<Connector port="8091" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8444" />
<!--<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />-->
<Engine name="Catalina2" defaultHost="localhost2">
<Realm className="org.apache.catalina.realm.LockOutRealm">
<Realm className="org.apache.catalina.realm.UserDatabaseRealm"
resourceName="UserDatabase"/>
</Realm>
<Host name="localhost2" appBase="webapps2"
unpackWARs="true" autoDeploy="true">
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="localhost2_access_log" suffix=".txt"
pattern="%h %l %u %t "%r" %s %b" />
</Host>
</Engine>
</Service>