{"id":64394,"date":"2017-03-09T13:00:20","date_gmt":"2017-03-09T11:00:20","guid":{"rendered":"https:\/\/www.javacodegeeks.com\/?p=64394"},"modified":"2017-03-09T12:34:59","modified_gmt":"2017-03-09T10:34:59","slug":"pipeline-code-spring-boot-application","status":"publish","type":"post","link":"https:\/\/www.javacodegeeks.com\/2017\/03\/pipeline-code-spring-boot-application.html","title":{"rendered":"Pipeline as code with a Spring Boot application"},"content":{"rendered":"<p>This is the last in a <a href=\"https:\/\/pragmaticintegrator.wordpress.com\/tag\/continuous-delivery\/\">serie of posts<\/a> about continuous delivery based on <a href=\"https:\/\/gitlab.com\/palmapps\/continuous-delivery\">my local Docker compose stack<\/a> (see the <a href=\"https:\/\/www.javacodegeeks.com\/2017\/01\/set-continuous-delivery-stack.html\">first<\/a> and <a href=\"https:\/\/www.javacodegeeks.com\/2017\/02\/configure-jenkins-continuous-delivery-spring-boot-application.html\">second post<\/a> here). In this post I use a simple <a href=\"https:\/\/projects.spring.io\/spring-boot\/\">Spring Boot<\/a> project to show how to make use of the \u2018<a href=\"https:\/\/go.cloudbees.com\/docs\/cloudbees-documentation\/cookbook\/book.html#pipeline-as-code\">pipeline as code<\/a>\u2018 concept. Please note that this is only an example and much, much more is possible. The application I use is taken from the <a href=\"https:\/\/projects.spring.io\/spring-boot\/#quick-start\">Spring Boot site<\/a>. The <a href=\"https:\/\/jenkins.io\/doc\/book\/pipeline\/jenkinsfile\/\">Jenkinsfile<\/a> is inspired by the one in <a href=\"http:\/\/christoph-burmeister.eu\/?p=3050\">this post<\/a> but I had to modify some things to have it work with my stack. The sources of my project can be found <a href=\"https:\/\/gitlab.com\/palmapps-pipeline-as-code\/hello-world\">here<\/a>. I will explain the most important snippets in this post.<br \/>\nThe pipeline I use contains the following stages:<\/p>\n<ul>\n<li><a href=\"#build_stage\">build stage<\/a><\/li>\n<li><a href=\"#deploy_stage\">deploy stage<\/a><\/li>\n<li><a href=\"#test_stage\">smoke test stage<\/a><\/li>\n<\/ul>\n<p><strong><a>build stage<\/a><\/strong><br \/>\nIn the build stage I make use of <a href=\"https:\/\/pragmaticintegrator.wordpress.com\/2017\/02\/07\/configure-jenkins-for-continuous-delivery-of-a-spring-boot-application\/#config_gitlab_plugin\">the GitLab plugin<\/a> to checkout the sources of my project. I also put the current commitId in a textFile in the work directory. Next I use Maven (the one we called \u2018M3\u2019 in the Jenkins configuration as I described <a href=\"https:\/\/pragmaticintegrator.wordpress.com\/2017\/02\/07\/configure-jenkins-for-continuous-delivery-of-a-spring-boot-application\/#add_maven_installation\">here<\/a>) to package the code. I also make sure the commitId is passed as parameter to Maven.<\/p>\n<p><strong><a>deploy stage<\/a><\/strong><br \/>\nin the deploy step I shutdown a running instance of the application by posting \u2018true\u2019 to the \/shutdown path. Then I simply run the jar I built in the previous step. After that the job waits until the application responds to a simple request.<\/p>\n<p><strong><a>smoke test<\/a><\/strong><br \/>\nIn this simple test step I compare the returned commitId of my deployed service with the commitId we got when I checked out the latest committed code. If everything went well these two id should match, if not something in the chain went wrong.<\/p>\n<p>That\u2019s all for this example. Lets see what this means for the source code. Since it is a Maven project I start with the pom.xml:<\/p>\n<pre class=\"brush:xml\">&lt;dependencies&gt;\r\n  &lt;dependency&gt;\r\n    &lt;groupId&gt;org.springframework.boot&lt;\/groupId&gt;\r\n    &lt;artifactId&gt;spring-boot-starter-web&lt;\/artifactId&gt;\r\n  &lt;\/dependency&gt;\r\n  &lt;dependency&gt;\r\n    &lt;!-- used for metrics like status, health etc --&gt;\r\n    &lt;groupId&gt;org.springframework.boot&lt;\/groupId&gt;\r\n    &lt;artifactId&gt;spring-boot-starter-actuator&lt;\/artifactId&gt;\r\n  &lt;\/dependency&gt;\r\n  &lt;dependency&gt;\r\n    &lt;!-- used for unit tests --&gt;\r\n    &lt;groupId&gt;org.springframework.boot&lt;\/groupId&gt;\r\n    &lt;artifactId&gt;spring-boot-starter-test&lt;\/artifactId&gt;\r\n    &lt;scope&gt;test&lt;\/scope&gt;\r\n  &lt;\/dependency&gt;\r\n&lt;\/dependencies&gt;<\/pre>\n<p>No special dependencies are necessary for this project. The \u2018<a href=\"https:\/\/projects.spring.io\/spring-boot\/\">spring-boot-starter-web<\/a>\u2018 is used for our REST controller. The \u2018<a href=\"https:\/\/spring.io\/guides\/gs\/actuator-service\/\">sprint-boot-starter-actuator<\/a>\u2018 can be used for checking the health and <a href=\"http:\/\/docs.spring.io\/spring-boot\/docs\/current\/reference\/htmlsingle\/#production-ready\">much more<\/a>.<br \/>\nFinally the \u2018spring-boot-starter-test\u2019 is used to be able to (unit) test the controller.<br \/>\nLets have a look at the Java sources. The Application just starts the Spring Boot application. The Controller class is also very basic:<div style=\"display:inline-block; margin: 15px 0;\"> <div id=\"adngin-JavaCodeGeeks_incontent_video-0\" style=\"display:inline-block;\"><\/div> <\/div><\/p>\n<pre class=\"brush:java\">package hello;\r\n\r\nimport org.springframework.web.bind.annotation.RestController;\r\nimport org.springframework.web.bind.annotation.RequestMapping;\r\n\r\n@RestController\r\npublic class HelloController {\r\n   \r\n  @RequestMapping(\"\/\")\r\n  public String index() {\r\n    return \"Greetings from Spring Boot!\";\r\n  }    \r\n}<\/pre>\n<p>As you can see I simply return a fixed string when a GET request is coming in at \u2018\/\u2019. The test class has the following test code:<\/p>\n<pre class=\"brush:java\">\/**\r\n * Created by pascal on 19\/01\/2017.\r\n *\/\r\n@RunWith(SpringRunner.class)\r\n@SpringBootTest\r\n@AutoConfigureMockMvc\r\npublic class HelloControllerTest {\r\n\r\n    @Autowired\r\n    private MockMvc mvc;\r\n\r\n    @Test\r\n    public void getHello() throws Exception {\r\n        mvc.perform(MockMvcRequestBuilders.get(\"\/\").accept(MediaType.APPLICATION_JSON))\r\n                .andExpect(status().isOk())\r\n                .andExpect(content().string(equalTo(\"Greetings from Spring Boot!\")));\r\n    }\r\n}<\/pre>\n<p>This is also straightforward I guess, I expect the fixed string as a response to a GET request. Next to the Java code there is the \u2018application.properties\u2019 file:<\/p>\n<pre class=\"brush:bash\">server.port=8888\r\ninfo.app.name=@project.name@\r\ninfo.app.description=@project.description@\r\ninfo.app.version=@project.version@\r\ninfo.app.commitid=@commitid@\r\nendpoints.shutdown.enabled=true<\/pre>\n<p>Besides two functional properties, the port we are running the application on (8888) and the ability to shutdown the application by calling the endpoint (endpoints.shutdown.enabled=true), the rest is meant to be shown when calling the endpoint \u2018\/info\u2019. The parameters @\u2026@ will be replaced with real values by Maven since we filter the resources:<\/p>\n<pre class=\"brush:xml\">...\r\n&lt;resources&gt;\r\n  &lt;!-- used for variable substitution in application.properties --&gt;\r\n  &lt;!-- https:\/\/github.com\/spring-projects\/spring-boot\/wiki\/Spring-Boot-1.3-Release-Notes#maven-resources-filtering --&gt;\r\n  &lt;resource&gt;\r\n    &lt;directory&gt;src\/main\/resources&lt;\/directory&gt;\r\n    &lt;filtering&gt;true&lt;\/filtering&gt;\r\n  &lt;\/resource&gt;\r\n&lt;\/resources&gt;\r\n...<\/pre>\n<p>Finally we have the Jenkinsfile in the project:<\/p>\n<pre class=\"brush:java\">import groovy.json.JsonSlurper;\r\n \r\nproperties([[$class: 'GitLabConnectionProperty', gitLabConnection: 'my-gitlab-connection']])\r\n\r\nnode{\r\n    stage 'Build, Test and Package'\r\n    env.PATH = \"${tool 'M3'}\/bin:${env.PATH}\"\r\n    checkout scm\r\n    \/\/ workaround, taken from https:\/\/github.com\/jenkinsci\/pipeline-examples\/blob\/master\/pipeline-examples\/gitcommit\/gitcommit.groovy\r\n    def commitid = sh(returnStdout: true, script: 'git rev-parse HEAD').trim()\r\n    def workspacePath = pwd()\r\n    sh \"echo ${commitid} &gt; ${workspacePath}\/expectedCommitid.txt\"\r\n    \r\n    withMaven(\r\n                maven: 'M3',\r\n                mavenSettingsConfig: 'a1adf035-653b-410d-b5a6-16b6da77b322',\r\n                mavenLocalRepo: '.repository') {\r\n    \r\n            \/\/ Run the maven build\r\n            sh \"mvn clean package -Dcommitid=${commitid}\"\r\n        }\r\n}\r\n \r\nnode{\r\n    stage 'Stop, Deploy and Start'\r\n    \/\/ shutdown\r\n    sh 'curl -X POST http:\/\/localhost:8888\/shutdown || true'\r\n    \/\/ copy file to target location\r\n    sh 'cp target\/*.jar \/tmp\/'\r\n    \/\/ start the application\r\n    sh 'nohup java -jar \/tmp\/*.jar &amp;'\r\n    \/\/ wait for application to respond\r\n    sh 'while ! httping -qc1 http:\/\/localhost:8888 ; do sleep 1 ; done'\r\n}\r\n \r\nnode{\r\n    stage 'Smoketest'\r\n    def workspacePath = pwd()\r\n    sh \"curl --retry-delay 10 --retry 5 http:\/\/localhost:8888\/info -o ${workspacePath}\/info.json\"\r\n    if (deploymentOk()){\r\n        return 0\r\n    } else {\r\n        return 1\r\n    }\r\n}\r\n \r\ndef deploymentOk(){\r\n    def workspacePath = pwd()\r\n    expectedCommitid = new File(\"${workspacePath}\/expectedCommitid.txt\").text.trim()\r\n    actualCommitid = readCommitidFromJson()\r\n    println \"expected commitid from txt: ${expectedCommitid}\"\r\n    println \"actual commitid from json: ${actualCommitid}\"\r\n    return expectedCommitid == actualCommitid\r\n}\r\n \r\ndef readCommitidFromJson() {\r\n    def workspacePath = pwd()\r\n    def slurper = new JsonSlurper()\r\n    def json = slurper.parseText(new File(\"${workspacePath}\/info.json\").text)\r\n    def commitid = json.app.commitid\r\n    return commitid\r\n}<\/pre>\n<p>I described the working of the script previously. There are three important constants that must match with our Jenkins installation:<\/p>\n<ul>\n<li>In the statement: <code>properties([[$class: 'GitLabConnectionProperty', gitLabConnection: 'my-gitlab-connection']])<\/code> \u2018<strong>my-gitlab-connection<\/strong>\u2018 matches the name I gave my gitlabConnection in the Jenkins plugin as I described <a href=\"https:\/\/pragmaticintegrator.wordpress.com\/2017\/02\/07\/configure-jenkins-for-continuous-delivery-of-a-spring-boot-application\/#config_gitlab_plugin\">here<\/a>.<\/li>\n<li>As I described before the \u2018M3\u2019 in the statement:<br \/>\n<code>env.PATH = \"${tool 'M3'}\/bin:${env.PATH}\"<\/code> must match the Maven installation in Jenkins as I described <a href=\"https:\/\/pragmaticintegrator.wordpress.com\/2017\/02\/07\/configure-jenkins-for-continuous-delivery-of-a-spring-boot-application\/#add_maven_installation\">here<\/a>.<\/li>\n<li>Finally there is the line <code> mavenSettingsConfig: 'a1adf035-653b-410d-b5a6-16b6da77b322'<\/code>. The id mentioned here is the one copied from the settings file I set up with Config File Provider plugin as described <a href=\"https:\/\/pragmaticintegrator.wordpress.com\/2017\/02\/07\/configure-jenkins-for-continuous-delivery-of-a-spring-boot-application\/#config_nexus\">here<\/a>.<\/li>\n<\/ul>\n<p>That\u2019s all about the sources of the project. Let me show you next how to create the pipeline job in Jenkins. In the dashboard choose to create a new job of the type \u2018pipeline\u2019:<br \/>\n<a href=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/03\/screenshot-at-feb-12-16-07-46.png\"><img decoding=\"async\" class=\"aligncenter wp-image-64408\" src=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/03\/screenshot-at-feb-12-16-07-46.png\" width=\"860\" height=\"703\" srcset=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/03\/screenshot-at-feb-12-16-07-46.png 1000w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/03\/screenshot-at-feb-12-16-07-46-300x245.png 300w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/03\/screenshot-at-feb-12-16-07-46-768x628.png 768w\" sizes=\"(max-width: 860px) 100vw, 860px\" \/><\/a><br \/>\nNext configure this job where the most important thing is to use the Jenkinsfile obtained from git. To configure this we have to use the username\/password to log in into Gitlab (I haven\u2019t found a way to use the Gitlab plugin here yet. You can also use another repo here if you want to keep your Jenkinsfiles separate from your project sources):<br \/>\n<a href=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/03\/screenshot-at-feb-12-16-18-45.png\"><img decoding=\"async\" class=\"aligncenter wp-image-64409\" src=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/03\/screenshot-at-feb-12-16-18-45.png\" width=\"860\" height=\"683\" srcset=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/03\/screenshot-at-feb-12-16-18-45.png 948w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/03\/screenshot-at-feb-12-16-18-45-300x238.png 300w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/03\/screenshot-at-feb-12-16-18-45-768x610.png 768w\" sizes=\"(max-width: 860px) 100vw, 860px\" \/><\/a><br \/>\nNow when I run the job it will fail at the last step with the following error:<\/p>\n<blockquote>\n<p>org.jenkinsci.plugins.scriptsecurity.sandbox.RejectedAccessException: Scripts not permitted to use new java.io.File java.lang.String<br \/>\nat org.jenkinsci.plugins.scriptsecurity.sandbox.whitelists.StaticWhitelist.rejectNew(StaticWhitelist.java:187)<br \/>\n\u2026.<\/p>\n<\/blockquote>\n<p>There is one final setting to do for this job to run successful. By default certain actions are not allowed by the pipeline job, so I have to tell Jenkins that in this case they are allowed.<br \/>\nTo do this go to \u2018Manage Jenkins\u2019 and go to the \u2018In-process Script Approval\u2019:<br \/>\n<a href=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/03\/screenshot-at-mar-08-07-12-58.png\"><img decoding=\"async\" class=\"aligncenter wp-image-64410\" src=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/03\/screenshot-at-mar-08-07-12-58.png\" width=\"860\" height=\"55\" srcset=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/03\/screenshot-at-mar-08-07-12-58.png 885w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/03\/screenshot-at-mar-08-07-12-58-300x19.png 300w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/03\/screenshot-at-mar-08-07-12-58-768x49.png 768w\" sizes=\"(max-width: 860px) 100vw, 860px\" \/><\/a><br \/>\nThere is a mention about a possible security vulnerability which you have to approve before the job will allow the action to happen:<br \/>\n<a href=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/03\/screenshot-at-mar-08-07-13-41.png\"><img decoding=\"async\" class=\"aligncenter wp-image-64411\" src=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/03\/screenshot-at-mar-08-07-13-41.png\" width=\"860\" height=\"692\" srcset=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/03\/screenshot-at-mar-08-07-13-41.png 936w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/03\/screenshot-at-mar-08-07-13-41-300x241.png 300w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/03\/screenshot-at-mar-08-07-13-41-768x618.png 768w\" sizes=\"(max-width: 860px) 100vw, 860px\" \/><\/a><br \/>\nAfter clicking the \u2018Approve\u2019 button en rerun the job there will be a second vulnerability which has to be approved for the job to finish successfully.<br \/>\nNow the build will be successful for all three stages as shown in the dashboard:<br \/>\n<a href=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/03\/screenshot-at-mar-08-07-26-35.png\"><img decoding=\"async\" class=\"aligncenter wp-image-64412 size-full\" src=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/03\/screenshot-at-mar-08-07-26-35.png\" width=\"666\" height=\"742\" srcset=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/03\/screenshot-at-mar-08-07-26-35.png 666w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/03\/screenshot-at-mar-08-07-26-35-269x300.png 269w\" sizes=\"(max-width: 666px) 100vw, 666px\" \/><\/a><br \/>\nThis concludes the example of continuous delivery and pipeline as code. As mentioned before this is just a very simple example of a pipeline but you could use it to get started with the concept and take much more out of it.<\/p>\n<div class=\"attribution\">\n<table>\n<tbody>\n<tr>\n<td><span class=\"reference\">Reference: <\/span><\/td>\n<td><a href=\"https:\/\/pragmaticintegrator.wordpress.com\/2017\/03\/08\/pipeline-as-code-with-a-spring-boot-application\/\">Pipeline as code with a Spring Boot application<\/a> from our <a href=\"http:\/\/www.javacodegeeks.com\/join-us\/jcg\/\">JCG partner<\/a> Pascal Alma at the <a href=\"http:\/\/pragmaticintegrator.wordpress.com\/\">The Pragmatic Integrator<\/a> blog.<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>This is the last in a serie of posts about continuous delivery based on my local Docker compose stack (see the first and second post here). In this post I use a simple Spring Boot project to show how to make use of the \u2018pipeline as code\u2018 concept. Please note that this is only an &hellip;<\/p>\n","protected":false},"author":366,"featured_media":240,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[8],"tags":[30,854],"class_list":["post-64394","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-enterprise-java","tag-spring","tag-spring-boot"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Pipeline as code with a Spring Boot application - Java Code Geeks<\/title>\n<meta name=\"description\" content=\"This is the last in a serie of posts about continuous delivery based on my local Docker compose stack (see the first and second post here). In this post I\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.javacodegeeks.com\/2017\/03\/pipeline-code-spring-boot-application.html\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Pipeline as code with a Spring Boot application - Java Code Geeks\" \/>\n<meta property=\"og:description\" content=\"This is the last in a serie of posts about continuous delivery based on my local Docker compose stack (see the first and second post here). In this post I\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.javacodegeeks.com\/2017\/03\/pipeline-code-spring-boot-application.html\" \/>\n<meta property=\"og:site_name\" content=\"Java Code Geeks\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/javacodegeeks\" \/>\n<meta property=\"article:published_time\" content=\"2017-03-09T11:00:20+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"150\" \/>\n\t<meta property=\"og:image:height\" content=\"150\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Pascal Alma\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@https:\/\/twitter.com\/paskal_1973\" \/>\n<meta name=\"twitter:site\" content=\"@javacodegeeks\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Pascal Alma\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"7 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2017\\\/03\\\/pipeline-code-spring-boot-application.html#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2017\\\/03\\\/pipeline-code-spring-boot-application.html\"},\"author\":{\"name\":\"Pascal Alma\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/person\\\/a4c0bb5bfa87eb00be92c7a1d293fecf\"},\"headline\":\"Pipeline as code with a Spring Boot application\",\"datePublished\":\"2017-03-09T11:00:20+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2017\\\/03\\\/pipeline-code-spring-boot-application.html\"},\"wordCount\":915,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2017\\\/03\\\/pipeline-code-spring-boot-application.html#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/spring-logo.jpg\",\"keywords\":[\"Spring\",\"Spring Boot\"],\"articleSection\":[\"Enterprise Java\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.javacodegeeks.com\\\/2017\\\/03\\\/pipeline-code-spring-boot-application.html#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2017\\\/03\\\/pipeline-code-spring-boot-application.html\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2017\\\/03\\\/pipeline-code-spring-boot-application.html\",\"name\":\"Pipeline as code with a Spring Boot application - Java Code Geeks\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2017\\\/03\\\/pipeline-code-spring-boot-application.html#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2017\\\/03\\\/pipeline-code-spring-boot-application.html#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/spring-logo.jpg\",\"datePublished\":\"2017-03-09T11:00:20+00:00\",\"description\":\"This is the last in a serie of posts about continuous delivery based on my local Docker compose stack (see the first and second post here). In this post I\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2017\\\/03\\\/pipeline-code-spring-boot-application.html#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.javacodegeeks.com\\\/2017\\\/03\\\/pipeline-code-spring-boot-application.html\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2017\\\/03\\\/pipeline-code-spring-boot-application.html#primaryimage\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/spring-logo.jpg\",\"contentUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/spring-logo.jpg\",\"width\":150,\"height\":150,\"caption\":\"spring-interview-questions-answers\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2017\\\/03\\\/pipeline-code-spring-boot-application.html#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Java\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/category\\\/java\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Enterprise Java\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/category\\\/java\\\/enterprise-java\"},{\"@type\":\"ListItem\",\"position\":4,\"name\":\"Pipeline as code with a Spring Boot application\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#website\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\",\"name\":\"Java Code Geeks\",\"description\":\"Java Developers Resource Center\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\"},\"alternateName\":\"JCG\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.javacodegeeks.com\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\",\"name\":\"Exelixis Media P.C.\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2022\\\/06\\\/exelixis-logo.png\",\"contentUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2022\\\/06\\\/exelixis-logo.png\",\"width\":864,\"height\":246,\"caption\":\"Exelixis Media P.C.\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/www.facebook.com\\\/javacodegeeks\",\"https:\\\/\\\/x.com\\\/javacodegeeks\"]},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/person\\\/a4c0bb5bfa87eb00be92c7a1d293fecf\",\"name\":\"Pascal Alma\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/53ba6f041ccc86b6efd6278d4bcffecc424dc8eeaca5593acab22ae19748f5cb?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/53ba6f041ccc86b6efd6278d4bcffecc424dc8eeaca5593acab22ae19748f5cb?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/53ba6f041ccc86b6efd6278d4bcffecc424dc8eeaca5593acab22ae19748f5cb?s=96&d=mm&r=g\",\"caption\":\"Pascal Alma\"},\"description\":\"Pascal is a senior JEE Developer and Architect at 4Synergy in The Netherlands. Pascal has been designing and building J2EE applications since 2001. He is particularly interested in Open Source toolstack (Mule, Spring Framework, JBoss) and technologies like Web Services, SOA and Cloud technologies. Specialties: JEE, SOA, Mule ESB, Maven, Cloud Technology, Amazon AWS.\",\"sameAs\":[\"http:\\\/\\\/pragmaticintegrator.wordpress.com\\\/\",\"http:\\\/\\\/www.linkedin.com\\\/in\\\/pascalalma\",\"https:\\\/\\\/x.com\\\/https:\\\/\\\/twitter.com\\\/paskal_1973\"],\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/author\\\/pascal-alma\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Pipeline as code with a Spring Boot application - Java Code Geeks","description":"This is the last in a serie of posts about continuous delivery based on my local Docker compose stack (see the first and second post here). In this post I","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.javacodegeeks.com\/2017\/03\/pipeline-code-spring-boot-application.html","og_locale":"en_US","og_type":"article","og_title":"Pipeline as code with a Spring Boot application - Java Code Geeks","og_description":"This is the last in a serie of posts about continuous delivery based on my local Docker compose stack (see the first and second post here). In this post I","og_url":"https:\/\/www.javacodegeeks.com\/2017\/03\/pipeline-code-spring-boot-application.html","og_site_name":"Java Code Geeks","article_publisher":"https:\/\/www.facebook.com\/javacodegeeks","article_published_time":"2017-03-09T11:00:20+00:00","og_image":[{"width":150,"height":150,"url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg","type":"image\/jpeg"}],"author":"Pascal Alma","twitter_card":"summary_large_image","twitter_creator":"@https:\/\/twitter.com\/paskal_1973","twitter_site":"@javacodegeeks","twitter_misc":{"Written by":"Pascal Alma","Est. reading time":"7 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.javacodegeeks.com\/2017\/03\/pipeline-code-spring-boot-application.html#article","isPartOf":{"@id":"https:\/\/www.javacodegeeks.com\/2017\/03\/pipeline-code-spring-boot-application.html"},"author":{"name":"Pascal Alma","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/person\/a4c0bb5bfa87eb00be92c7a1d293fecf"},"headline":"Pipeline as code with a Spring Boot application","datePublished":"2017-03-09T11:00:20+00:00","mainEntityOfPage":{"@id":"https:\/\/www.javacodegeeks.com\/2017\/03\/pipeline-code-spring-boot-application.html"},"wordCount":915,"commentCount":0,"publisher":{"@id":"https:\/\/www.javacodegeeks.com\/#organization"},"image":{"@id":"https:\/\/www.javacodegeeks.com\/2017\/03\/pipeline-code-spring-boot-application.html#primaryimage"},"thumbnailUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg","keywords":["Spring","Spring Boot"],"articleSection":["Enterprise Java"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.javacodegeeks.com\/2017\/03\/pipeline-code-spring-boot-application.html#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.javacodegeeks.com\/2017\/03\/pipeline-code-spring-boot-application.html","url":"https:\/\/www.javacodegeeks.com\/2017\/03\/pipeline-code-spring-boot-application.html","name":"Pipeline as code with a Spring Boot application - Java Code Geeks","isPartOf":{"@id":"https:\/\/www.javacodegeeks.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.javacodegeeks.com\/2017\/03\/pipeline-code-spring-boot-application.html#primaryimage"},"image":{"@id":"https:\/\/www.javacodegeeks.com\/2017\/03\/pipeline-code-spring-boot-application.html#primaryimage"},"thumbnailUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg","datePublished":"2017-03-09T11:00:20+00:00","description":"This is the last in a serie of posts about continuous delivery based on my local Docker compose stack (see the first and second post here). In this post I","breadcrumb":{"@id":"https:\/\/www.javacodegeeks.com\/2017\/03\/pipeline-code-spring-boot-application.html#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.javacodegeeks.com\/2017\/03\/pipeline-code-spring-boot-application.html"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.javacodegeeks.com\/2017\/03\/pipeline-code-spring-boot-application.html#primaryimage","url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg","contentUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg","width":150,"height":150,"caption":"spring-interview-questions-answers"},{"@type":"BreadcrumbList","@id":"https:\/\/www.javacodegeeks.com\/2017\/03\/pipeline-code-spring-boot-application.html#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.javacodegeeks.com\/"},{"@type":"ListItem","position":2,"name":"Java","item":"https:\/\/www.javacodegeeks.com\/category\/java"},{"@type":"ListItem","position":3,"name":"Enterprise Java","item":"https:\/\/www.javacodegeeks.com\/category\/java\/enterprise-java"},{"@type":"ListItem","position":4,"name":"Pipeline as code with a Spring Boot application"}]},{"@type":"WebSite","@id":"https:\/\/www.javacodegeeks.com\/#website","url":"https:\/\/www.javacodegeeks.com\/","name":"Java Code Geeks","description":"Java Developers Resource Center","publisher":{"@id":"https:\/\/www.javacodegeeks.com\/#organization"},"alternateName":"JCG","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.javacodegeeks.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.javacodegeeks.com\/#organization","name":"Exelixis Media P.C.","url":"https:\/\/www.javacodegeeks.com\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/logo\/image\/","url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","contentUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","width":864,"height":246,"caption":"Exelixis Media P.C."},"image":{"@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/javacodegeeks","https:\/\/x.com\/javacodegeeks"]},{"@type":"Person","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/person\/a4c0bb5bfa87eb00be92c7a1d293fecf","name":"Pascal Alma","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/53ba6f041ccc86b6efd6278d4bcffecc424dc8eeaca5593acab22ae19748f5cb?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/53ba6f041ccc86b6efd6278d4bcffecc424dc8eeaca5593acab22ae19748f5cb?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/53ba6f041ccc86b6efd6278d4bcffecc424dc8eeaca5593acab22ae19748f5cb?s=96&d=mm&r=g","caption":"Pascal Alma"},"description":"Pascal is a senior JEE Developer and Architect at 4Synergy in The Netherlands. Pascal has been designing and building J2EE applications since 2001. He is particularly interested in Open Source toolstack (Mule, Spring Framework, JBoss) and technologies like Web Services, SOA and Cloud technologies. Specialties: JEE, SOA, Mule ESB, Maven, Cloud Technology, Amazon AWS.","sameAs":["http:\/\/pragmaticintegrator.wordpress.com\/","http:\/\/www.linkedin.com\/in\/pascalalma","https:\/\/x.com\/https:\/\/twitter.com\/paskal_1973"],"url":"https:\/\/www.javacodegeeks.com\/author\/pascal-alma"}]}},"_links":{"self":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts\/64394","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/users\/366"}],"replies":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/comments?post=64394"}],"version-history":[{"count":0,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts\/64394\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/media\/240"}],"wp:attachment":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/media?parent=64394"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/categories?post=64394"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/tags?post=64394"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}