I want to log.debug from src/groovy. The 2.1.1 Grails user guide says to it like this:
package org.other
import org.apache.commons.logging.LogFactory
class MyClass {
private static final log = LogFactory.getLog(this)
…
}
But import org.apache.juli.logging.LogFactory works (in dev environment) as well. What's the difference?
Why not use the Groovy standard #Log annotation. That will inject a log instance into your class. Read more here: http://groovy.codehaus.org/Logging
Related
I'm attempting to create unit tests for a JenkinsShared library using Gradle in order to run the test tasks.
I've followed this tutorial which upon conclusion one has a working test suite for a shared library for functions within the vars folder (with the unit tests in src/test/groovy/*Test.groovy).
However, in our internal shared jenkins library we followed a more object oriented style and isolated functionality into a package of classes in the format: src/org/company/*.groovy.
The problem arises when attempting to import said package into a unit test class. In the tutorial, the functions are imported using the loadScript method this method fails when loading a class which is dependent on another file.
Take the class:
package tests
import org.junit.*
import com.lesfurets.jenkins.unit.*
import static groovy.test.GroovyAssert.*
import org.company.UtilFactory
class UtilFactoryTest extends BasePipelineTest {
#Test
void testCall() {
def util = UtilFactory.getUtil("hello")
assertEquals true, true
}
}
src/org/company/UtilFactory.groovy
package org.company
class UtilFactory implements Serializable {
static Util instance
static Util getUtil(script=null) {
if (!(UtilFactory.instance)) {
if (!script) {
// Throws an exception if on the first call to getUtil the
// script parameter is null.
throw new ScriptUndefinedException("script parameter null on initial call to getUtil")
}
UtilFactory.instance = new Util(script)
}
return UtilFactory.instance
}
}
class ScriptUndefinedException extends Exception {
// Parameterless Constructor
public ScriptUndefinedException() {}
// Constructor that accepts a message
public ScriptUndefinedException(String message)
{
super(message);
}
}
Which gives me the exception:
jenkins-utilities/src/test/groovy/UtilFactoryTest.groovy: 7:
unable to resolve class org.company.UtilFactory
# line 7, column 1.
import org.company.UtilFactory
This may be more of a Gradle issue than a JenkinsShared Library. I've just spent a good portion of my day trying to figure out exactly what I'm doing wrong to no avail.
I would really appreciate any help to guide me in the right direction.
This library may be helpful getting your shared libraries to work in the unit test https://github.com/stchar/pipeline-sharedlib-testharness
I am setting up a shared library for Jenkins pipelines and am trying to figure out how to import a class in the shared library into a custom step that I am writing.
Here's what the directory structure looks like:
src
--jenny
----util
------Versioning.groovy
vars
--calculateVersion.groovy
The Versioning.groovy file defines some static helper methods that do some stuff.
package jenny.util
class Versioner implements Serializable {
static bool checkForValidVersion(version) {
return true
}
}
I would like to call this method from the calculateVersion.groovy something like this:
def call(version) {
return jenny.util.Versioner.checkForValidVersion(version)
}
So that my declarative pipeline can call:
def valid = calculateVersion "1.0.0"
But I receive this error No such property: jenny for class: calculateReleaseVersions
Is it possible to reference the classes in the shared library from files in the vars to define custom steps and how is this done?
Yes it is possible. At least for us:
Just like in plain java (or groovy) we put an import statement into the groovy script in vars. In your case that would be something like:
import jenny.util.Versioner
def call(version) {
return Versioner.checkForValidVersion(version)
}
Another thing I just found: It looks like the file name of the class Versioner doesn't match the class name: Versioning.groovy. Could that be the issue?
If that doesn't work you propably want to upgrade your pipeline plugin version(s).
Spock tests injects null to grailsApplication,as i tried autowiring both to grails service and to domain objects(spec)
code(AttackSpec.groovy)
package core
import grails.test.mixin.TestFor
import grails.test.mixin.TestMixin
import grails.test.mixin.support.GrailsUnitTestMixin
import spock.lang.Specification
/**
* See the API for {#link grails.test.mixin.domain.DomainClassUnitTestMixin} for usage instructions
*/
#TestMixin(GrailsUnitTestMixin)
#TestFor(Attack)
class AttackSpec extends Specification {
def grailsApplication
def setup() {
Attack attack = new Attack();
println 'app '+grailsApplication.toString()
}
def cleanup() {
}
void "test something"() {
setup:
println 'app '+grailsApplication.toString()
}
}
output
log4j:WARN No appenders could be found for logger (org.codehaus.groovy.grails.commons.DefaultGrailsApplication).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
appnull
appnull
SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/C:/ops/grails-2.4.4/dist/grails-plugin-log4j-2.4.4.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/C:/ops/grails-2.4.4/lib/org.slf4j/slf4j-simple/jars/slf4j-simple-1.7.5.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
SLF4J: Actual binding is of type [org.slf4j.impl.GrailsSlf4jLoggerFactory]
I have tried using explicit #Autowired annotation and Static Typing,yet it's always the same. it seems like I have to inflate the grails application somewhere?
It sounds like you want to be running an integration test and not a unit test. Move your class under the integrations test folder and you may need to eliminate your test class annotations because I think those are only for unit testing.
What is the point of injecting grailsApplication in a unit test?. If you want to set a config, because your class under test: Attack reads a value of the grails application, then you can mock the grailsApplication as following:
def 'test whatever you want to'() {
def attack = new Attack()
attack.grailsApplication = [config: [my: [setting: "myValue"]]] // if attack uses grailsApplication.config.my.setting internally
when:
def setting = attack.getMySetting()
then:
setting == "myValue"
}
Or you could use a real Mock if you want to track access to it.
If you really want to use the grails environment to test, that access of the values on the framework (for whatever reason that might be) is correct executed, you should use an integration test. Subclassing IntegrationSpec from Spock will inject the grailsApplication into your test, so you can set the real thing in your Attack class.
I have a file under src/groovy and I have some properties that are in my Config.groovy and in external property file too. Normally if one want access properties its possible to use grailsApplication .configuration.property.name expression. I want to be able to access all those properties from this file that is under src/groovy directory. What I've tried so far
import grails.util.Holders
class ForkedTomcatCustomizer {
def application
void customize(Tomcat tomcat) {
println Holders.grailsApplication.config.property.name
}
}
gave me NPE saying that grailsAppliction is null
import org.codehaus.groovy.grails.web.context.ServletContextHolder as SCH
import org.codehaus.groovy.grails.web.servlet.GrailsApplicationAttributes as GA
class ForkedTomcatCustomizer {
def application
void customize(Tomcat tomcat) {
def ctx = SCH.servletContext.getAttribute(GA.APPLICATION_CONTEXT)
def grailsAppliction = ctx.grailsApplication.getObject()
println grailsAppliction.config.property.name
}
}
the same - NPE because grailsAppliction is null
Is it possible to handle this situation somehow? Thank you!
Use the below and see if it works
println Holders.config.property.name
You don't need grailsApplication when using Holders.
The examples below are probably a little more complex than what you need, but they show how to get a configuration property at build time. I use them to merge two configuration files, but you might not need to do that.
This method returns a config property when called here at the CompileEnd event.
You could define a similar method in your app's _Events.groovy file that calls your own configuration holder class.
import org.codehaus.groovy.grails.commons.ConfigurationHolder;
class KeyAndSecret{
public static String consumerKey = ConfigurationHolder.config.consumerKey;
public static String consumerSecret = ConfigurationHolder.config.consumerSecret;
}
Try like this
Relating to Accessing grails application config from a quartz job:
Apparently, DI doesn't happen prior to the creation of a job. I'm guessing this is the same with other grails artefacts (couldn't spot relevant documentation).
In my particular case, I was aiming to load a property from config and expose that property from the job class. In general though, it seems a valid use-case to me, that artefacts will load configuration, and then return those properties via API.
I'm wondering then, how could this be achieved when a class cannot rely on access to grailsApplication.config at construction.
Thanks
Try with:
import org.codehaus.groovy.grails.commons.ConfigurationHolder as CH
class MyJob {
def execute() {
def myConfigVar = CH.flatConfig.get('my.var.setup.in.config.groovy')
...
}
}
OR
import grails.util.Holders
class MyJob {
def execute() {
def myConfigVar = Holders.config.my.var.setup.in.config.groovy
...
}
}