Single WAR Tomcat Windows Service Deployment and Database Population

Hello,

I can’t seem to get a tomcat WAR file to update the database (despite “cuba.automaticDatabaseUpdate = true” property)

I am just asking if this is expected behavior.

Steps I am following:

  1. install fresh tomcat instance as a windows service (tomcat 8)
  2. build single WAR
  3. Create and empty database
  4. Drop WAR in webapps folder and start tomcat.

What happens is only one table is every written to the database: SYS_DB_CHANGELOG and nothing else.
So it is clear that the app can create tables, it is just unclear why it is not making the rest.

I have been getting around this by taking the scripts from all the folders and assembling a single script to create the database, but this is a little time consuming. Is this expected behavior when deploying to tomcat?

*Database is SQL Server 2014
**I gave the app SA permissions to see if that was the issue.

1 Like

Hi Thomas,

can you share the tomcat log files so that we can have a look at it? For now you can take a look at the logs and search for DbUpdaterEngine to see what went wrong.

Bye,
Mario

Thanks,
Sounds like that is not expected behavior.

It is likely I am doing something wrong.

Here is the log file. I didn’t see anything jump out at me.

(I had fixed the app by running the scripts manually)

tomcat8-stdout.2016-12-05.log (142.9K)

Hi,

so there are definitely some errors like:


2016-12-05 13:28:13.536 ERROR [localhost-startStop-1] com.haulmont.cuba.core.sys.singleapp.SingleAppCoreContextLoader - Error initializing application
java.lang.RuntimeException: Error loading DB-stored app properties cache
	at com.haulmont.cuba.core.app.ConfigStorage.loadCache(ConfigStorage.java:135) ~[cuba-core-6.3.4.jar:6.3.4]
	at com.haulmont.cuba.core.app.ConfigStorage.getDbProperty(ConfigStorage.java:106) ~[cuba-core-6.3.4.jar:6.3.4]
	at com.haulmont.cuba.core.sys.ConfigPersisterImpl.getProperty(ConfigPersisterImpl.java:44) ~[cuba-core-6.3.4.jar:6.3.4]
	at com.haulmont.cuba.core.config.ConfigGetter.getProperty(ConfigGetter.java:110) ~[cuba-global-6.3.4.jar:6.3.4]
	at com.haulmont.cuba.core.config.ConfigGetter.getProperty(ConfigGetter.java:95) ~[cuba-global-6.3.4.jar:6.3.4]
	at com.haulmont.cuba.core.config.ConfigGetter.invoke(ConfigGetter.java:67) ~[cuba-global-6.3.4.jar:6.3.4]
	at com.haulmont.cuba.core.config.ConfigHandler.invoke(ConfigHandler.java:79) ~[cuba-global-6.3.4.jar:6.3.4]
	at com.sun.proxy.$Proxy524.getAnonymousLogin(Unknown Source) ~[na:na]
	at com.haulmont.cuba.security.app.LoginWorkerBean.loginAnonymous(LoginWorkerBean.java:209) ~[cuba-core-6.3.4.jar:6.3.4]
	at com.haulmont.cuba.security.app.LoginWorkerBean.initializeAnonymousSession(LoginWorkerBean.java:511) ~[cuba-core-6.3.4.jar:6.3.4]
	at com.haulmont.cuba.security.app.LoginWorkerBean.applicationStarted(LoginWorkerBean.java:521) ~[cuba-core-6.3.4.jar:6.3.4]
	at com.haulmont.cuba.core.sys.AppContext.startContext(AppContext.java:234) ~[cuba-global-6.3.4.jar:6.3.4]
	at com.haulmont.cuba.core.sys.AppContext$Internals.startContext(AppContext.java:289) ~[cuba-global-6.3.4.jar:6.3.4]
	at com.haulmont.cuba.core.sys.AbstractWebAppContextLoader.contextInitialized(AbstractWebAppContextLoader.java:74) ~[cuba-global-6.3.4.jar:6.3.4]
	at com.haulmont.cuba.core.sys.singleapp.SingleAppCoreContextLoader.contextInitialized(SingleAppCoreContextLoader.java:56) [cuba-core-6.3.4.jar:6.3.4]
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_111]
	at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_111]
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_111]
	at java.lang.reflect.Method.invoke(Unknown Source) ~[na:1.8.0_111]
	at org.springframework.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:216) [spring-core-4.3.1.RELEASE.jar:4.3.1.RELEASE]
	at com.haulmont.cuba.core.sys.singleapp.SingleAppCoreServletListener.contextInitialized(SingleAppCoreServletListener.java:88) [cuba-core-6.3.4.jar:6.3.4]
	at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4853) [catalina.jar:8.0.39]
	at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5314) [catalina.jar:8.0.39]
	at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:145) [catalina.jar:8.0.39]
	at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:753) [catalina.jar:8.0.39]
	at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:729) [catalina.jar:8.0.39]
	at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:717) [catalina.jar:8.0.39]
	at org.apache.catalina.startup.HostConfig.deployWAR(HostConfig.java:940) [catalina.jar:8.0.39]
	at org.apache.catalina.startup.HostConfig$DeployWar.run(HostConfig.java:1816) [catalina.jar:8.0.39]
	at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source) [na:1.8.0_111]
	at java.util.concurrent.FutureTask.run(Unknown Source) [na:1.8.0_111]
	at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) [na:1.8.0_111]
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) [na:1.8.0_111]
	at java.lang.Thread.run(Unknown Source) [na:1.8.0_111]
