Deploying Web Apps

by Robert Pastel, Mark Woodford and Travis Forester for Grail 2. Revised for Grails 3 by Robert Pastel.

Deploying a web app is the operation of packaging the files in your development environment and uploading the package to the server, but there are details of the application that you will need to attend to so that your application runs properly on the server. In particular you will need to:

  • Configure the database for operation on the server
  • Configure mail service to run on the server
  • Configure any file paths that might differ between development and production
  • Configure Build for the Tomcat
  • Package your application into a WAR
  • Upload the WAR to a server
  • Restart the tomcat
  • Check that it is running properly

Terminology

Environments

I need to introduce some terminology before we can configure and deploy of your applications. Grails can be configured to run differently in different “environments.” See

http://grails.github.io/grails-doc/latest/guide/conf.html#environments

Grails has basically three different environments:

  • development
  • test
  • production

Typically the development environment is the environment while you are programming on your computer at home. The production environment is typically a server that is accessed by the public. The test environment is a server that is setup to test integration of many services and web apps. The primary difference between the environments is the data sources. In the development environment, you use a in memory H2 database and in the production environment you might use a MySQL server. The Grail has a convenient technique for configuring the data sources for the different environment.

Although, a development process should proceed from the development environment to the test environment and then finally made public in the production environment, we will shorten the process and use only the development and production environment. This implies that you will do final testing in the production environment.

WAR File

The second term to discuss is the “WAR.” WAR stands for “Web application ARchive.” It is basically a JAR file that has a specific directory structure for web applications.

http://en.wikipedia.org/wiki/WAR_(file_format)

In Java Server Page (JSP) technology, deployment proceeds by making a WAR file of your application and uploading the WAR file to a special directory on the server. The server un-packages the WAR, called exploding, knows how to interpret the files in your applications, and consequently can serve the files to the public. There are several JSP servers, see the list at Wikipedia

http://en.wikipedia.org/wiki/JavaServer_Pages

We will be using the Apache Tomcat server

http://en.wikipedia.org/wiki/Apache_Tomcat

Realize that Tomcat is in essences just a Java application. There is no special hardware associated with the server, but for the server to be public it needs be connected to the Internet and registered in a Domain Name Server (DNS).

Tomcat Server Directories

Domain

The domain name for the machine with the tomcat instances is

hci-dev.cs.mtu.edu

Catalina Base Directories

Catalina is the core component of Tomcat. Catalina is Tomcat’s servlet container. Catalina implements Sun Microsystems’ specifications for servlet and JavaServer Pages (JSP)

https://www.mulesoft.com/tcat/tomcat-catalina

http://stackoverflow.com/questions/32985051/what-are-the-tomcat-component-what-is-catalina-and-coyote

The Catalina base directories for the teams are located at

  • var/lib/tomcats/2017_hci_1/
  • var/lib/tomcats/2017_hci_2/
  • var/lib/tomcats/2017_hci_3/

Note that the tomcats/ has a “s”. The directory names for the different teams specify the year, the class and the team number. The team number is your team/group number. The format of the Catalina base directory is

<year>_<class>_<team number>

Each team has access only to their tomcat instance’s Catalina base directories. If your explore your tomcat directories, you will find

  • bin/ – this is a symbolic link
  • conf/ – contains the configuration files for your tomcat instance
  • lib/ – this is a symbolic
  • logs/ – this contains the log for your tomcat instance
  • temp
  • webapp/ – this is the appBase directory and contains the apps directories.
  •  work

We will talk more about these directories later, in particular the webapp/ and logs/ directories.

Set the Context Path

Don’t forget to set the server context path for your app, as you did in your first programming assignment.

Edit grails-app/conf/application.yml by adding to the bottom of the file

server:
    contextPath: '/<app name>'

Where <app name> is the name of your app.

It is important that your app sets the context path because when the app is deployed to the production server, a “load balancer” that uses the app name to route the requests to the correct server.

Configure Upload Sizes

If the app uploads files or post large data, the controllers need to configured for maximum file size and request size in application.yml. For example:

grails:
    controllers:
        upload:
            maxFileSize: <max file size in bytes>
            maxRequestSize: <max request in bytes>

Configure the Database for operation on the server

When developing a Grails application, there are a number of database options available. You may choose to use H2 (default), HSQLDB, MySQL, etc. In addition, you can choose how the database will be stored:

  • hosted on a server: a service such as mysqld, running separately from the web application and possibly on a different machine, handles requests from the application to create, read, update, or delete data within the database
  • embedded: the database is located within the application itself, and all operations to the database are done directly by the application

For rapid prototyping, and for use cases in which the database accessed relatively infrequent  (i.e. there are only a few connections at once) an embedded database will work just fine. For small projects, embedded databases have the advantage of being easy to initialize and maintain.

Another design choice is whether to have the database stored on disk or in memory. If the database is expected to grow very large, then it would be better to store the database files on disk to prevent out-of-memory errors. Keeping the database in memory allows faster access times, but if something goes wrong, all data in memory will be lost. So, it makes sense that during development you would like to use a database that is stored in memory, so that you can quickly make and use the database. But during production, you would like the database to be stored on the disk so that the data will persist between stopping and starting the web application.

I now explain how to configure your Grails application to connect to an embedded H2 database stored on disk.

Open the application.yml configuration file.

Direct your attention to the dataSource settings at the end of the file. The property driverClassName should be “org.h2.Driver”. Also, note that the username and password for the database are defined here.

Now locate the environment-specific settings. You should see code structure as below

environments:
    development:
        dataSource:
            …

    test:
        dataSource:
            …

    production:
        dataSource:
           dbCreate: none
           url: ... 
           properties:
                …

Grails allows you to configure specific settings for development, testing, and production environments. I suggest leaving the development and testing settings how they are. You need to make two changes to production settings.  In the production settings, just above the url, you need to change the “dbCreate” setting to “create”.

dbCreate: create

The “create” setting will make the database new each time you deploy a new war. If later you wish to save the database then change “create” to “none”. See Grails Gorm documentation

http://docs.grails.org/latest/guide/conf.html#dataSource

In the production settings, you need to change url, to specify the path to the database.

url: jdbc:h2:file:/var/lib/tomcats/<tomcat instance name>/db/<app name>;MVCC=TRUE;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE

For example, if your tomcat instance name is 2020_hci_3 then the settings should be

url: jdbc:h2:file:/var/lib/tomcats/2020_hci_3/db/traveler;MVCC=TRUE;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE

Comment out all the “properties” options. These are for a database server not for a H2 file based database. Don’t delete them because you might need them later when you deploy to another server.

Save the changes to application.yml. Now your Grails application is configured to connect to an on-disk H2 database at the file path specified for your the tomcat server instance. Now when you deploy your application (as a WAR file) to the tomcat server, a new H2 database with the given name will be created (if it doesn’t already exist).

For more details about how to configure the data source see the grails documentation

http://grails.github.io/grails-doc/latest/guide/conf.html#dataSource

and for a summary on how data source is configured by environments

http://grails.github.io/grails-doc/latest/guide/conf.html#dataSourcesAndEnvironments

Database configuration for Apps without Databases

Some apps do not use a database, but I have learned that nevertheless the production database must still be configurated. My experience is that when a Gails war is deployed and while the app is initializing it looks for a database even if it will not use it. The quick fix I have made is to configure Grails so that it has an imbedded memory production database. Grails can then create the database, but never use it. So in application.yml, copy development dataSource setting to the production dataSource settings. In other it should look like:

...
production:
    dataSource:
        dbCreate: create-drop
        url: jdbc:h2:mem:devDb;MVCC=TRUE;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE
...

Configure dbconsole for use in production

The dbconsole is not enabled by default in the production environment. In grails-app/conf/application.groovy file add at the bottom:

environments {
   production {
      grails.dbconsole.enabled = true
      grails.dbconsole.urlRoot = '/dbconsole'
   }
}

