How do I completely bootstrap a grails environment? - grails

I have the included grails script that I found in some random place on the internet and it works pretty well for firing up scripts in a bootstrapped grails env. The only thing it doesn't seem to do is kick off my conf/*Bootstrap.groovy scripts like when I do run-app.
Is there another function like loadApp() and configureApp() that will do that for me?
import org.codehaus.groovy.grails.support.PersistenceContextInterceptor
Ant.property(environment: "env")
grailsHome = Ant.antProject.properties."env.GRAILS_HOME"
includeTargets << new File("${grailsHome}/scripts/Bootstrap.groovy")
target('default': "Runs scripts in the test/local directory") {
if (!args) { throw new RuntimeException("[fail] This script requires an argument - the script to run.") }
depends(configureProxy, packageApp, classpath)
classLoader = new URLClassLoader([classesDir.toURI().toURL()] as URL[], rootLoader)
Thread.currentThread().setContextClassLoader(classLoader)
loadApp()
configureApp()
def interceptor = null
def beanNames = appCtx.getBeanNamesForType(PersistenceContextInterceptor)
if (beanNames && beanNames.size() == 1) {
interceptor = appCtx.getBean(beanNames[0])
}
try {
interceptor?.init()
new GroovyScriptEngine(Ant.antProject.properties."base.dir", classLoader).run("scripts/${args}.groovy", new Binding(['appCtx':appCtx]))
interceptor?.flush()
} catch (Exception e) {
e.printStackTrace()
interceptor?.clear()
} finally {
interceptor?.destroy()
}
}

Yes, try
new BootStrap().init()

Related

Groovy code works, Then in Jenkins it doesn't. How can I make this work?

I am trying to augment the 'load' pipeline step function and I keep getting an error. I have found the code it executes based on the stack trace but I can't for the life of me figure out why it wouldn't just call the code as written.
I have written lots-and-lots of Java code so I know what it's trying to do. I just don't understand why it's trying to do it or how to convince it to stop! The groovy sample works perfectly! BTW: if there is an idiomatic way to do this in groovy/jenkins, I am all in.
Jenkins version: 2.176.1
Groovy plugin: 2.2
test.groovy
def someFunction(def params){
println("someFunction ${params}")
}
def someFunction2(def params){
println("someFunction2 ${params}")
}
def mainFunc(def stuff){
}
def somemainThingrunFunmain(){
}
def ___cps___21685(){
}
def ___cps___21688(){
}
this
main.groovy
def loaded = evaluate('test.groovy' as File)
def toAugment = loaded.class.declaredMethods*.name.findAll { !(it =~ '^(main|run)$|^[$]|^(___cps___)') }
def proxy = new Script(this.binding) {
#Override
Object run() {
monad.run()
}
}
toAugment.each {
proxy.metaClass."${it}" = { "logging ${it}".tap { println(it)} } >> loaded.&"${it}"
}
proxy.someFunction('hello world1')
proxy.someFunction2('hello world2')
outputs:
called
someFunction hello world1
called
someFunction2 hello world2
Now in Jenkins:
Jenkinsfile:
library 'common-libraries#chb0'
node('java') {
stage('SCM') {
checkout scm
}
def loaded = load('test.groovy')
stage('experiment') {
loaded.someFunction('hello world1')
loaded.someFunction2('hello world2')
}
}
adapted library (in common-library:vars/load.groovy):
def call(String path) {
def loaded = steps.load(path)
def proxy = new Script(this.getBinding()) { // error here
#Override
Object run() {
loaded.run()
}
}
// remove groovy and jenkins generated functions. Don't touch those
def toAugment = loaded.class.declaredMethods*.name.findAll { !(it =~ '^(main|run)$|^[$]|^(___cps___)') }
toAugment.each {
proxy.metaClass."${it}" = { "logging ${it}".tap { println(it) } } >> loaded.&"${it}"
}
}
exception:
groovy.lang.GroovyRuntimeException: Could not find matching constructor for: load$1(load, Script1, groovy.lang.Binding)
at groovy.lang.MetaClassImpl.invokeConstructor(MetaClassImpl.java:1732)
at groovy.lang.MetaClassImpl.invokeConstructor(MetaClassImpl.java:1532)
at org.codehaus.groovy.runtime.callsite.MetaClassConstructorSite.callConstructor(MetaClassConstructorSite.java:49)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallConstructor(CallSiteArray.java:60)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callConstructor(AbstractCallSite.java:235)
at com.cloudbees.groovy.cps.sandbox.DefaultInvoker.constructorCall(DefaultInvoker.java:25)

Jenkins timeout/abort exception