Caused by: java.sql.SQLException: Invalid object name 'SYS_CONFIG'. Query: select NAME, VALUE from SYS_CONFIG Parameters: []
	at com.haulmont.bali.db.QueryRunner.rethrow(QueryRunner.java:463) ~[cuba-global-6.3.4.jar:6.3.4]
	at com.haulmont.bali.db.QueryRunner.query(QueryRunner.java:321) ~[cuba-global-6.3.4.jar:6.3.4]
	at com.haulmont.bali.db.QueryRunner.query(QueryRunner.java:412) ~[cuba-global-6.3.4.jar:6.3.4]
	at com.haulmont.bali.db.QueryRunner.query(QueryRunner.java:387) ~[cuba-global-6.3.4.jar:6.3.4]
	at com.haulmont.bali.db.QueryRunner.query(QueryRunner.java:431) ~[cuba-global-6.3.4.jar:6.3.4]
	at com.haulmont.cuba.core.app.ConfigStorage.loadCache(ConfigStorage.java:123) ~[cuba-core-6.3.4.jar:6.3.4]
	... 33 common frames omitted

Did you activate cuba. automaticDatabaseUpdate = true in the configuration / while war creation? There is a particular doc around windows service and war creation. Did you go through that one?

Bye,
Mario

Hi guys,

These lines in the log state that the automatic DB update is on and the app thinks that all DB scripts were executed.


2016-12-05 13:27:39.945 INFO  [localhost-startStop-1] com.haulmont.cuba.core.sys.dbupdate.DbUpdaterEngine - Updating database...
2016-12-05 13:27:40.198 INFO  [localhost-startStop-1] com.haulmont.cuba.core.sys.dbupdate.DbUpdaterEngine - Database is up-to-date

It means that either there are no scripts in WEB-INF\db, or all of them are registered in the SYS_DB_CHANGELOG table. Could you check this?

So I cleared everything out of Tomcat, deleted all the logs and made a fresh database to equalize everything. Same issue, but I think I have cleaner errors now.

Here is my build war task:


task buildWar(type: CubaWarBuilding) {
    webXmlPath = 'modules/web/web/WEB-INF/single-war-web.xml'
    appProperties = ['cuba.web.loginDialogDefaultUser':'<disabled>', 'cuba.automaticDatabaseUpdate':'true', 'cuba.web.loginDialogPoweredByLinkVisible':'false', 'cuba.web.loginDialogDefaultPassword':'<disabled>']
    includeContextXml = true
    includeJdbcDriver = true
    appHome = 'wjvacation'
}

Also I can confirm there are in fact scripts in the proper directories. That is where I have to pull them from to make the DB manually.

tomcat8-stdout.2016-12-06.log (25.5K)