The setting “grails.dbconsole.enabled = true” enables dbconsole. The setting “grails.dbconsole.urlRoot = ‘/dbconsole’ demands the URL for the dbconsole relative to the web app use. So if you have port number 8081 and app name “traveler” then the URL for dbconsole will be

https://hci-dev.cs.mtu.edu:8081/traveler/dbconsole

You should make sure that access to dbconsole is secured by using spring-security core grails plugin. Also you will need give access to the admin role by adding the static rule in application.groovy

grails.plugin.springsecurity.controllerAnnotations.staticRules = [
...
   [pattern: '//dbconsole/',   access: ['ROLE_ADMIN']
]]

When using dbconsole in production, make sure that dbconsole login fields are correct.

  • Driver Class: org.h2.Driver
  • JDBC URL: jdbc:h2:file:/var/lib/tomcats/<tomcat instance name>/db/<your app name> – This is the same URL that you used to specified for the database file location.
  • User Name: what you specified for the database username. Default is “sa”
  • Password: default is blank

Configure mail service to run on the server

If your web application uses a mail service then you will need to configure the mail for the production mail server. If your application requires users to register in order to use the app then your web app should be using the mail server to send a key to the user’s email address so that they can finish the registration. This is done for two reasons. The email address is a unique identifier for the user. Also, responding to the email address assures that the user is a “real” person and not a robot because a real user can click on the url specified in email. Finally the mail service is used to send a key to the user when they forget their passwords and need to reset their passwords. If you are using Spring Security UI plugin in your application then the above registration and forgotten password procedures are implement in your web app, and your web app is using a mail server and the Grails Mail plugin.

By default the Mail plugin is configured at localhost on port 25. The Mail plugin can be reconfigured in Config.groovy file. On the production server your application will use a special mtu email account. The email address is “mushroommail@mtu.edu”  with a password I’ll give you later. In the bottom of the application.groovy file add the following code:

// Spring Security Email Configurations
grails {
    	mail {
        		host = "smtp.gmail.com"
        		port = 465
        		username = "mushroommail@mtu.edu"
        		password = "actual-password"
        		props = ["mail.smtp.auth":"true",
            			"mail.smtp.socketFactory.port":"465",
            			"mail.smtp.socketFactory.class":"javax.net.ssl.SSLSocketFactory",
            			"mail.smtp.socketFactory.fallback":"false"]
     }
}

Note that you will have to replace “actual-password” with a password that I will give you via google docs.

You can read more about configuring and using the Mail plugin at

http://grails.org/plugins/mail

Configure file paths that differ between development and production

I suspect that most of the teams can skip this step. Meaning your production application is not using different file paths from your development paths. This might be because your app is storing uploaded files as blobs in the database. But sometimes databases are setup to store only the file path to the uploaded file rather than the complete file. If your database is configured like this then the file paths will be different on the development machine then on the production server. Another example of development and production file differing is when your app uses resources such as JSON or GeoJSON files. Below is technique to make it convenient to have different file paths.

First consider where uploaded files should be kept on the production server. Although it is possible to locate the files in the exploded web app folder that tomcat makes, this would not be appropriate because redeploying the app would cause the app to be be lost. Although the uploaded files can be stored any location on the server that the tomcat has permission to access, I have found it convenient to locate the uploaded in the webapp directory and the full file path would be:

/<catatina path>/webapps/<app name>_content

This clearly indicates that the directory is for the web app’s content files and the intended app. Note that this location is also accessible to ftp, so that programmers can add content after deployment.

Consider where to locate the files on the development machine. If you are using a Linux machine for development the directory can be anywhere as long as tomcat has read and write permission in the directory. But a windows development machine will not let the web app write into any directory outside web-app folder. Consequently the best location on the develop machine is to use a relative path to the web-apps directory, so the full file path would be

web-apps/<app name>_content

The example below is a slightly modified solution I used for uploading JSON configuration files for my “vmr” web app. My development machine is a window machine, and during development, JSON files are uploaded to a the “vmr_content” subdirectory in the web-app/ directory. While on the production machine the JSON files are uploaded to the “vmr_content” directory in the webapp folder.