We have a Jenkins pipeline script that requests approval from the user after all the preparatory steps are complete, before it actually applies the changes.
We want to add a timeout to this step, so that if there is no input from the user then the build is aborted, and are currently working on using this kind of method:
try {
timeout(time: 30, unit: 'SECONDS') {
userInput = input("Apply changes?")
}
} catch(err) {
def user = err.getCauses()[0].getUser()
if (user.toString == 'SYSTEM') { // if it's system it's a timeout
didTimeout = true
echo "Build timed out at approval step"
} else if (userInput == false) { // if not and input is false it's the user
echo "Build aborted by: [${user}]"
}
}
This code is based on examples found here: https://support.cloudbees.com/hc/en-us/articles/226554067-Pipeline-How-to-add-an-input-step-with-timeout-that-continues-if-timeout-is-reached-using-a-default-value and other places online, but I really dislike catching all errors then working out what's caused the exception using err.getCauses()[0].getUser(). I'd rather explicitly catch(TimeoutException) or something like that.
So my question is, what are the actual exceptions that would be thrown by either the approval step timing out or the userInput being false? I haven't been able to find anything in the docs or Jenkins codebase so far about this.
The exception class they are referring to is org.jenkinsci.plugins.workflow.steps.FlowInterruptedException.
Cannot believe that this is an example provided by CloudBeeds.
Most (or probably all?) other exceptions won't even have the getCauses() method which of course would throw another exception then from within the catch block.
Furthermore as you already mentioned it is not a good idea to just catch all exceptions.
Edit:
By the way: Scrolling further down that post - in the comments - there you'll find an example catching a FlowInterruptedException.
Rather old topic, but it helped me, and I've done some more research on it.
As I figured out, FlowInterruptedException's getCauses()[0] has .getUser() only when class of getCauses()[0] is org.jenkinsci.plugins.workflow.support.steps.input.Rejection. It is so only when timeout occured while input was active. But, if timeout occured not in input, getCause()[0] will contain object of another class: org.jenkinsci.plugins.workflow.steps.TimeoutStepExecution$ExceededTimeout (directly mentioning timeout).
So, I end up with this:
def is_interrupted_by_timeout(org.jenkinsci.plugins.workflow.steps.FlowInterruptedException e, Boolean throw_again=true) {
// if cause is not determined, re-throw exception
try {
def cause = e.getCauses()[0]
def cause_class = cause.getClass()
//echo("cause ${cause} class: ${cause_class}")
if( cause_class == org.jenkinsci.plugins.workflow.steps.TimeoutStepExecution$ExceededTimeout ) {
// strong detection
return true
} else if( cause_class == org.jenkinsci.plugins.workflow.support.steps.input.Rejection ) {
// indirect detection
def user = cause.getUser()
if( user.toString().equals('SYSTEM') ) {
return true
} else {
return false
}
}
} catch(org.jenkinsci.plugins.scriptsecurity.sandbox.RejectedAccessException e_access) {
// here, we may deal with situation when restricted methods are not approved:
// show message and Jengins' admin will copy/paste and execute them only once per Jenkins installation.
error('''
To run this job, Jenkins admin needs to approve some Java methods.
There are two possible ways to do this:
1. (better) run this code in Jenkins Console (URL: /script):
import org.jenkinsci.plugins.scriptsecurity.scripts.ScriptApproval;
def scriptApproval = ScriptApproval.get()
scriptApproval.approveSignature('method org.jenkinsci.plugins.workflow.steps.FlowInterruptedException getCauses')
scriptApproval.approveSignature('method org.jenkinsci.plugins.workflow.support.steps.input.Rejection getUser')
scriptApproval.save()
'''.stripIndent())
return null
}
if( throw_again ) {
throw e
} else {
return null
}
}
And now, you may catch it with something like this:
try {
...
} catch (org.jenkinsci.plugins.workflow.steps.FlowInterruptedException err) {
if( is_interrupted_by_timeout(err) ) {
echo('It is timeout!')
}
}
P.S. I agree, this is bad Jenkins design.

Spring Boot Resources in Docker container