2016-12-06 07_53_59-wjvacation - CUBA Studio

2016-12-06 07_59_02-SQLQuery10.sql - not connected - Microsoft SQL Server Management Studio

The app core still doesn’t see any scripts, so it just creates the SYS_DB_CHANGELOG table and doesn’t run any init scripts. If you are sure that there are DB init scripts in the proper structure inside WEB-INF\db of the WAR, let’s track down the cuba.dbDir app property.

Please look at web.xml of the WAR and find the appPropertiesConfig context parameter. It contains all resources that are scanned for properties. Each subsequent resource overrides values set by a previous one. Usually, when you build a single WAR, there is the WEB-INF\local.app.properties file that contains the following line:


cuba.dbDir = web-inf:db

Make sure this property exists and is not overridden by any subsequent properties file.

Here are is the web xml:


<?xml version="1.0" encoding="UTF-8"?>
<!--
  ~ Copyright (c) 2016 Haulmont Technology Ltd. All Rights Reserved.
  ~ Haulmont Technology proprietary and confidential.
  ~ Use is subject to license terms.
  -->

<web-app xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
         version="3.0">

    <!-- Web Client parameters -->

    <context-param>
        <description>List of app properties files for Web Client</description>
        <param-name>appPropertiesConfigWeb</param-name>
        <param-value>
            classpath:cuba-web-app.properties
            classpath:web-app.properties
            /WEB-INF/local.app.properties
        </param-value>
    </context-param>
    
    <context-param>
        <description>Web resources version for correct caching in browser</description>
        <param-name>webResourcesTs</param-name>
        <param-value>2016_12_05_13_26</param-value>
    </context-param>
    

    <!-- Middleware parameters -->

    <context-param>
        <description>List of app properties files for Middleware</description>
        <param-name>appPropertiesConfigCore</param-name>
        <param-value>
            classpath:cuba-app.properties
            classpath:app.properties
            /WEB-INF/local.app.properties
        </param-value>
    </context-param>
    <!--Application components-->
    <context-param>
        <param-name>appComponents</param-name>
        <param-value>com.haulmont.cuba</param-value>
    </context-param>

    <!-- Servlet context listeners that load the application blocks -->
    
    <listener>
        <listener-class>com.vaadin.server.communication.JSR356WebsocketInitializer</listener-class>
    </listener>
    <listener>
        <listener-class>com.haulmont.cuba.core.sys.singleapp.SingleAppCoreServletListener</listener-class>
    </listener>
    <listener>
        <listener-class>com.haulmont.cuba.web.sys.singleapp.SingleAppWebServletListener</listener-class>
    </listener>
</web-app>

Single war xml


<?xml version="1.0" encoding="UTF-8"?>
<!--
  ~ Copyright (c) 2016 Haulmont Technology Ltd. All Rights Reserved.
  ~ Haulmont Technology proprietary and confidential.
  ~ Use is subject to license terms.
  -->

<web-app xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
         version="3.0">

    <!-- Web Client parameters -->

    <context-param>
        <description>List of app properties files for Web Client</description>
        <param-name>appPropertiesConfigWeb</param-name>
        <param-value>
            classpath:cuba-web-app.properties
            classpath:web-app.properties
            /WEB-INF/local.app.properties
        </param-value>
    </context-param>
    
    <context-param>
        <description>Web resources version for correct caching in browser</description>
        <param-name>webResourcesTs</param-name>
        <param-value>${webResourcesTs}</param-value>
    </context-param>
    

    <!-- Middleware parameters -->

    <context-param>
        <description>List of app properties files for Middleware</description>
        <param-name>appPropertiesConfigCore</param-name>
        <param-value>
            classpath:cuba-app.properties
            classpath:app.properties
            /WEB-INF/local.app.properties
        </param-value>
    </context-param>
    <!--Application components-->
    <context-param>
        <param-name>appComponents</param-name>
        <param-value>com.haulmont.cuba</param-value>
    </context-param>

    <!-- Servlet context listeners that load the application blocks -->
    
    <listener>
        <listener-class>com.vaadin.server.communication.JSR356WebsocketInitializer</listener-class>
    </listener>
    <listener>
        <listener-class>com.haulmont.cuba.core.sys.singleapp.SingleAppCoreServletListener</listener-class>
    </listener>
    <listener>
        <listener-class>com.haulmont.cuba.web.sys.singleapp.SingleAppWebServletListener</listener-class>
    </listener>
