Here are steps to deploy and run the CUBA application in Google App Engine Flexible.
Install the Cloud SDK. See the documentation.
When the installation is finished, create a new project and name it cuba-sample. If you skip this step, then you’ll need to create the project in the web console.
Install the app-engine-java component: gcloud components install app-engine-java.
If you skipped project creation, use the GCP Console to do it. Open the console and click on the sample project name on the top of the screen. Create new project.
Give project the name cuba-sample. Create an application using Java language
Specify a region. The default on is US-Central zone. You can choose another if you'd like to.
Please note project ID – in this case it is cuba-sample-278518
Choose SQL menu and click on it.
Create cloud SQL instance
Select PostgreSQL
Assign the instance name. In this case, it is cuba-sample-db
. Specify the password for the postgres user
(postgres
in this case) and select the region. Here we choose the same region as for the application: US-Central
Dive into the DB instance settings
and create a new database. For this application, its name is gaef
.
As stated in this documentation section you’ll need to enable the Cloud SQL Admin API. Follow the “Enable API” link
from this section and select a cuba-sample
project in the appeared dialog. Click “Continue”.
Open the CUBA-> Main Data Store Settings in the CUBA Studio and change the database type to PostgreSQL, datasource should be defined in application.
Open the CUBA -> Deployment -> Edit UberJar Settings menu and specify Uber JAR deployment options as shown on the picture:
- Check the ‘Build Uber JAR’ checkbox
- Generate the Logback configuration file
We will use runtime profiles to change database connection properties for Google Application Engine deploy. Create file gae-app.properties in CORE module.
Add GAE-specific PostgreSQL connection. The database URL should conform the format described in the manual, i.e.:
jdbc:postgresql://google/${database}?useSSL=false& cloudSqlInstance=${INSTANCE_CONNECTION_NAME}& socketFactory=com.google.cloud.sql.postgres.SocketFactory&user=${user}& password=${password}
Instance connection name can be copied from the database properties in the web console.
For this application, the profile-specific properties will look like this:
cuba.dataSource.username=postgres
cuba.dataSource.password=postgres
cuba.dataSource.dbName=gaef
cuba.dataSource.host=google
cuba.dataSource.connectionParams=?useSSL=false&cloudSqlInstance=cuba-sample-278518:us-central1:cuba-sample-db&socketFactory=com.google.cloud.sql.postgres.SocketFactory
To connect deployed application to the cloud database, you need to enable VPC connector according to documentation.
Create the app.yaml file in the appengine directory in the root of the project. Please note that we use project ID and conector name that we defined earlier. Entrypoint is important, in this line we specify the following:
-Dapp.home=/tmp/app_home
- specifies temporary folder where CUBA stores its settings-Dspring.profiles.active=gae
- enables settings values specified ingae-app.properties
file. Double check that spring profile name and file name suffix are the same.
runtime: java11
manual_scaling:
instances: 1
entrypoint: "java -Dapp.home=/tmp/app_home -Dspring.profiles.active=gae -jar app.jar"
vpc_access_connector:
name: "projects/cuba-sample-278518/locations/us-central1/connectors/gaef-connector"
You can find more about app.yaml
syntax in the documentation.
The next step - configure deployment using the Gradle plugin.
Add a dependency - appengine-gradle-plugin in the build.gradle:
dependencies {
classpath "com.haulmont.gradle:cuba-plugin:$cubaVersion"
classpath 'com.google.cloud.tools:appengine-gradle-plugin:2.2.0'
}
In the end of the build.gradle
file add the required gradle tasks:
apply plugin: 'com.google.cloud.tools.appengine'
appengine {
stage {
artifact = "$buildDir/distributions/uberJar/app.jar"
appEngineDirectory = 'appengine' // a directory with app.yaml
stagingDirectory = "$buildDir/staged-app"
}
deploy {
projectId = 'cuba-sample-278518' // specify a project id if the current project is not the default one
stopPreviousVersion = true // default - stop the current version
promote = true // default - & make this the current version
version = 'GCLOUD_CONFIG'
}
}
appengineStage.dependsOn(buildUberJar)
// a dummy task. It is required for appengineStage task of the google plugin
task assemble {
doLast {}
}
In the dependencies section of the coreModule add a dependency to the postgres-socket-factory:
dependencies {
compile(globalModule)
compileOnly(servletApi)
jdbc(postgres)
jdbc('com.google.cloud.sql:postgres-socket-factory:1.0.16') {
exclude group: 'com.google.guava', module: 'guava'
}
testRuntime(postgres)
}
Please note the exclusion of the guava library in the dependencies. If you don’t do it, you can get a problem because of CUBA’s and SocketFactory libraries clash.
java.lang.NoSuchMethodError: 'java.util.stream.Collector com.google.common.collect.ImmutableList.toImmutableList()'
Change the PostgreSQL JDBC driver version:
def postgres = 'org.postgresql:postgresql:42.2.12'
Then run the appengineDeploy
gradle task and the project should be deployed:
./gradlew appengineDeploy
After the deployment is completed, open the application URL in the browser and add the /app to the end of the URL similar to this: https://cuba-sample-278518.uc.r.appspot.com/app
An important note here. You will not be able to save files using the standard FileStorage. If your application uses it, then you 'll have to do something with files persistence. There is a sample implementation of such storage can be foung on GitHub.