I'm using Docker for a Spring Boot application and so far everything is working.
I have a resource file in src/main/resources/db/data/dummydata.csv
In a bootstrap class this file is used to import the dummy data into the database.
private fun getDummyData(): List {
var fileReader: BufferedReader? = null
val dummyData = ArrayList<DummyDataEntity>()
try {
var line: String?
val res = ResourceUtils.getFile("classpath:db/data/dummydata.csv")
fileReader = BufferedReader(FileReader(res.path))
// Read CSV header
fileReader.readLine()
... Processing the data ...
} catch (e: Exception) {
e.printStackTrace()
} finally {
try {
fileReader!!.close()
} catch (e: Exception) {
e.printStackTrace()
}
return dummyData
}
}
When I run the application in IntelliJ, everything works just fine, but when I'm running it in Docker it cannot be found.
The Jar and the Docker image are created using Kotlin DSL Gradle.
import com.palantir.gradle.docker.DockerExtension
import io.spring.gradle.dependencymanagement.dsl.DependencyManagementExtension
import org.gradle.tooling.model.GradleTask
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
import org.springframework.boot.gradle.tasks.bundling.BootJar
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath(Libs.springBootGradlePlugin)
classpath(Libs.kotlinGradlePlugin)
classpath(Libs.kotlinAllOpen)
classpath(Libs.gradleDocker)
}
}
plugins {
// Apply the java-library plugin to add support for Java Library
`java-library`
}
apply {
plugin("kotlin")
plugin("kotlin-spring")
plugin("org.springframework.boot")
plugin("io.spring.dependency-management")
plugin("com.palantir.docker")
}
repositories {
mavenCentral()
}
dependencies {
compile(Libs.kotlinReflect)
// Spring Boot
compile(Libs.springBootStarterDataJpa)
}
configure<DependencyManagementExtension> {
imports {
mavenBom(Libs.vaadinBom)
}
}
val bootJar: BootJar by tasks
bootJar.baseName = "reporting-app-site"
bootJar.version = "0.0.1"
configure<DockerExtension> {
name = "brabantia/${bootJar.baseName}"
files(bootJar.archivePath)
buildArgs(mapOf("JAR_FILE" to bootJar.archiveName))
dependsOn(tasks["build"])
}
val compileKotlin: KotlinCompile by tasks
compileKotlin.kotlinOptions.jvmTarget = "1.8"
The Jar does contain BOOT-INF/classes/db/data/dummyData.csv but when the application is run the error that is thrown is
java.io.FileNotFoundException: class path resource [db/data/dummydata.csv] cannot be resolved to absolute file path because it does not reside in the file system: jar:file:/app.jar!/BOOT-INF/classes!/db/data/dummydata.csv
What am I missing here?
The below worked for me.., you need to use an InputStream and not a File.
...
#Autowired
private ResourceLoader resourceLoader;
...
Resource resource= resourceLoader.getResource("classpath:/account_info.html");
InputStream inputStream= resource.getInputStream();
Assert.notNull(inputStream,"Could not load template resource!");
String email = null;
try {
byte[] bdata = FileCopyUtils.copyToByteArray(inputStream);
email = new String(bdata, StandardCharsets.UTF_8);
} catch (IOException e) {
logger.warn("IOException", e);
}finally {
if ( inputStream != null) {
IOUtils.closeQuietly(inputStream);
}
}

Why does this wslite SOAP client code not work?

Im new to Groovy and Im working on a Grails app. I need to make a SOAP call so Im using the wslite package, but the following code doesn't appear to do anything:
def client = new SOAPClient(apiEndpoint)
println "SOAP client is ${client.dump()}"
try {
def response = client.send(SOAPAction: 'GetService') {
body {
"Request" {
"Username"(credentials.userId)
"Password"(credentials.password)
"Param1"(code)
"Param2"(location)
"Items" {
"Item" {
"ItemParam1"("some data")
"ItemParam2"(some more data)
}
}
}
}
}
}
} catch (SOAPFaultException sfe) {
println "${sfe.dump()}"
} catch (SOAPClientException sce) {
println "${sce.dump()}"
}
println "${response.dump()}"
The first println works but then nothing after that.
By adding a catch all for exceptions I was able to see the problem in the markup.

How to deploy a module

I have a problem with deploying module. Here is module.epl:
import com.fss.demo.esperevent.*;
#Name('Count-Switched-On')
select count(*) from DemoSimpleEvent1;
and the code
{
DemoSimpleEvent1 demoSimpleEvent1 = new DemoSimpleEvent1();
Configuration config = new Configuration();
config.addEventTypeAutoName("com.fss.demo.esperevent");
EPServiceProvider EpService = EPServiceProviderManager.getDefaultProvider(config);
EPDeploymentAdmin deployAdmin = EpService.getEPAdministrator().getDeploymentAdmin();
MyListener myListener = new MyListener();
try {
Module module = deployAdmin.read(new File("module.epl"));
DeploymentResult MyResult = deployAdmin.deploy(module, new DeploymentOptions());
EPStatement Stta = EpService.getEPAdministrator().getStatement("Count-Switched-On");
} catch (IOException | ParseException | DeploymentException e) {
e.printStackTrace();
}
}
}
but Stta is null,and MyResult.statement does not contain any statement.
So what am I doing wrong?
It looks allright, maybe the code is reading the wrong file?
Perhaps pack it up into a complete test class and send it to the Esper user mailing list.
I think I figured out the problem.
The problem here is version of library antlr-runtime.jar
With esper 4.11.0.jar, should use antlr-runtime-3.2.jar

Resources