06 April 2019

blog java

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);
	}

}

Tomcat embarqué mvn tomcat7:run

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)
[...]

Tomcat 7 de XAMPP

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.

Avec tomcat 9

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...

Gestions des chemins

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}"

Changement de la configuration, et retour en arrière

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.

war.original and repackage

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.

Erreurs de chargement lorsqu'une autre version est encore chargée

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 ...

Pour servir sur un autre port

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 &quot;%r&quot; %s %b" />

      </Host>
    </Engine>
  </Service>