This code in the init/BootStrap.groovy files makes it easy to find and change the paths if necessary, without delving into the code throughout the app:

package vmr

import grails.util.Environment

class BootStrap {
    private static final contentName = 'vmr_content'
    // System's separator 
    String sep = System.getProperty('file.separator')
    // Catalina/webapp/ Full Path
    String webappPath = "${sep}var${sep}lib${sep}tomcats${sep}2017_hci_1${sep}webapp"

    def init = { servletContext ->

      // File location based on environment
   
        switch (Environment.current) {
            case Environment.DEVELOPMENT:
                servletContext.files = [
                    server: "web-app${sep}${contentName}",
                    client: "${sep}${contentName}"
                ]
                break
             case Environment.PRODUCTION:
                 servletContext.files = [
                     server: "${webappPath}${sep}${contentName}",
                     client: "${sep}${contentName}"
                 ]
                 break
             default:
                 println 'Files switch default. Should not get here.'
       }

    ....
}

Note the code uses Grails utility Environment property to switch between the different variables. Also because the deployment and production machine are different systems, the System’s getProrperty(‘file.separator’) is used to determine weather to use ‘/’ for linux machines or ‘\’ for Windows machine.

The ‘servletContext’ variable is injected into the controllers. So while uploading the file, the controller would use serveletContext.files.server to specify the path to save the file. For example to upload a json file and write it to the “vmr_content” directory, the controller code could be:

class SomeController {
   String sep = System.getProperty('file.separator')

   def uploadFile(){
      def json = request.JSON
      Sting jsonName = "SpecificFileName.json"
      String filePath = "${serveletContext.files.server}${sep}${jsonName}
      File file = new File(filePath)
      file.delete() // just in case already exist
      file.createNewFile()
      file.text = json.toString()
   }
   ...
}

If a jpg file is to be displayed in a view, the controller should add serveletContext.files.client to the model for the view.

class ShowFileController {
   String sep = System.getProperty('file.separator')