</web-app>

Local app properties:


cuba.logDir = wjvacation/logs
cuba.confDir = wjvacation/${cuba.webContextName}/conf
cuba.tempDir = wjvacation/${cuba.webContextName}/temp
cuba.dataDir = wjvacation/${cuba.webContextName}/work
cuba.dataSourceJndiName = jdbc/CubaDS
cuba.download.directories = ${cuba.tempDir};${cuba.logDir}
cuba.dbDir = web-inf:db
cuba.web.loginDialogDefaultUser = <disabled>
cuba.automaticDatabaseUpdate = true
cuba.web.loginDialogPoweredByLinkVisible = false
cuba.web.loginDialogDefaultPassword = <disabled>
cuba.connectionUrlList = http://localhost:8080/wjvacation-core
cuba.useLocalServiceInvocation = true

I should point out it is not just this one app, but every app I have deployed that does this, which is why I thought it was “just how it was.”

I’m sure I am doing something wrong, even though I tried to stick to Cuba Studio for configuration options.

I have again confirmed all the scripts are in the DB folder. This is where I have to go snag them every-time and run them manually to get the app off the ground. After I run the scripts manually, the application works. Of course moving forward that might be a problem if I need to make app updates etc.

I tried deploying it as a two war files and received the same behavior.

The process I have been following to track this issue down.

  1. install a fresh instance of Tomcat (changing nothing)

  2. Build the WAR file via the deployment options in Cuba Studio

  3. drop the WAR file in webapps and start tomcat.

If I grab the scripts from the db directory and apply them manually via SSMS the app will function:
If I create or update the database from Cuba Studio that works fine as well.

So here is a question, is there some Tomcat Environment setting that could cause this to happen? As I said , I installed the instance of Tomcat and changed nothing.

Not sure if this is an issue or not, but when I apply the create-db.sql script manually, I receive this warning:
‘’’
Warning! The maximum key length for a nonclustered index is 1700 bytes. The index ‘IDX_CAT_ATTR_ENT_TYPE_AND_CODE’ has maximum length of 4108 bytes. For some combination of large values, the insert/update operation will fail.
‘’’
This doesn’t stop the script from running however.

catalina.2016-12-07.log (16.1K)

commons-daemon.2016-12-07.log (282B)

localhost.2016-12-07.log (4.7K)

tomcat8-stderr.2016-12-07.log (16.2K)

tomcat8-stdout.2016-12-07.log (25.5K)

2016-12-07 08_17_14-create-db.sql - TMEACHAM-PC3.wjvacation_app (WITINC_tmeacham (55))_ - Microsoft

Possibly important note: I have changed the default ports on the tomcat server. (8181 instead of 8080) could this cause the issue? I doesn’t seem to impact the application from running once I manually create the DB.

Eventually, we found a bug in DB updater - it doesn’t find DB scripts if a dbmsVersion is specified (2012 in your case), but there are no specific scripts in a folder for this version. I think it should work now if you create an empty create-db.sql file in the modules\core\db\init\mssql-2012 folder.

The fix will be available in the platform 6.3.5 next week. Sorry for the inconvenience.

Just to clarify, I do have a create-db.sql script in the “db>init>mssql”

I noticed that your example above has a folder called “mssql-2012” do I need to create that?

I have attached a screenshot.

2016-12-08 07_49_14-init

I changed database type to Microsoft SQL Server (rather than Microsoft SQL Server 2012) and the database was populated by the war deployment as expected.

I think I understand the the problem now was the application was looking for a mssql-2012 folder that did not exist. Thank you for your help!

Exactly. The bug is that the mssql-2012 is actually optional and should be ignored if not exists. So an alternative solution for you would be creating this folder with an empty script.

1 Like

:ticket: See the following issue in our bug tracker:

https://youtrack.cuba-platform.com/issue/PL-8323