<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Levant &#8211; Henry Poon&#039;s Blog</title>
	<atom:link href="https://blog.henrypoon.com/blog/tag/levant/feed/" rel="self" type="application/rss+xml" />
	<link>https://blog.henrypoon.com</link>
	<description></description>
	<lastBuildDate>Sun, 18 May 2025 05:39:28 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	
<site xmlns="com-wordpress:feed-additions:1">83044199</site>	<item>
		<title>Wadi Rum</title>
		<link>https://blog.henrypoon.com/blog/2020/03/20/wadi-rum/</link>
					<comments>https://blog.henrypoon.com/blog/2020/03/20/wadi-rum/#respond</comments>
		
		<dc:creator><![CDATA[hp]]></dc:creator>
		<pubDate>Sat, 21 Mar 2020 05:49:26 +0000</pubDate>
				<category><![CDATA[asia]]></category>
		<category><![CDATA[food]]></category>
		<category><![CDATA[middle east]]></category>
		<category><![CDATA[Afghanistan]]></category>
		<category><![CDATA[Aqaba Governorate]]></category>
		<category><![CDATA[Arabian Peninsula]]></category>
		<category><![CDATA[Camping]]></category>
		<category><![CDATA[COM]]></category>
		<category><![CDATA[D]]></category>
		<category><![CDATA[Desert]]></category>
		<category><![CDATA[Drive]]></category>
		<category><![CDATA[Geography of Asia]]></category>
		<category><![CDATA[Go]]></category>
		<category><![CDATA[hike]]></category>
		<category><![CDATA[IDE]]></category>
		<category><![CDATA[IME]]></category>
		<category><![CDATA[It]]></category>
		<category><![CDATA[Jordan]]></category>
		<category><![CDATA[lamb]]></category>
		<category><![CDATA[Levant]]></category>
		<category><![CDATA[Light]]></category>
		<category><![CDATA[Nature reserves in Jordan]]></category>
		<category><![CDATA[Petra]]></category>
		<category><![CDATA[rice]]></category>
		<category><![CDATA[Run]]></category>
		<category><![CDATA[star wars]]></category>
		<category><![CDATA[Tel Aviv]]></category>
		<category><![CDATA[Thou]]></category>
		<category><![CDATA[Time]]></category>
		<category><![CDATA[Tourism in Jordan]]></category>
		<category><![CDATA[Urge]]></category>
		<category><![CDATA[Vol]]></category>
		<category><![CDATA[Wadi Rum]]></category>
		<category><![CDATA[Western Asia]]></category>
		<category><![CDATA[World War I]]></category>
		<category><![CDATA[Z]]></category>
		<guid isPermaLink="false">https://blog.henrypoon.com/?p=5296</guid>

					<description><![CDATA[From Petra, we went out to the desert, Wadi Rum. This is the same place where famous movies were filmed, like The Martian, and some of recent Star Wars reboots. But it&#8217;s probably best known for it&#8217;s connection to Lawrence of Arabia, who spent some time in the desert during the Arabian revolt against the [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">From Petra, we went out to the desert, Wadi Rum.  This is the same place where famous movies were filmed, like The Martian, and some of recent Star Wars reboots.  But it&#8217;s probably best known for it&#8217;s connection to Lawrence of Arabia, who spent some time in the desert during the Arabian revolt against the Ottoman Empire during World War I.</p>



<figure class="wp-block-image size-large"><a href="https://photos.google.com/share/AF1QipPeMKBhzfINGDoRokDKh3j5CayfsXNtc5Aml88xzq1RWOBB5eeh56sExp5icsoLSQ/photo/AF1QipOFiDofxfpeXQ1kvckhV1PkLA4Hfxrt0sHFPVmt?key=RXowdEJYVUNCOXU1ZTBYbHFlZWx3bWk5dmZveXJR" target="_blank" rel=" noreferrer noopener"><img decoding="async" src="https://lh3.googleusercontent.com/pw/AP1GczMVJTk38U9dX8FnFAox_TsEEMW4oktj2mk-uomOQQ1V9Z5TCiXLQMowJXZCC92ud6B-nu1qLtolJFS6Efs4BzT1lUOYBHKpRelB0TLcDmq-zVQ4cShBX8LO3f17a5UI5n6mMBtNIXaM9yJ6Gsw0CY4mVQ=w1634-h919-s-no?authuser=0" alt=""/></a></figure>



<p class="wp-block-paragraph">Our tour took us through the desert in a pickup truck.  All we had to do was sit in the back and admire the views.  At first it was a little bit disorienting because I literally have never sat in the back of a pickup truck before.  I&#8217;d seen it many times in movies and what not, but that was it &#8211; especially from news clips where insurgents in Iraq or Afghanistan would do it, so it was pretty hard to not compare my experience with that.</p>



<figure class="wp-block-image size-large"><a href="https://photos.google.com/share/AF1QipPeMKBhzfINGDoRokDKh3j5CayfsXNtc5Aml88xzq1RWOBB5eeh56sExp5icsoLSQ/photo/AF1QipNA-PPEdK5u43S4yMXPTnIxqPkHRG0dp0ez9ISG?key=RXowdEJYVUNCOXU1ZTBYbHFlZWx3bWk5dmZveXJR" target="_blank" rel=" noreferrer noopener"><img decoding="async" src="https://lh3.googleusercontent.com/pw/AP1GczPNdE6XFumTF6xgoLXUd6tVjmvzD3Rhqba53otIR2S0JQaZ7LMK2BPXlA0egAFZZZI0RlSOZjuugNHMDPbrWn0tzeNyeSepQ4B4ILFOA7bYfFbs8yo_H1Q17Yuq94mytIp6ncD5bE-38NNbprQJpArURQ=w1634-h919-s-no?authuser=0" alt=""/></a></figure>



<p class="wp-block-paragraph">Along the way, we stopped by some old carvings on the rocks (so called petroglypths) from the Thamud, an ancient civilization that existed around 8th century BCE.</p>



<figure class="wp-block-image size-large"><img decoding="async" src="https://lh3.googleusercontent.com/pw/AP1GczNxRSiIW-leWnin3GrG91Wq5_7D6PN8lzcmbQabe0-rkFLLRAdTtIfoDFXDm-3pkX_kPn7DpHX9N8T8SGpZQTPtMbZ95ZorElvyaan9MbaQrLhSkoBfA7tuZWPG_ZCsLGoqme0p-dCsgJ9LgUvKSk9EGQ=w1634-h919-s-no?authuser=0" alt=""/></figure>



<p class="wp-block-paragraph">We hiked around the desert a little bit.</p>



<figure class="wp-block-image size-large"><a href="https://photos.google.com/share/AF1QipPeMKBhzfINGDoRokDKh3j5CayfsXNtc5Aml88xzq1RWOBB5eeh56sExp5icsoLSQ/photo/AF1QipNX7XuXQdCQrV4icrHnhMbY1fTnAP5yGr0tOMbN?key=RXowdEJYVUNCOXU1ZTBYbHFlZWx3bWk5dmZveXJR" target="_blank" rel=" noreferrer noopener"><img decoding="async" src="https://lh3.googleusercontent.com/pw/AP1GczOUy6h_4ISfTPSNldrhbUj4v4NymmnVzSOVHhYrozJxwnasI0D2h8W8Ej-wt8di6CqYysFqEbQT3C5Vn_D-zdbVQDWyXnm22bIDrQ_iyiMhLKw5lmvBcKmNUV7JcjHw5sLxCSsCUgGJcMOnff3D7u540w=w1634-h919-s-no?authuser=0" alt=""/></a></figure>



<p class="wp-block-paragraph">Then we stayed in the desert for the sunset. I normally don&#8217;t pay attention to the sunset, but it was pretty amazing to see how fast the sun actually set. </p>



<figure class="wp-block-image size-large"><a href="https://photos.google.com/share/AF1QipPeMKBhzfINGDoRokDKh3j5CayfsXNtc5Aml88xzq1RWOBB5eeh56sExp5icsoLSQ/photo/AF1QipMLC1uNGzAh03Txy-58U_rY__91LijJEJu-Rea5?key=RXowdEJYVUNCOXU1ZTBYbHFlZWx3bWk5dmZveXJR" target="_blank" rel=" noreferrer noopener"><img decoding="async" src="https://lh3.googleusercontent.com/pw/AP1GczPVrzNu_LRDyiM0e6ixRVNm9h8f64f8CI1XU9wR2hCRajYUcGcrcANlI5aek79evPbnfVxfkUyTQCSlSbmqm3zJQ8DHLzyji_yE6xpu8ZcrGfqmd2l-TYqAZ8XC_dALQrEHSyc1HS_j5ZgwgO4AFm3nxA=w1634-h919-s-no?authuser=0" alt=""/></a></figure>



<p class="wp-block-paragraph">Once the sun touched the horizon, 30 seconds later, it was gone.</p>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-8f761849 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<figure class="wp-block-image size-large"><a href="https://photos.google.com/share/AF1QipPeMKBhzfINGDoRokDKh3j5CayfsXNtc5Aml88xzq1RWOBB5eeh56sExp5icsoLSQ/photo/AF1QipOS4qFC6aWrP-yM9lLz8Cj5YABATxo6GJmW0_hG?key=RXowdEJYVUNCOXU1ZTBYbHFlZWx3bWk5dmZveXJR" target="_blank" rel=" noreferrer noopener"><img decoding="async" src="https://lh3.googleusercontent.com/pw/AP1GczPJr_AcqZziIvJ28Y_kkOy9S1sQxu_axLmfWrVtp6otZxGL0OO3kUObK7FF5Pj5_JrQ6k4wqh_Gc3nLGBtN4yxfy8Fp7b9CtnPchoJK3mj6sxqKfvMKQad-mQP0AHCGDuSMPV47tak3UWqDLcUvX6RY_A=w1634-h919-s-no?authuser=0" alt=""/></a></figure>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<figure class="wp-block-image size-large"><a href="https://photos.google.com/share/AF1QipPeMKBhzfINGDoRokDKh3j5CayfsXNtc5Aml88xzq1RWOBB5eeh56sExp5icsoLSQ/photo/AF1QipMt3yedQ6GwZJQoOmvbuTCHBJ8zLyjeLwOqDq1s?key=RXowdEJYVUNCOXU1ZTBYbHFlZWx3bWk5dmZveXJR" target="_blank" rel=" noreferrer noopener"><img decoding="async" src="https://lh3.googleusercontent.com/pw/AP1GczMPpjHfFM17_T-cwA2nI_00awiwHyacVZ58IcLnNC8vCaStksjYWB2Eo99187jjOw2X64ILc7F6D8pMIjjj-VSztBrLFMWshVcKKgLvsNxT3IVQ4nfk9RtOUzBPcQlonnv22_4-ctgKgubRqhBvnjzyOA=w1634-h919-s-no?authuser=0" alt=""/></a></figure>
</div>
</div>



<p class="wp-block-paragraph">For dinner, the staff at the camp prepared a feast for us &#8211; zarb, they called it.  It&#8217;s similar to the chicken/lamb on rice meals we had in the previous days, but this one was cooked underground inside a barrel.  This was the best meal in Jordan by far!</p>



<figure class="wp-block-image size-large"><a href="https://photos.google.com/share/AF1QipPeMKBhzfINGDoRokDKh3j5CayfsXNtc5Aml88xzq1RWOBB5eeh56sExp5icsoLSQ/photo/AF1QipPnohtT-F4l9hPfKeyca60yXwyDWJNtZ4Ft011N?key=RXowdEJYVUNCOXU1ZTBYbHFlZWx3bWk5dmZveXJR" target="_blank" rel=" noreferrer noopener"><img decoding="async" src="https://lh3.googleusercontent.com/pw/AP1GczO0B3SKzylqwLHvkygjkkqwV2oqOPdljz6O3HWvv1pR8ETV8p_zbKVeuruRS45H9IomlqMesGZU5jwU0_m9zMnzkNraqnZTQ_wlKCoHRBGPj305GqijcUnCGyXFnmdVkIuDrwweqJZ5lAGL-QvzyYNBLQ=w1634-h919-s-no?authuser=0" alt=""/></a></figure>



<p class="wp-block-paragraph">That night, we stayed in a camp in the desert.  The best part about it was being able to see stars without all the light pollution in the city, and hanging out with the rest of the tour group around a campfire.</p>



<p class="wp-block-paragraph">The worst part of it was the actual camping.  There was some running water, but no hot water.  To make it worse, we had to leave the next morning at 04:00 because we had a couple hours drive back through the Israeli border in time before it closed (what kind of border crossing closes during the day?).</p>



<p class="wp-block-paragraph">The desert was our last destination in Jordan, before we went back into Israel/Palestine (not to take sides here&#8230;), to visit the Dead Sea and Tel Aviv.</p>



<p class="wp-block-paragraph">More photos of Wadi Rum <a href="https://photos.google.com/share/AF1QipPeMKBhzfINGDoRokDKh3j5CayfsXNtc5Aml88xzq1RWOBB5eeh56sExp5icsoLSQ?key=RXowdEJYVUNCOXU1ZTBYbHFlZWx3bWk5dmZveXJR" target="_blank" rel="noreferrer noopener">here</a></p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.henrypoon.com/blog/2020/03/20/wadi-rum/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">5296</post-id>	</item>
		<item>
		<title>Jenkins pipeline for Spring with beta and prod stages and deployment rollback</title>
		<link>https://blog.henrypoon.com/blog/2017/03/09/jenkins-pipeline-for-spring-with-beta-and-prod-stages-and-deployment-rollback/</link>
					<comments>https://blog.henrypoon.com/blog/2017/03/09/jenkins-pipeline-for-spring-with-beta-and-prod-stages-and-deployment-rollback/#respond</comments>
		
		<dc:creator><![CDATA[hp]]></dc:creator>
		<pubDate>Thu, 09 Mar 2017 08:04:51 +0000</pubDate>
				<category><![CDATA[computer stuff]]></category>
		<category><![CDATA[9]]></category>
		<category><![CDATA[Apache Ant]]></category>
		<category><![CDATA[Apache Maven]]></category>
		<category><![CDATA[Build automation]]></category>
		<category><![CDATA[Chan]]></category>
		<category><![CDATA[COM]]></category>
		<category><![CDATA[Compiling tools]]></category>
		<category><![CDATA[Computing]]></category>
		<category><![CDATA[Const]]></category>
		<category><![CDATA[Continuous integration]]></category>
		<category><![CDATA[D]]></category>
		<category><![CDATA[Database]]></category>
		<category><![CDATA[Digital technology]]></category>
		<category><![CDATA[Download]]></category>
		<category><![CDATA[EAR]]></category>
		<category><![CDATA[future]]></category>
		<category><![CDATA[Go]]></category>
		<category><![CDATA[Google]]></category>
		<category><![CDATA[groovy]]></category>
		<category><![CDATA[Hole]]></category>
		<category><![CDATA[IDE]]></category>
		<category><![CDATA[IME]]></category>
		<category><![CDATA[It]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Java enterprise platform]]></category>
		<category><![CDATA[Jenkins]]></category>
		<category><![CDATA[Levant]]></category>
		<category><![CDATA[Password]]></category>
		<category><![CDATA[PATH]]></category>
		<category><![CDATA[Plug]]></category>
		<category><![CDATA[Port]]></category>
		<category><![CDATA[Reference]]></category>
		<category><![CDATA[Rolling]]></category>
		<category><![CDATA[Run]]></category>
		<category><![CDATA[Scripting languages]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[STR]]></category>
		<category><![CDATA[Thou]]></category>
		<category><![CDATA[Time]]></category>
		<category><![CDATA[URL]]></category>
		<category><![CDATA[Variable]]></category>
		<category><![CDATA[Z]]></category>
		<category><![CDATA[Zip]]></category>
		<guid isPermaLink="false">https://blog.henrypoon.com/?p=2614</guid>

					<description><![CDATA[In the past couple of days, I&#8217;ve been experimenting a bit with the Jenkins pipeline plugin to create a code deployment pipeline with independent beta and prod stages for a Spring Boot app. I even managed to add rolling back a deployment in case a prod deployment fails! It took me a bit of time [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">In the past couple of days, I&#8217;ve been experimenting a bit with the <a href="https://wiki.jenkins-ci.org/display/JENKINS/Pipeline+Plugin" target="_blank" rel="noopener">Jenkins pipeline plugin</a> to create a code deployment pipeline with independent beta and prod stages for a Spring Boot app. I even managed to add rolling back a deployment in case a prod deployment fails! It took me a bit of time to Google my way through how to do everything, so I figure I just lay it all out here in case it helps other people do the same thing.</p>



<p class="wp-block-paragraph">The nice thing about all of this is that I can push a code change to git, and Jenkins can build it, run through all the tests and then deploy to production automatically.</p>



<h1 class="wp-block-heading">Layout of a pipeline script</h1>



<p class="wp-block-paragraph">Pipeline scripts are written in <a rel="noopener" href="http://www.groovy-lang.org/" target="_blank">Groovy</a>, which is a variant of Java. In general, a pipeline script is laid out like this:</p>



<pre class="wp-block-code"><code lang="python" class="language-python">node {
    def SOME_CONSTANT = "whatever"
    ...

    stage('some stage name like Build') {
        // Stuff to do as a part of this stage
    }

    stage('another stage') {
        // More stuff
    }

    ...
}</code></pre>



<p class="wp-block-paragraph">Each stage represents a stage in the pipeline (e.g. building, beta deployment, prod deployment etc.)</p>



<h1 class="wp-block-heading">Defining some constants</h1>



<p class="wp-block-paragraph">First, a list of constants can be defined that can be used throughout the pipeline so that if the pipeline script gets reused somewhere, only these constants have to be changed. I&#8217;m not aware of anything that lets me reuse a pipeline in Jenkins without copying and pasting the code somewhere else so for now I&#8217;ll have to live with copying and pasting.</p>



<p class="wp-block-paragraph">My project uses Maven so I got Jenkins to download its own copy of Maven that it can use to execute builds and have defined it as a constant. The name I&#8217;ve given it in the Jenkins Global Tool Configuration is &#8220;Maven 3.3.9&#8221; exactly. My project also uses Tomcat so there are some Tomcat specific things in there that may or may not be relevant to your use case.</p>



<pre class="wp-block-code"><code lang="python" class="language-python">def MAVEN_HOME = tool 'Maven 3.3.9'
    def WORKSPACE = pwd()

    def PROJECT_NAME = "name-of-project"
    def WAR_PATH_RELATIVE = "App/target/${PROJECT_NAME}.war"
    def WAR_PATH_FULL = "${WORKSPACE}/${WAR_PATH_RELATIVE}"
    def TOMCAT_CTX_PATH_BETA = "Tomcat-context-path-for-the-beta-stage"
    def TOMCAT_CTX_PATH_PROD = "Tomcat-context-path-for-the-prod-stage"
    def GIT_REPO_URL = "URL-to-git-repo-ending-in-.git"</code></pre>



<h1 class="wp-block-heading">Preparation Stage</h1>



<p class="wp-block-paragraph">First, the code has to be retrieved from the repository before it gets built. Jenkins allows storing username/password pairs so that they can be referenced without having to write out the password in plaintext. Jenkins uses a &#8220;credential ID&#8221; for this.</p>



<pre class="wp-block-code"><code lang="python" class="language-python">    stage('Preparation') {
        git branch: "master",
        credentialsId: "credentials-ID-stored-in-Jenkins-that-can-access-the-git-repo",
        url: "${GIT_REPO_URL}"
    }</code></pre>



<h1 class="wp-block-heading">Build Stage</h1>



<p class="wp-block-paragraph">Next, the code must be built and unit tested. &#8220;mvn clean install&#8221; will do just that (depending on what you want, you can always put in a different maven goal). The junit command is just there to take the resulting XML that gets generated during the build process and posts a graph of how many tests were run for each build.</p>



<pre class="wp-block-code"><code lang="python" class="language-python">    stage('Build') {
        sh "'${MAVEN_HOME}/bin/mvn' clean install"
        junit '**/target/surefire-reports/TEST-*.xml'
    }
</code></pre>



<h1 class="wp-block-heading">Beta Stage</h1>



<p class="wp-block-paragraph">Once the build succeeds, you&#8217;ll want to deploy it to a beta environment, so integration tests can happen. The following happens at this stage:</p>



<ol class="wp-block-list"><li>Get the right credentials to get permissions to Tomcat</li><li>Call the deploy method to deploy the war file in Tomcat (more on that later)</li><li>If the deployment fails for whatever reason, print out the deployment log for debugging and fail the build</li><li>If the deployment succeeds, run the integration tests (the command to do this may differ based on use case)</li></ol>



<pre class="wp-block-code"><code lang="python" class="language-python">    stage('Beta') {
        withCredentials([[$class: 'UsernamePasswordMultiBinding',
            credentialsId: 'credential-id-for-tomcat',
            usernameVariable: 'USERNAME', passwordVariable: 'PASSWORD']]) {
                // Password is available as an env variable, but will be masked 
                // if you try to print it out any which way
                def output = deploy(WAR_PATH_FULL, TOMCAT_CTX_PATH_BETA,
                        env.USERNAME, env.PASSWORD)
                if (output.contains("FAIL - Deployed application at context path " + 
                        "/${TOMCAT_CTX_PATH_BETA} but context failed to start")) {
                    echo "----- Beta deployment log -----"
                    echo output
                    echo "-------------------------------"
                    currentBuild.result = 'FAILURE'
                    error "Beta stage deployment failure"
                }
            }

        echo "Running integration tests"
        sh "'${MAVEN_HOME}/bin/mvn' -Dtest=*IT test"
        junit '**/target/surefire-reports/TEST-*.xml'
    }</code></pre>



<p class="wp-block-paragraph">The deploy method is what takes care of the actual deployment to Tomcat, which is how the Jenkins build tells Tomcat about the newly built war file. The deploy method is below (be sure to change the server IP and port). Alternatively, I could have built my project as an embedded jar file, but that has a different challenge in figuring out how to get Jenkins to tell the OS to execute the newly built jar file as a particular user.</p>



<ol class="wp-block-list"><li>Based on the Tomcat context path, decide whether a beta or production deployment is happening</li><li>Make a copy of the build war file and add .prod or .beta to the end of it so as to keep the original</li><li>Set the Spring profile to use on the newly copied war file (more on that later)</li><li>Call the curl command to do the actual deployment to Tomcat (more on that later)</li></ol>



<pre class="wp-block-code"><code lang="python" class="language-python">def deploy(warPathFull, tomcatCtxPath, username, password) {
    def envSuffix = ""
    def isBeta = tomcatCtxPath.contains("beta")
    if (isBeta) {
        envSuffix = "beta"
    } else {
        envSuffix = "prod"
    }
    sh script: "cp ${warPathFull} ${warPathFull}.${envSuffix}" 
    setSpringProfile(warPathFull, isBeta)
    def output = sh script: "curl --upload-file '${warPathFull}.${envSuffix}' " +
            "'http://${username}:${password}@localhost:8081/manager/text/deploy" + 
            "?path=/${tomcatCtxPath}&amp;update=true'", returnStdout: true
    return output
}</code></pre>



<p class="wp-block-paragraph">In the case of my project, I&#8217;m building a single war file that does not have a Spring profile (beta/prod) defined. This means that I have to manually define this before I deploy the app to Tomcat since there are some things that differ between beta and prod like database URL&#8217;s. To do this, I wrote a method that opens the war file like a zip (jar/war files are zip files) and adds a line to my application.properties to define a Spring profile.</p>



<p class="wp-block-paragraph">Admittedly, doing this zip file manipulation seems kind of hacky. Alternatively, I could have defined my build such that I had a separate beta build and a prod build to avoid modifying the zip file, but the drawback is that I&#8217;d then have to build my code twice.</p>



<pre class="wp-block-code"><code lang="python" class="language-python">def setSpringProfile(warPathFull, isBeta) {
    def zipFileFullPath = warPathFull + "." + (isBeta ? "beta" : "prod")
    def zipIn = new File(zipFileFullPath)
    def zip = new ZipFile(zipIn)
    def zipTemp = File.createTempFile("temp_${System.nanoTime()}", 'zip')
    zipTemp.deleteOnExit()
    def zos = new ZipOutputStream(new FileOutputStream(zipTemp))
    def toModify = "WEB-INF/classes/application.properties"

    for(e in zip.entries()) {
        if(!e.name.equalsIgnoreCase(toModify)) {
            zos.putNextEntry(e)
            zos &lt;&lt; zip.getInputStream(e).bytes
        } else {
            zos.putNextEntry(new ZipEntry(toModify))
            zos &lt;&lt; zip.getInputStream(e).bytes
            zos &lt;&lt; ("\nspring.profiles.active=" + (isBeta ? "beta" : "prod")).bytes
        }
        zos.closeEntry()
    }

    zos.close()
    zipIn.delete()
    zipTemp.renameTo(zipIn)
}</code></pre>



<p class="wp-block-paragraph">A curl command to Tomcat is what actually does the deployment. To deploy a file to Tomcat, do the following below. This will deploy the war file to Tomcat and instantly run it, thus it will be accessible at the given context path.</p>



<pre class="wp-block-code"><code lang="bash" class="language-bash">curl --upload-file 'path-to-war-file' http://username:password@server-address:port/manager/text/deploy?path=/tomcat-context-path&amp;update=true</code></pre>



<h1 class="wp-block-heading">Prod Stage</h1>



<p class="wp-block-paragraph">The same kind of stuff happens in the prod stage as in the beta stage with a few exceptions. The following happens at this stage:</p>



<ol class="wp-block-list"><li>Get the right credentials to get permissions to Tomcat</li><li>Call the deploy method to deploy the war file in Tomcat (except this time it is prod)</li><li>If the deployment fails for whatever reason, print out the deployment log for debugging and roll back the deployment</li><li>If the deployment succeeds, save the build files, and then the pipeline is finished. Alternatively, smoke tests can be run at this point, but I did not implement this in my project</li></ol>



<p class="wp-block-paragraph">Rollback is important because if the deployment fails, you don&#8217;t want to be stuck with a broken environment. Since build artifacts are saved on successful deployments, these same artifacts can be brought back if future deployments fail. This means they can be redeployed so that the code can be fixed before another deployment happens.</p>



<pre class="wp-block-code"><code lang="python" class="language-python">    stage('Prod') {
        withCredentials([[$class: 'UsernamePasswordMultiBinding',
            credentialsId: 'credential-id-for-tomcat',
            usernameVariable: 'USERNAME', passwordVariable: 'PASSWORD']]) {
                // Password is available as an env variable, but will be masked 
                // if you try to print it out any which way
                def output = deploy(WAR_PATH_FULL, TOMCAT_CTX_PATH_PROD, env.USERNAME, env.PASSWORD)
                if (output.contains("FAIL - Deployed application at context path " + 
                        "/${TOMCAT_CTX_PATH_PROD} but context failed to start")) {
                    echo "Prod stage deployment failure, rolling back deployment"
                    echo "----- Prod deployment log -----"
                    echo output
                    echo "-------------------------------"
                    step([$class: 'CopyArtifact',
                            filter: "${WAR_PATH_RELATIVE}",
                            fingerprintArtifacts: true,
                            projectName: "${PROJECT_NAME}",
                            target: "${WAR_PATH_RELATIVE}.rollback"])
                    deploy(WAR_PATH_FULL + ".rollback/" + WAR_PATH_RELATIVE,
                            TOMCAT_CTX_PATH_PROD, env.USERNAME, env.PASSWORD)
                    currentBuild.result = 'FAILURE'
                    error "Prod deployment rolled back"
                } else {
                    archiveArtifacts artifacts: "${WAR_PATH_RELATIVE}*", fingerprint: true
                }
            }
    }
</code></pre>



<p class="wp-block-paragraph">At the end you get to have something like this:</p>


<div class="wp-block-image">
<figure class="aligncenter"><img data-recalc-dims="1" fetchpriority="high" decoding="async" width="600" height="882" src="https://i0.wp.com/blog.henrypoon.com/wp-content/uploads/2017/03/JenkinsPipeline.png?resize=600%2C882&#038;ssl=1" alt="" class="wp-image-2638"/></figure>
</div>


<p class="wp-block-paragraph">That pretty much sums up the whole Jenkins pipeline that I&#8217;ve been using lately for Spring projects!</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.henrypoon.com/blog/2017/03/09/jenkins-pipeline-for-spring-with-beta-and-prod-stages-and-deployment-rollback/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2614</post-id>	</item>
		<item>
		<title>War Memorial of Korea</title>
		<link>https://blog.henrypoon.com/blog/2014/07/11/war-memorial-of-korea/</link>
					<comments>https://blog.henrypoon.com/blog/2014/07/11/war-memorial-of-korea/#respond</comments>
		
		<dc:creator><![CDATA[hp]]></dc:creator>
		<pubDate>Sat, 12 Jul 2014 04:28:19 +0000</pubDate>
				<category><![CDATA[asia]]></category>
		<category><![CDATA[b-52 bomber]]></category>
		<category><![CDATA[Countries]]></category>
		<category><![CDATA[D]]></category>
		<category><![CDATA[EAR]]></category>
		<category><![CDATA[East Asia]]></category>
		<category><![CDATA[First Sino-Japanese War]]></category>
		<category><![CDATA[Flag]]></category>
		<category><![CDATA[Force]]></category>
		<category><![CDATA[Geography of Asia]]></category>
		<category><![CDATA[Go]]></category>
		<category><![CDATA[IDE]]></category>
		<category><![CDATA[ise]]></category>
		<category><![CDATA[It]]></category>
		<category><![CDATA[Japan]]></category>
		<category><![CDATA[korea]]></category>
		<category><![CDATA[Korea under Japanese rule]]></category>
		<category><![CDATA[Korean]]></category>
		<category><![CDATA[korean war]]></category>
		<category><![CDATA[Lag]]></category>
		<category><![CDATA[Levant]]></category>
		<category><![CDATA[Link]]></category>
		<category><![CDATA[Member states of the United Nations]]></category>
		<category><![CDATA[Military]]></category>
		<category><![CDATA[military history]]></category>
		<category><![CDATA[military vehicles]]></category>
		<category><![CDATA[Museum]]></category>
		<category><![CDATA[Outdoors]]></category>
		<category><![CDATA[Outside]]></category>
		<category><![CDATA[Republics]]></category>
		<category><![CDATA[rockets]]></category>
		<category><![CDATA[Sino-Japanese War]]></category>
		<category><![CDATA[south korea]]></category>
		<category><![CDATA[Tank]]></category>
		<category><![CDATA[tanks]]></category>
		<category><![CDATA[the Korean War]]></category>
		<category><![CDATA[Thou]]></category>
		<category><![CDATA[Vol]]></category>
		<category><![CDATA[War memorial]]></category>
		<category><![CDATA[war memorial of korea]]></category>
		<guid isPermaLink="false">http://henrypoon.mooo.com/blog/war-memorial-of-korea</guid>

					<description><![CDATA[The War Memorial of Korea is a place of remembrance and a museum for Korea&#8217;s military history and most of the exhibits are dedicated to the Korean War. Outside of the main building is an outdoors exhibit of many military vehicles, weapons, and aircraft. Directly in front of the building are the flags of the [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">The War Memorial of Korea is a place of remembrance and a museum for Korea&#8217;s military history and most of the exhibits are dedicated to the Korean War. Outside of the main building is an outdoors exhibit of many military vehicles, weapons, and aircraft. Directly in front of the building are the flags of the countries that assisted South Korea during the war and flags of different branches of their armed forces.</p>


<div class="wp-block-image">
<figure class="aligncenter"><a href="https://photos.google.com/share/AF1QipMOtKRU0CWYplEWZj7hddJcQNn6Sa9QjBMmcfj3Te1WbQ88sN5V0ljuR6H9QZy2wQ/photo/AF1QipOENYHGMX1bzZVAtNiX-lb1TZlfAYE_b218nrgg?key=Wnc4b0VnNzhlZG5ZX2R2OVpEd3VYUHFrazA1LUZn" target="_blank" rel="noreferrer noopener"><img decoding="async" src="https://lh5.googleusercontent.com/Zdqsm7VTk8tJy0xOeq39QTe2b424PD8mmlXuk4Cen87-=w1357-h763-no" alt=""/></a></figure>
</div>


<p class="has-text-align-center wp-block-paragraph"></p>



<p class="wp-block-paragraph">The war history exhibits revolved around conflicts that revolved around the Korean Peninsula such as the Russo-Japanese War and the Sino-Japanese War</p>


<div class="wp-block-image">
<figure class="aligncenter"><a href="https://photos.google.com/share/AF1QipMOtKRU0CWYplEWZj7hddJcQNn6Sa9QjBMmcfj3Te1WbQ88sN5V0ljuR6H9QZy2wQ/photo/AF1QipOtafx6v_vo0g5EBAjCrh3fiCmdqp_F-ZJfFEz5?key=Wnc4b0VnNzhlZG5ZX2R2OVpEd3VYUHFrazA1LUZn" target="_blank" rel="noreferrer noopener"><img decoding="async" src="https://lh4.googleusercontent.com/oCjTOEl10YjGxHK4Iz69zZsYw4v4oMCRJOMupsD16Rwp=w1358-h764-no" alt=""/></a></figure>
</div>


<p class="has-text-align-center wp-block-paragraph"></p>



<p class="wp-block-paragraph">To remember the soldiers, the names of fallen soldiers are inscribed on the walls</p>


<div class="wp-block-image">
<figure class="aligncenter"><a href="https://photos.google.com/share/AF1QipMOtKRU0CWYplEWZj7hddJcQNn6Sa9QjBMmcfj3Te1WbQ88sN5V0ljuR6H9QZy2wQ/photo/AF1QipNnlatq59yGnGLzqfmjtX6-ihu3RH3X1syQce22?key=Wnc4b0VnNzhlZG5ZX2R2OVpEd3VYUHFrazA1LUZn" target="_blank" rel="noreferrer noopener"><img data-recalc-dims="1" decoding="async" src="https://i0.wp.com/lh5.googleusercontent.com/-gIj2fnQO6cQ/U7ZIMM1rZSI/AAAAAAAAUbY/gWdQt0bhS5M/w652-h869-no/IMG_0161.JPG?w=1280&#038;ssl=1" alt=""/></a></figure>
</div>


<p class="has-text-align-center wp-block-paragraph"></p>



<p class="wp-block-paragraph">In the outdoor exhibit, I was surprised to see an American B-52 bomber here &#8211; I wish we got to go inside it though.</p>


<div class="wp-block-image">
<figure class="aligncenter"><a href="https://photos.google.com/share/AF1QipMOtKRU0CWYplEWZj7hddJcQNn6Sa9QjBMmcfj3Te1WbQ88sN5V0ljuR6H9QZy2wQ/photo/AF1QipMTmOTi1ZMkmtyPt_Q8ZoJ9700vunBtjfQy3pSX?key=Wnc4b0VnNzhlZG5ZX2R2OVpEd3VYUHFrazA1LUZn" target="_blank" rel="noreferrer noopener"><img decoding="async" src="https://lh6.googleusercontent.com/0TLdDyo-zlxobNs4Y9jlHxrfaStaTeNtXn3G63jLlx-u=w1358-h764-no" alt=""/></a></figure>
</div>


<p class="has-text-align-center wp-block-paragraph"></p>



<p class="wp-block-paragraph">No surprise, there were lots of tanks.</p>


<div class="wp-block-image">
<figure class="aligncenter"><a href="https://photos.google.com/share/AF1QipMOtKRU0CWYplEWZj7hddJcQNn6Sa9QjBMmcfj3Te1WbQ88sN5V0ljuR6H9QZy2wQ/photo/AF1QipNvtpIdUF8jMT-nqZLuDDnyihZWq84-AJlSWfDJ?key=Wnc4b0VnNzhlZG5ZX2R2OVpEd3VYUHFrazA1LUZn" target="_blank" rel="noreferrer noopener"><img decoding="async" src="https://lh4.googleusercontent.com/hWFlJnpXQ_DZLjmI5-DhGfqFSP_dx116-pPZwAaq29oJ=w1358-h764-no" alt=""/></a></figure>
</div>


<p class="has-text-align-center wp-block-paragraph"></p>



<p class="wp-block-paragraph">And rockets.</p>


<div class="wp-block-image">
<figure class="aligncenter"><a href="https://photos.google.com/share/AF1QipMOtKRU0CWYplEWZj7hddJcQNn6Sa9QjBMmcfj3Te1WbQ88sN5V0ljuR6H9QZy2wQ/photo/AF1QipOXNvjXTJCZImtV0s5uDJA_jjUyrbYD5eWbIAwu?key=Wnc4b0VnNzhlZG5ZX2R2OVpEd3VYUHFrazA1LUZn" target="_blank" rel="noreferrer noopener"><img decoding="async" src="https://lh3.googleusercontent.com/xmZp8fo2Jio9qau_WngSB-OUBeJjQZwKTd5Xg0YBJQTS=w1358-h764-no" alt=""/></a></figure>
</div>


<p class="has-text-align-center wp-block-paragraph"></p>



<p class="wp-block-paragraph">This museum definitely contains many interesting items and relics and is worth a visit for those interested in military history or looking at cool military vehicles. For many Koreans, I&#8217;m sure a lot of the museum content is still relevant to them as the Korean War is still technically on-going and it is clear that it is a huge part of their history.</p>



<p class="wp-block-paragraph">Link to more pictures: <a href="https://photos.google.com/share/AF1QipMOtKRU0CWYplEWZj7hddJcQNn6Sa9QjBMmcfj3Te1WbQ88sN5V0ljuR6H9QZy2wQ?key=Wnc4b0VnNzhlZG5ZX2R2OVpEd3VYUHFrazA1LUZn" target="_blank" rel="noreferrer noopener">here</a></p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.henrypoon.com/blog/2014/07/11/war-memorial-of-korea/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1864</post-id>	</item>
		<item>
		<title>Life Lessons from Moonlight Resonance (溏心風暴之家好月圓)</title>
		<link>https://blog.henrypoon.com/blog/2011/03/01/life-lessons-from-moonlight-resonance-%e6%ba%8f%e5%bf%83%e9%a2%a8%e6%9a%b4%e4%b9%8b%e5%ae%b6%e5%a5%bd%e6%9c%88%e5%9c%93/</link>
					<comments>https://blog.henrypoon.com/blog/2011/03/01/life-lessons-from-moonlight-resonance-%e6%ba%8f%e5%bf%83%e9%a2%a8%e6%9a%b4%e4%b9%8b%e5%ae%b6%e5%a5%bd%e6%9c%88%e5%9c%93/#respond</comments>
		
		<dc:creator><![CDATA[hp]]></dc:creator>
		<pubDate>Tue, 01 Mar 2011 19:59:49 +0000</pubDate>
				<category><![CDATA[opinions]]></category>
		<category><![CDATA[Articles]]></category>
		<category><![CDATA[Business]]></category>
		<category><![CDATA[Chinese people]]></category>
		<category><![CDATA[D]]></category>
		<category><![CDATA[Dream]]></category>
		<category><![CDATA[EAR]]></category>
		<category><![CDATA[Emotions]]></category>
		<category><![CDATA[Ethics]]></category>
		<category><![CDATA[Event]]></category>
		<category><![CDATA[Family]]></category>
		<category><![CDATA[Go]]></category>
		<category><![CDATA[Happiness]]></category>
		<category><![CDATA[Hole]]></category>
		<category><![CDATA[Human behavior]]></category>
		<category><![CDATA[IDE]]></category>
		<category><![CDATA[IME]]></category>
		<category><![CDATA[ise]]></category>
		<category><![CDATA[It]]></category>
		<category><![CDATA[Levant]]></category>
		<category><![CDATA[Lie]]></category>
		<category><![CDATA[Light]]></category>
		<category><![CDATA[Matt]]></category>
		<category><![CDATA[Moonlight Resonance]]></category>
		<category><![CDATA[Over]]></category>
		<category><![CDATA[Philosophy of love]]></category>
		<category><![CDATA[Pleasure]]></category>
		<category><![CDATA[Port]]></category>
		<category><![CDATA[Positive mental attitude]]></category>
		<category><![CDATA[The Go]]></category>
		<category><![CDATA[Thou]]></category>
		<category><![CDATA[Time]]></category>
		<category><![CDATA[TVB]]></category>
		<guid isPermaLink="false">http://henrypoon.mooo.com/blog/life-lessons-from-moonlight-resonance-%e6%ba%8f%e5%bf%83%e9%a2%a8%e6%9a%b4%e4%b9%8b%e5%ae%b6%e5%a5%bd%e6%9c%88%e5%9c%93</guid>

					<description><![CDATA[After watching Moonlight Resonance, I learned a few things about living life. That&#8217;s one of the good things about some TVB shows. Despite all the crying and arguing, there is always a lesson to be learned or a point of view of how people should live life. Although, I&#8217;m still pretty young and I haven&#8217;t [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>After watching Moonlight Resonance, I learned a few things about living life. That&#8217;s one of the good things about some TVB shows. Despite all the crying and arguing, there is always a lesson to be learned or a point of view of how people should live life. Although, I&#8217;m still pretty young and I haven&#8217;t experienced as many crises as the older folks, I still think I learned a lot of interesting things from this show.</p>
<p>The idea that an absolute right and wrong existing is false. The only &#8220;right&#8221; and &#8220;wrong&#8221; are what one values and believes. Everyone&#8217;s opinions toward something differs and everyone has reasons for why they are &#8220;right&#8221;. In the show, one of the conflicts that the characters had was who really owned the brand name in the moon cake business. For easy naming in this discussion, I will name the two parties Family A and family B. Family A had been using the name Jia Hao Yue Yuan (家好月圓) for decades, while Family B alleges that Family A allowed Family B to use this brand some time ago in the past. But Family A denies this and accuses Family B of swindling the brand name from them. This conflict eventually went to court. Each lawyer made their case with valid reasons. The conflict lay in who was better at convincing the judge using logic and reasoning. A good example that doesn&#8217;t relate to the show that many people know is the ending of Inception. Everyone had an idea for whether Cobb stayed in the dream or not in the end. There were reasons for both. Here are some more examples on a more serious note. The Iraq War, gay marriage, abortion, and stem cell research. These are all real controversies, and after looking at the arguments on both sides, they all have valid points. Both parties believe they are right, and that the other party is wrong.</p>
<p>A &#8220;right&#8221; and &#8220;wrong&#8221; way to live life exists too. Using the same names for the two families as before, Family A and B are both after happiness. But Family A believes this happiness can only be achieved through a loving family and not by how much money they have. Chinese people have a phrase that says, &#8220;人在天堂; 錢在銀行&#8221;, which means &#8220;The person is in Heaven, but their money is in the bank.&#8221; Family B believes that money makes them happy. They believe that by having lots of money, they can buy their way to happiness through material goods. During the show, they see Family A&#8217;s true happiness and togetherness as a family and feel jealousy towards them and made it their goal to ruin the happiness they enjoy. This part of the show shows the age old theme that &#8220;money can&#8217;t buy happiness&#8221;, but at the same time they add on to this. They show <em>how</em> to achieve happiness. The way to do it is by loving your family and spending time with them. In Chinese, we call this &#8220;家庭溫暖&#8221;, which literally means &#8220;family warmth&#8221;. Throughout the entire show, Family A can be seen to always be happy at the dinner table, when the whole family is together for dinner. Money never mattered to them, so long as the family was together.</p>
<p>Although the family lifestyles in the show are written like that, I still envied their happy lifestyle and togetherness as a family. It gives people something to work towards. It&#8217;s true that some people aim to make lots of money, but the amount of money is irrelevant. The important thing is to live happily. Despite everything I said, this is after all, only my perception of what is &#8220;right&#8221;. I&#8217;m sure some people will disagree and also have their own reasons to back up their point of view.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.henrypoon.com/blog/2011/03/01/life-lessons-from-moonlight-resonance-%e6%ba%8f%e5%bf%83%e9%a2%a8%e6%9a%b4%e4%b9%8b%e5%ae%b6%e5%a5%bd%e6%9c%88%e5%9c%93/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">904</post-id>	</item>
	</channel>
</rss>