   def show(){
      fileName = "SpecificFileName.jpg"
      model.filePath = "serveletContext.files.client${sep}${fileName}
      return model 
   }
   ...   
}

To display the image, the gsp file would then use

<img src="${filePath}" >

Naturally, the user running the server, typically “tomcat”, should have +rwx permissions on the “vmr_content” directory in question.

Test Build before Deployment

At this point, you can test your changes before deploying. We do this by making a jar file instead of a war file and then running the app with the imbedded tomcat server. To make the war file, we need to remove from the build.gradle:

apply plugin: "war"

In build.gradle, locate the “apply plugin” section and add

apply plugin:"eclipse"
apply plugin:"idea"

// For testing with jar, comment out.
// Need to also change provided to compile in dependencies.
// Will make jar. Run using "java -jar". Needs java 8.
// Uncomment to make war.
//apply plugin:"war"

apply plugin:"org.grails.grails-web"
apply plugin:"com.moowork.node"
apply plugin:"org.grails.plugins.views-json"

Be sure to comment out the applly plugin: “war”. If there any other references to the war file in build.gradle, you need to comment out those references. Also assure that “org.springframework.boot:sprintg-boot-starter-tomcat” in the dependencies section is “compile” and not “provided” as we will do in the next section of this lecture.

You make the jar file by running Grails’ “war” command. In intelliJ IDEA, you click on “Tools” in the menu and then select “Grails” “Run Grails Command”. In the “Run Grails Command” window, enter “war” (without the quotes) in the “Command:” text field, and click the “OK” button. This will open the “Grails Console” at the bottom of intelliJs IDEA. After a few seconds, you should see “BUILD SUCCESSFUL”.

The jar file is made in the “build/libs” directory. It should appear as

<app name>-0.1.jar
<app name>-0.1.jar.original

Where <app name> is the rootProject.name in settings.gradle. Verify that your are using Java 8 by entering in the root directory of the project:

java -version

You can use the terminal panel in the bottom of intelliJ IDEA to enter the command. You run the jar file by entering:

java -jar build/libs/<app name>-0.1.jar

You should see in the terminal:

Grails application running at http://localhost:8080/<contextPath> in environment: production

Where <contextPath> is the “server: contextPath” that you specified in application.yml. You can click on the link to “http://localhost:8080…”. This will open you default browser and point it at “http://localhost:8080…”. You can now test your app as it would be in production.

Correct the Build for the Production Environment

External Tomcat Container Specification

Grails 3 embeds the Tomcat server in WAR file. The embedded tomcat server might interfere with the external container if it is a different tomcat version.

https://docs.grails.org/latest/guide/gettingStarted.html#deployingAnApplication

https://docs.grails.org/latest/guide/deployment.html

Assuming that you are using the Grails Web profile find the find find the dependencies section In the build.gradle configuration file at the root of project. (Note if you are using the Grails React profile you should search in the build.gradle configuration file in the server/ directory.)

dependencies {
    compile "org.springframework.boot:spring-boot-starter-logging"
    compile "org.springframework.boot:spring-boot-autoconfigure"
    compile "org.grails:grails-core"
    compile "org.springframework.boot:spring-boot-starter-actuator"
    compile "org.springframework.boot:spring-boot-starter-tomcat"
    ...
}

....

Just above the dependencies section add the line to specify the tomcat version.

ext['tomcat.version'] = '7.0.69'

Where ‘7.0.69’ is the current tomcat version on hci-dev.cs.mtu.edu. Later, you will learn how to check the version number on the server.

Next we need to specify that the tomcat should not be included in the WAR file to do this change “compile” specification for the spring-boot-starter-tomcat to “provided” in the dependencies section. The edited version should look like

ext['tomcat.version'] = '7.0.69'

dependencies {
    compile "org.springframework.boot:spring-boot-starter-logging"
    compile "org.springframework.boot:spring-boot-autoconfigure"
    compile "org.grails:grails-core"
    compile "org.springframework.boot:spring-boot-starter-actuator"
    provided "org.springframework.boot:spring-boot-starter-tomcat"
    ...
}

If you tested you app by making a jar file be sure to uncomment:

apply plugin: "war"

Naming the War file

By default Grails name the WAR file with a version number. When deploying to an external tomcat, we do not want the version number. The WAR file name must match the project name or the web app will not deploy properly. You can edit the WAR file name if you want without hurting the contents.  Once your have configured the WAR name properly, you’ll not have to do this again.

The WAR is named in build.gradle configuration file in your project root directory. In build.gradle, add the following line to the bottom of the file.

war.archiveName="${war.baseName}.war"

Package your application into a WAR

To make the WAR file you run a grails command. You’ll need to do this step each time you want to deploy a new version of your web application. On your development machine, your home machine, make the war file in production environment mode. Production environment is the default for the “war” command but not for the “run-war” command. The command executed in your project directory is simply

grails war

If you are using IntelliJ IDEA, you can make the WAR file by clicking “Build” in the menu and selecting “Make Grails Web Archive”.  I have noticed that the “Make Grails Web Archive” menu item does not always appear in the “Build” menu. You can build the WAR file by using “Grails” in the “Tools” menu. Select “Run Grails Command” and enter “war” in the “Command” text field.

The build and compression will take several minutes. You will find the WAR file in your project’s build/lib/ directory. I always delete the old WAR file before building it, so that I know for certain that it is a new WAR file. The first time you build a WAR file there will not be libs/ directory. It will be made during the first building.

War Packaging for App Development using React Profile

Note that if you are using the React profile with client and sever projects, the process is different. You need create Gradle tasks to combine the projects, besides other configuration changes. Follow the direction in the “Combining the React profile projects” Grails Guide:

http://guides.grails.org/react-combined/guide/index.html

Uploading the WAR to your Server and Insure it is running

Tomcat servers have a special directory called the appbase. The WAR files are uploaded to the appbase directory and then tomcat will expand/explode the WAR file in the directory. This deploys the web application. If there is already a WAR file with the same name then the old WAR file should be deleted before uploading the new WAR file. Tomcat will detect that the WAR file is deleted and delete the corresponding exploded web application. This is called undeploying. You must undeploy before redeploying.

Because Tomcat is just a Java application, the machine running Tomcat can have multiple instances of Tomcat. In order that the Tomcat servers do not interfere with each other while serving pages, the different instances of the Tomcat servers are configured to receive their request and send their responses through different ports, specified by port numbers. Recall that while you were programming and testing your individual assignments you would point your browser to the URL

http://localhost:8080/cs4760progassign/
  • http: – represents the protocol, in this case hypertext transfer protocol
  • localhost – is the domain name for the server, in this case it means the current machine
  • 8080 – is the port number

Each team in the class has their own instance of Tomcat to use for deployment. But each Tomcat will be listening and sending to a different port.

A Sepecial Note about Protocol

The tomcat servers on hci-dev.cs.mtu.edu are configured to be a secure server, SSL. This is the https protocol. When browsering to your web app on hci-dev.cs.mtu.edu, you need to specify https, not http. You can not just type the domain into the browser’s URL window, you must add “https://”.

Port Numbers

I will give you the port numbers for your tomcat instance in file called tomcat in your team/group directory. I will also give you passwords that you will need in this file.

The URL to your app will be

https://hci-dev.cs.mtu.edu:<port number>/<app name>

So if you have port number 8081 and app name “traveler” then the URL will be

https://hci-dev.cs.mtu.edu:8081/traveler

Special Note about the number of WAR files

JSP and especially Grails web applications use lots of memory. They can also have a memory leak if they are not redeployed properly. The tomcat instances for the class have enough memory for only one additional web applications besides the web application that comes standard with tomcat.

In your appbase you’ll notice that there are already some directories which are web applications. They are:

