This is part 2 of a series of (still) unknown length where I try to describe how to deploy the SDL Tridion Web 8.5 Discovery Service on CloudFoundry. All parts:

  1. Deploy Tridion SDL Web 8.5 Discovery Service on Pivotal CloudFoundry (part 1)
  2. Deploy Tridion SDL Web 8.5 Discovery Service on Pivotal CloudFoundry (part 2) (this post)

I finished the previous post thinking I was done, except a few small changes. Unfortunately, that wasn’t true. Remember we had to provide an explicit command line because of classpath requirements. This classpath wasn’t yet complete. Let’s analyze the start.sh file again:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#!/usr/bin/env bash

# Java options and system properties to pass to the JVM when starting the service. For example:
# JVM_OPTIONS="-Xrs -Xms128m -Xmx128m -Dmy.system.property=/var/share"
JVM_OPTIONS="-Xrs -Xms128m -Xmx128m"
SERVER_PORT=--server.port=8082

# set max size of request header to 64Kb
MAX_HTTP_HEADER_SIZE=--server.tomcat.max-http-header-size=65536

BASEDIR=$(dirname $0)
CLASS_PATH=.:config:bin:lib/*
CLASS_NAME="com.sdl.delivery.service.ServiceContainer"
PID_FILE="sdl-service-container.pid"

cd $BASEDIR/..
if [ -f $PID_FILE ]
  then
    if ps -p $(cat $PID_FILE) > /dev/null
        then
          echo "The service already started."
          echo "To start service again, run stop.sh first."
          exit 0
    fi
fi

ARGUMENTS=()
for ARG in $@
do
    if [[ $ARG == --server\.port=* ]]
    then
        SERVER_PORT=$ARG
    elif [[ $ARG =~ -D.+ ]]; then
    	JVM_OPTIONS=$JVM_OPTIONS" "$ARG
    else
        ARGUMENTS+=($ARG)
    fi
done
ARGUMENTS+=($SERVER_PORT)
ARGUMENTS+=($MAX_HTTP_HEADER_SIZE)

for SERVICE_DIR in `find services -type d`
do
    CLASS_PATH=$SERVICE_DIR:$SERVICE_DIR/*:$CLASS_PATH
done

echo "Starting service."

java -cp $CLASS_PATH $JVM_OPTIONS $CLASS_NAME ${ARGUMENTS[@]} & echo $! > $PID_FILE

At line 12 the classpath is set to .:config:bin:lib/*. We ended the previous post with a classpath of $PWD/*:.:$PWD/lib/*:$PWD/config/*, not quite the same. Furthermore, on lines 42..45, additional folders are added to the classpath. Taking all this into account, we get the following classpath: $PWD/*:.:$PWD/lib/*:$PWD/config:$PWD/services/discovery-service/*:$PWD/services/odata-v4-framework/* and the following manifest.yml:

---
applications:
- name: discovery_service
  path: ./
  buildpack: java_buildpack_offline
  command: $PWD/.java-buildpack/open_jdk_jre/bin/java -cp $PWD/*:.:$PWD/lib/*:$PWD/config:$PWD/services/discovery-service/*:$PWD/services/odata-v4-framework/* com.sdl.delivery.service.ServiceContainer -Xrs -Xms128m -Xmx128m
  env:
    JBP_CONFIG_JAVA_MAIN: '{ java_main_class: "com.sdl.delivery.service.ServiceContainer", arguments: "-Xrs -Xms128m -Xmx128m" }'
    JBP_LOG_LEVEL: DEBUG

Now that we have fixed the classpath, let’s see if the discovery service still runs when we push it.

0 of 1 instances running, 1 starting
0 of 1 instances running, 1 starting
0 of 1 instances running, 1 starting
0 of 1 instances running, 1 crashed
FAILED
Error restarting application: Start unsuccessful

TIP: use 'cf logs discovery_service --recent' for more information

Ok, that is unfortunate, we broke it again. Let’s check the log files again:

[APP/PROC/WEB/0] OUT                                             '#b
[APP/PROC/WEB/0] OUT                                              @# ,###
[APP/PROC/WEB/0] OUT     ##########  @##########Mw     ####   ########^
[APP/PROC/WEB/0] OUT    #####%554WC  @#############p  j####       ##"@#m
[APP/PROC/WEB/0] OUT   j####,        @####     1####  j####      ##    "
[APP/PROC/WEB/0] OUT    %######M,    @####     j####  j####
[APP/PROC/WEB/0] OUT      "%######m  @####     j####  j####
[APP/PROC/WEB/0] OUT          "####  @####     {####  j####
[APP/PROC/WEB/0] OUT   ]##MmmM#####  @#############C  j###########
[APP/PROC/WEB/0] OUT   %#########"   @#########MM^     ###########
[APP/PROC/WEB/0] OUT :: Service Container :: Spring Boot  (v1.4.1.RELEASE) ::
[APP/PROC/WEB/0] OUT Exit status 0
[CELL/0] OUT Exit status 0
[CELL/0] OUT Stopping instance ef44cf20-b9da-48c6-5edc-a6d7
[CELL/0] OUT Destroying container
[API/0] OUT Process has crashed with type: "web"
[API/0] OUT App instance exited with guid e9a00d0c-86b4-4dad-ae5d-e4208f09590f payload: {"instance"=>"ef44cf20-b9da-48c6-5edc-a6d7", "index"=>0, "reason"=>"CRASHED", "exit_description"=>"Codependent step exited", "crash_count"=>4, "crash_timestamp"=>1513173007899100032, "version"=>"692f3c6a-acf3-4adc-b870-3827355948d6"}
[CELL/0] OUT Successfully destroyed container

Not very informative… This just tells us that something went wrong but not what went wrong. It should be possible to get more logging than this. Lucky for us, it is.

In my config/logback.xml file, a number of RollingFileAppenders were configured (this may be different for your configuration). These were setup to log to a local folder. This isn’t going to fly on CloudFoundry of course, we should log to stdout and let the platform manage the rest. So I modified logback.xml:

<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true">
    <!-- Properties -->
    <property name="log.pattern" value="%date %-5level %logger{0} - %message%n"/>
    <property name="log.level" value="DEBUG"/>
    <property name="log.encoding" value="UTF-8"/>

    <!-- Appenders -->
    <appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <charset>${log.encoding}</charset>
            <pattern>${log.pattern}</pattern>
        </encoder>
    </appender>

    <!-- Loggers -->
    <logger name="com" level="${log.level}">
        <appender-ref ref="stdout"/>
    </logger>

    <root level="ERROR">
        <appender-ref ref="stdout"/>
    </root>
</configuration>

This should take care of logging everything to stdout. If we push the app now, we get a lot of logging and in my case, the discovery service still crashes. But at least now I can see why:

[APP/PROC/WEB/0] OUT DEBUG SQLServerConnection - ConnectionID:1 Connecting with server: DBSERVER port: 1433 Timeout slice: 4800 Timeout Full: 15
[APP/PROC/WEB/0] OUT DEBUG SQLServerConnection - ConnectionID:1 This attempt No: 3
[APP/PROC/WEB/0] OUT DEBUG SQLServerException - *** SQLException:ConnectionID:1 com.microsoft.sqlserver.jdbc.SQLServerException: The TCP/IP connection to the host DBSERVER, port 1433 has failed. Error: "DBSERVER. Verify the connection properties. Make sure that an instance of SQL Server is running on the host and accepting TCP/IP connections at the port. Make sure that TCP connections to the port are not blocked by a firewall.". The TCP/IP connection to the host DBSERVER, port 1433 has failed. Error: "DBSERVER. Verify the connection properties. Make sure that an instance of SQL Server is running on the host and accepting TCP/IP connections at the port. Make sure that TCP connections to the port are not blocked by a firewall.".

The service attempts to connect to a database named DBSERVER. I have not yet configured the discovery database so this makes sense.

All in all, we’re again one step further in deploying SDL Tridion Web 8.5 Discovery Service on CloudFoundry.