====== Grails 3 Application Guide ====== Thanks to Grails 3 is based on Spring Boot, we can use tons of cool feature from Spring Boot and Grails 3 is very friendly to amazing other Spring Frameworks. Document correct on Grails 3.2.6 ====== Configuration File ====== ===== User Environment Variable on the server ===== Spring Boot inject environment variable when application starts meaning value of SUPPORT_PAGE_JVM_ROUTE in app handler, not one in machine that builds war tomcat: jvmRoute: ${SUPPORT_PAGE_JVM_ROUTE} ===== Access to Variable in application.yml ===== User annotation org.springframework.beans.factory.annotation.Value @Value('${tomcat.jvmRoute}') String jvmRouteString ====== Environment Specific War/Jar ====== We can create environment specific War/Jar file. What you need is environment specific application.yml For instance, support page war for errigalqa, you need to create application-errigalqa.yml You don't need to redefine all config values in application.yml, only ones you want to override such as dataSource. To build war, all you need is put **"-Dgrails.env=errigalqa"** before grails command. Benefit of this is very simple deployment. You don't need to put configuration file, tomcat container on deployment server. In practice, you may need startup script that define Environment Variable. Drawback of this are * multiple different war for each environment * multiple build process may required for each environment Those drawbacks could be overcome with more automated build process ===== Graceful Shutdown ===== Do **"kill "** (no options such as -9) will do graceful shutdown and will call BootStrap.destroy() method. ====== Configure Tomcat ====== ===== Enable JMX and jvmRoute ===== Part of Application.yml --- tomcat: ajp: port: 8018 remoteauthentication: false enabled: true # Environment Variable will be loaded when application starts, i.e. at app handler jvmRoute: ${SUPPORT_PAGE_JVM_ROUTE} Configuration Bean for Tomcat package com.errigal.support.page.systemconfig import org.apache.catalina.connector.Connector import org.springframework.beans.factory.annotation.Value import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory import org.springframework.boot.context.properties.ConfigurationProperties import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration /*************************************************************** * Copyright (c) 2017 Errigal Inc. * * This software is the confidential and proprietary information * of Errigal, Inc. You shall not disclose such confidential * information and shall use it only in accordance with the * license agreement you entered into with Errigal. * ***************************************************************/ /** * Start AJP for load balancer * https://docs.spring.io/spring-boot/docs/current/reference/html/howto-embedded-servlet-containers.html * https://blog.swdev.ed.ac.uk/2015/06/24/adding-embedded-tomcat-ajp-support-to-a-spring-boot-application/ * https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html * * @ConfigurationProperties this let this class only load property with prefix tomcat * * User: wonlee * Date: 15/03/2017 */ @Configuration @ConfigurationProperties(prefix = "tomcat") class TomcatConfiguration { @Value('${tomcat.ajp.port}') int ajpPort @Value('${tomcat.ajp.remoteauthentication}') String remoteAuthentication @Value('${tomcat.ajp.enabled}') boolean tomcatAjpEnabled @Value('${tomcat.jvmRoute}') String jvmRouteString @Bean public EmbeddedServletContainerFactory tomcatEmbeddedServletContainerFactory() { TomcatEmbeddedServletContainerFactory tomcat = new TomcatEmbeddedServletContainerFactory() if (tomcatAjpEnabled) { Connector ajpConnector = new Connector("AJP/1.3") ajpConnector.setProtocol("AJP/1.3") ajpConnector.setPort(ajpPort) ajpConnector.setSecure(false) ajpConnector.setAllowTrace(false) ajpConnector.setScheme("http") tomcat.addAdditionalTomcatConnectors(ajpConnector) } /* * Set jvmRoute which is required by jk_mod (load balancer) * http://stackoverflow.com/questions/31166336/how-to-set-embedded-tomcat-jvmroute * * Tomcat uses System Property to set jvmRoute * https://tomcat.apache.org/tomcat-8.5-doc/config/systemprops.html * * jvmRoute won't be added to cookie name if it is empty string */ System.setProperty("jvmRoute", jvmRouteString) return tomcat } } ====== Single Sign On ====== [[development:applications:singlesignon#integrate_single_sing_on_in_grails_3|Integrate Single Sing on in Grails 3]] ====== Load-balancer Set-Up (support_page example) ====== on: EXTLB - Prepare new Load Balancer setting cd /etc/httpd/conf sudo cp mod-jk.conf mod-jk.conf.bk sudo vi mod-jk.conf.bk Append following lines at the end JkMount /Support/ SupportPageLoadBalancer JkMount /Support/* SupportPageLoadBalancer JkMount /Support SupportPageLoadBalancer sudo cp workers.properties workers.properties.bk sudo vi workers.properties.bk Line2, at the end of "worker.list=", add "SupportPageLoadBalancer" to the list So the line has to look like worker.list=jkstatus,NocPortalLoadBalancer,SnmpManagerLoadBalancer,SnmpManagerEMSLoadBalancer,ReportingManagerLoadBalancer,TicketerLoadBalancer,CasLoadBalancer,SoapLoadBalancer,SupportPageLoadBalancer Add following line after Soap Worker Config lines # Configure SupportPage worker.SupportPageLoadBalancer.type=lb worker.SupportPageLoadBalancer.sticky_session=1 worker.SupportPageWorker1.reference=worker.ajptemplate worker.SupportPageWorker1.host=extapps1.ext worker.SupportPageWorker1.port=8018 worker.SupportPageWorker1.reply_timeout=600000 worker.SupportPageWorker2.reference=worker.ajptemplate worker.SupportPageWorker2.host=extapps2.ext worker.SupportPageWorker2.port=8018 worker.SupportPageWorker2.reply_timeout=600000 Append following lines at the end worker.SupportPageLoadBalancer.balance_workers=SupportPageWorker1,SupportPageWorker2 Do restart the HTTPD: sudo service httpd restart Setup SSO for Support Page APPS1 & APPS2 cd /usr/local/conf/cas/services/ touch support_page-1008.json vi support_page-1008.json { "@class" : "org.jasig.cas.services.RegexRegisteredService", "serviceId" : "https://nocportal.extenetsystems.com/Support/.*", "name" : "Support Page", "id" : 1008 } Change will be applied automatically to CAS