  • ROOT/ – web app for bare domain
  • docs/ – documents for how to use tomcat
  • examples/ – example web applications

Leave these web apps in your appBase. They do not consume much memory. You can access ROOT, docs, and examples through your browser. You should do so in order to check that your tomcat instances is running properly. To get to the ROOT app use the URL

https://hci-dev.cs.mtu.edu:<port number>/

This page tell you about tomcat. It also specifies the tomcat version number.

Remember: ONLY add one more web app to your appBase, otherwise your tomcat might run out of memory and crash.

Uploading and Deploying

Using a SFTP client (WinSCP is a very good choice for Windows) login into the Tomcat machine. (See domain name above.) I highly recommend that you use RSA keys so that the client can auto log in during network distributions. If you are logging into the server from a machine not on MTU network then you need to use a virtual network (VPN) with mtu. Point a browser to

vpn.mtu.edu

Log in and then select “Standalone VPN client”. This will download “BIGIPEdgeClient.exe”. Run this executable file in admin mode, and it will install the “BIG-IP Edge Client” to your apps. You run the client and click the “connect button.” A window will pop up asking for your username and password. After clicking the logon button, the VPN is created. You need to keep the app running while use your SFTP client to upload files to the server. If you do not have a VPN connection, you’ll get an “network error” and not be able to connect.

In the SFTP client, navigate to the appBase. (See above for the appBase directory.)

If you have previously deployed a WAR file for your web app that you are currently deploying then it should still exist in the appBase alongside the exploded web app. The exploded wep app is a directory with the same name as the WAR file. Delete the old WAR in the appBase before uploading the new WAR.

Wait. Wait until Tomcat deletes the old exploded web app. If you do not wait then deployment will fail, and Tomcat will never explode the new WAR file.

When the old web app directory disappears, you should stop tomcat server using a sudo command so that tomcat server does not prematurely explode a partially uploaded war file.

You have access to a few commands that are normally run by the root user. These commands are called sudo commands and are proceed by “sudo.”

There are four commands

  • start – to start tomcat
  • stop – to spot tomcat
  • restart – to stop and start
  • status – to check tomcat status

The format running the commands is

sudo systemctl <command> tomcat@<tomcat instance name>

On the development server the tomcat instance name is the same as the Catalina base. For the 2017 HCI team 1, to stop the tomcat, they would type.

sudo systemctl stop tomcat@2017_hci_1

You will then have to enter the password for your team account.

Sometimes IT admin forgets to give the account sudo permissions. If you suspect that this is a problem see the sub section “Problems with Stopping and Starting Tomcat” in “Something Goes Wrong” section below for how to check sudo permissions.

After stopping the tomcat server, use your SFTP client to upload the new WAR file.

After the war file is uploaded check it permissions using “ls -l”, the long list format. The war file needs to have user and group read and write premonitions. The other permissions should be read only.

ls -l
...
chmod 664 <war-file-name>.war

Wait. Sometimes Tomcat takes several minute, up to 10 minutes, to see the new WAR file and explode it.

After the war file is uploaded to the webapp folder, you should start the tomcat server by running the sudo comand

sudo systemctl start tomcat@<tomcat instance name>

Wait, wait, and wait longer. Tomcat takes a long time to start and explode the war file, generally 5 minutes. I normally point my browser to the ROOT app and wait for the page to load.

Point your browser to the web app and inspect it. (See above for port number.)

Deployment Scripts

Several students have written deployment scripts:

  • redeploy by Bryce Williams
  • deploy.py – Ryan Doyle’s Deployment script for Linux machines on MTU network. Instructions are on the ReadMe.

I recommend deploying by hand several times before using scripts so that you know what is going on.

Something Goes Wrong

The above procedure can go wrong. Some typically difficulties are

  1. The URL is wrong. Make sure you are using https protocol and you have the correct app name
  2. Memory overflow locking or crashing the server

You should first check that tomcat is running either by pointing the browser to the ROOT app or running the status command.

Second you should try restarting your tomcat.

In most cases stopping and starting tomcat will solve your problems. Sometimes you may need to delete the offending file or directory, e.g. the lockfile in the db/ directory.

You can get an idea of your problems by inspecting the log files. The log files are located in the logs/ directory in the catalina base directory.  The log file with the errors printed are in the catalina.***.log. Where “***” is the date specified by year first then month and then day.  A new log file is created each day that has errors. You find most recent entry in the log file by scrolling to the bottom of the log file. Pay attention to “SEVERE” errors.  If there is a SEVERE error. Study the chain of “Caused by” to determine the cause.

Class Not Found Error

If you see error like

Caused by: java.lang.ClassNotFoundException: ACLIP.Role

The tradition is for the package name to be lower case. But the package name in the error message is upper case. For some reason this causes confusion after deployment, even though it works in development. The solution is refactor the package name to be all lower case.

Problems with Database?

First make sure that production dbCreate is set to “create” in the application.yml. Otherwise the database will not be made. Later you may want to deploy a new WAR without changing the database then make sure that BootStrap.groovy does not add to the database and change dbCreate  to “none” in the application.yml.

Check that the db/ directory is made. It should be made in your catalina base directory. Examine the directory for files. If your app is still having trouble accessing the database you could delete these files and restart tomcat.

If the db/ directory is not created. Try creating the db/ directory and redeploying.

Apps without Domain Objects

If your app does not have Domain Objects then it is not using a database. Even if the app is not using a database the production data source configuration in application.yml must be correct because the app will try to connect to the data source during start up. I solve the problem by copying the data source configuration for development into production.

Problems with Styling?

I have had my CSS styling broken on the production server when it worked fine on development. I have fixed this by changing the asset pipeline settings in “build.gradle” to not enabling CSS minifying. Search for the assets section in “build.gradle” and change it to

assets {
    minifyJs = true
    minifyCss = false
}

Problems with Stopping and Starting Tomcat

Sometimes IT admin forgets to grant sudo or all the necessary permissions to the user account. If you have problems with sudo commands, you can check what you can do with sudo by

sudo -l -U <username>
e.g. sudo -l -U 2017_hci_1

Problems with Tomcat versions

Some time tomcat minor versions conflict. You can check the version of your Tomcat by navigator to the provided ROOT page (the URL for the Tomcat with just the port). The page should show the Tomcat version running. If you believe that the mismatch of Tomcat versions is the problem, you can change the Tomcat version specified by the “ext” directive in the build.gradle.

Good luck