Create files programatically in ‘right’ resources folder in gradle/Ide project …

October 29, 2017 Leave a comment

Been having problems creating files in correct ‘/resources’ folder in projects.  quite confusing.  However i have a ‘workable’ solution as follows

steps –

(1)first locate root of your IDE/project using System.getProperty(“user.dir”)

(2) get the current resource file for ‘this’ – the class you run from ide

(3) see if the resource is in $root/out/test/.. dir – it so its a test else its your normal code.

(4) set resourcePath now to correct ‘location’ either in src/main/resources or src/test/resources/ – then build rest of file from this stub

(5) check if file exists – if so delete and rewrite this (you can make this cleverer)

(6) create file and fill its contents

job done this file should now appear where you expect it. Happy to take cleverer ways to get do this – but for anyone else stuck this seems to do the trick

code looks something like this

void exportToFile (dir=null, fileName=null) {

    boolean isTest = false
    String root = System.getProperty("user.dir")
    URL url = this.getClass().getResource("/")
    File loc = new File(url.toURI())
    String canPath = loc.getCanonicalPath()
    String stem = "$root${File.separatorChar}out${File.separatorChar}test"
    if (canPath.contains(stem))
        isTest = true

    String resourcesPath
    if (isTest)
        resourcesPath = "$root${File.separatorChar}src${File.separatorChar}test${File.separatorChar}resources"
    else
        resourcesPath = "$root${File.separatorChar}src${File.separatorChar}main${File.separatorChar}resources"

    String procDir = dir ?: "some-dir-string"
    if (procDir.endsWith("$File.separatorChar"))
        procDir = procDir - "$File.separatorChar"
    String procFileName = fileName ?: "somedefaultname"
    String completeFileName
    File exportFile = "$resourcesPath${File.separatorChar}$procDir${File.separatorChar}${procFileName}"
    exportFile = new File(completeFileName)
    println "path: $procDir, file:$procFileName, full: $completeFileName"

    exportFile.with {
        if (exists())
            delete()
        createNewFile()
        text = toString()
    }

}

 

Advertisements

logback configuration for gradle/springboot type projects …

yet another painful trawl to set up logging, and have it behave like spring boot default.

So to basics.

  1. create your gradle project, i’m using Intellij Idea for that.  You need to include the latest springboot-gradle-plugin.  Then ensure you apply the plugin.  Then fill your dependencies, but include latest log back from maven central and Slf4j-api.  This will provide default mapping for logger directly to logback.
  2. group 'org.softwood'
    version '1.0-SNAPSHOT'
    
    buildscript {
        repositories {
            mavenCentral()
        }
        dependencies {
            classpath("org.springframework.boot:spring-boot-gradle-plugin:1.5.2.RELEASE")
        }
    }
    
    apply plugin: 'idea'
    apply plugin: 'org.springframework.boot'
    apply plugin: 'groovy'
    apply plugin: 'java'
    
    sourceCompatibility = 1.8
    
    repositories {
        mavenCentral()
    }
    
    dependencies {
        compile 'org.apache.camel:camel-spring-boot-starter:2.18.4'
        compile 'org.apache.camel:camel-groovy:2.18.4'
        compile 'org.apache.camel:camel-stream:2.18.4'
        compile 'org.codehaus.groovy:groovy-all:2.4.11'
        //add Logback
        compile 'ch.qos.logback:logback-classic:1.2.3'
        compile 'ch.qos.logback:logback-core:1.2.3'
        compile 'org.slf4j:slf4j-api:1.7.25'
    
        testCompile group: 'junit', name: 'junit', version: '4.11'
        testCompile group: 'junit', name: 'junit', version: '4.12'
    }
    
    
  3. Then put either a logback.groovy or a logback.xml file into the project classpath. By default i’ve used logback.groovy for this groovy project and put it under the resources directory (along with application.yml etc you may want to tailor the spring application)

    I did some digging and if you want coloured output as the spring boot default you need a logback.groovy a bit like this. This does a scan for changes which you can disable, and calls two closures to configure the appenders, and the loggers

    
    import org.springframework.boot.ApplicationPid
    
    import java.nio.charset.Charset
    
    import static ch.qos.logback.classic.Level.*
    import ch.qos.logback.core.ConsoleAppender
    import ch.qos.logback.classic.encoder.PatternLayoutEncoder
    import ch.qos.logback.core.status.OnConsoleStatusListener
    import ch.qos.logback.core.FileAppender
    
    displayStatusOnConsole()
    scan('5 minutes')  // Scan for changes every 5 minutes.
    setupAppenders()
    setupLoggers()
    
    def displayStatusOnConsole() {
        statusListener OnConsoleStatusListener
    }
    
    def setupAppenders() {
    
        //add to converters to handle colour and whitespace
        conversionRule 'clr', org.springframework.boot.logging.logback.ColorConverter
        conversionRule 'wex', org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter
    
    
        def consolePatternFormat = "%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(%5p) %clr([%property{PID} - %thread]){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(>){faint} %m%n%wex"
        def filePatternFormat = "%d{yyyy-MM-dd HH:mm:ss.SSS} [%property{PID} - %thread] %-5level %-12logger{12}:[.%M] > %msg%n%wex"
        if (!System.getProperty("PID")) {
            System.setProperty("PID", (new ApplicationPid()).toString())
        }
    
    
        //def logfileDate = timestamp('yyyy-MM-dd') // Formatted current date.
        // hostname is a binding variable injected by Logback.
        //def filePatternFormat = "%d{HH:mm:ss.SSS} %-5level [${hostname}] %logger - %msg%n"
        //appender('logfile', FileAppender) {
        //    file = "simple.${logfileDate}.log"
        //    encoder(PatternLayoutEncoder) {
        //        pattern = filePatternFormat
        //    }
        //}
    
        // Add custom converter for %smiley pattern.
        //conversionRule 'smiley', SmileyConverter
    
        
        appender('STDOUT', ConsoleAppender) {
            encoder(PatternLayoutEncoder) {
                charset = Charset.forName('UTF-8')
                pattern = consolePatternFormat
                //pattern =
            }
        }
    }
    
    def setupLoggers() {
        //logger 'com.mrhaki.java.Simple', getLogLevel(), ['logfile']
        logger 'application.Application', DEBUG
        root DEBUG, ['STDOUT']
    }
    
    def getLogLevel() {
        (isDevelopmentEnv() ? DEBUG : INFO)
    }
    
    def isDevelopmentEnv() {
        def env =  System.properties['app.env'] ?: 'DEV'
        env == 'DEV'
    }
    
    
  4. As this is a groovy project you can just use @SLF4J annotation to your class and it will inject the log variable automatically – less noise that creating the logger. Now use the logh variable in a method as you need it
    @Slf4j //inject logger
    @SpringBootApplication
    public class Application {
        @Autowired
        ApplicationContext ctx
    ...
    public someMethod () {
                log.debug "log something "
    }
    ...
    

That will give you a basic config that you can extend as you see fit, and add new classes to log as you go.

Categories: Uncategorized

A little bit of housework – MOPping up

December 31, 2016 Leave a comment

in doing some basics you keep relearning some stuff so here’s a quick recap on Groovy MOP.

Each groovy class has a metaClass, who’s default class is groovy.lang.MetaClassImpl.  If you set a property on the metaClass groovy changes this to be ExpandoMetaClass.  Normally calls to methods on your class are normally redirected to the metaClass to call the methods on your class using the invokeMethod call on the metaClass

Using the metaClass of your class you can lookup the methods on your class  like this

class MyIntercepted {

    def myMethods () {
        println "methods fom meta class"
        int total = 0
        def list = this.getMetaClass().getMethods().each {total++; println "$it.name"}
        println "total methods found : $total \n"
        list
    }

    def myMetaMethods () {
        println "list of meta methods from meta class"
        int total = 0
        def list = this.getMetaClass().getMetaMethods().each {total++; println "$it.name"}
        println "total of metaMethods found : $total \n"
        list
    }

    //has higher priority than invokeMethod
    /*def methodMissing (String name, args) {
        println "missing method: method $name ($args) was called by methodMissing"
    }*/

    //will be called if no method can be matched
    def invokeMethod (String name, args) {
        println "metaclass is of type " + this.getMetaClass().getClass()
        println "method $name ($args) was called intercepted by invokeMethod"
    }
}

// and use it 
MyIntercepted mi = new MyIntercepted()

mi.myMethods()       //class method exists
mi.myMetaMethods()   //class method exists
mi.smoke()           //class method doesn't exist 

 

calling myMethods() lists out the basic class methods found via the metaClass including those of GroovyObject, and my two class methods.

calling the myMetaMethods() will list out the broader list of metaMethods that Groovy embellishes each class with with via the GDK, which includes the “println” method.

if you implement def invokeMethod (String name, args), as shown (and you have to put the String type to name to get right dynamic dispatch), then when you call the nonexistent smoke(), method then Groovy calls the invokeMethod call where you can see the trace wriiten to your console.

if you uncomment the def methodMissing() this has higher priority and so this methodMissing() is called when the mi.smoke() method is called.

if you change your class to implement the marker interface GroovyInterceptable like this, then groovy intercepts all calls on the class and directs them to the invokeMethod call, including metaMethods such as println. Because of this you can’t use println as this is intercepted as wll and go into stackoverflow loop. you have to use the System.out.println to get trace output.

class MyIntercepted implements GroovyInterceptable {

    def myMethods () {
        println "methods from meta class"
        int total = 0
        def list = this.getMetaClass().getMethods().each {total++; println "$it.name"}
        println "total methods found : $total \n"
        list
    }

    def myMetaMethods () {
        println "list of meta methods fom meta class"
        int total = 0
        def list = this.getMetaClass().getMetaMethods().each {total++; println "$it.name"}
        println "total of metaMethods found : $total \n"
        list
    }

    //has higher priority than invokeMethod
    def methodMissing (String name, args) {
        println "missing method: method $name ($args) was called by methodMissing"
    }

    //will be called if no method can be matched
    def invokeMethod (String name, args) {
        System.out.println "method $name ($args) was called intercepted by invokeMethod"
    }
}

So how do call method if you have intercepted all the calls? You lookup the method and if it exists you can use the method.invoke(this, args) on it

    //will be called if no method can be matched
    def invokeMethod (String name, args) {
        //System.out.println "metaclass is of type " + this.getMetaClass().getClass()
        System.out.println "method $name ($args) was called intercepted by invokeMethod"
        MyIntercepted.metaClass.invokeMethod(this, 'println', "invoked println from metaClass.invokeMethod ")
        MetaMethod method = MyIntercepted.metaClass.getMetaMethod("hello")
        if (method) {
            System.out.println "looked up hello metamethod and tried to call it "
            method.invoke(this, "\tmethod.invoke: invoked hello metamethod")
            method.invokeMethod('println', "\tmethod.invokeMethod: invoked println directly from a meta method")
        }
    }

however you have to be careful like with println as this will again go into stack overflow

if you override the invokeMethod on the metaClass like this

MyIntercepted mi = new MyIntercepted()
mi.metaClass.invokeMethod = {String name, args -> System.out.println "used overriden metaClass invokeMethod"}

it has lower priority than a class method of same the name implemented in the class. whereas if you have a methodMissing on a class and one on the metaClass, the resolution path uses the metaClass implementation first!

Categories: Groovy Tags: ,

Eclipse high display scale (DPI) – ‘tactical’ fix for Windows

March 26, 2016 Leave a comment

I Eventually found a fix that seems to work for eclipse Mars (2) and Neon builds. It doesn’t seem to have any impact on Eclipse Luna (great shame i was trying to get IBM RSA 9.5 which is based on Luna to scale – failed back to IBM for an upgrade path).  But if you are doing general development work with eclipse on windows with high DPI screen this is massive improvement – it makes it all usable again.

My laptop is running Windows 10, but i suspect this works for Windows 8/8.1 just the same, but i no longer have such a build to try it on.

Essentially this is just a re-post of the answer i found here referenced fix

To get this to work you have to first make an edit to your registry  as follows.  You have to add a new key, and set its value to 1 (true), as follows. The registry structure up to the SideBySide entry should already be in existence when you navigate in the registry browser.

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\SideBySide\PreferExternalManifest (DWORD) to 1

The next thing you have to do is to create a new text file in the same directory as your eclipse.exe installation.
The file should be called eclipse.exe.manifest and have the following ‘magic’ text cut and past and then saved.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
    <description>eclipse</description>
    <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
        <security>
            <requestedPrivileges>
                <requestedExecutionLevel xmlns:ms_asmv3="urn:schemas-microsoft-com:asm.v3"
                               level="asInvoker"
                               ms_asmv3:uiAccess="false">
                </requestedExecutionLevel>
            </requestedPrivileges>
        </security>
    </trustInfo>
    <asmv3:application>
        <asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
            <ms_windowsSettings:dpiAware xmlns:ms_windowsSettings="http://schemas.microsoft.com/SMI/2005/WindowsSettings">false</ms_windowsSettings:dpiAware>
        </asmv3:windowsSettings>
    </asmv3:application>
</assembly>

Then stand back and pray. Double click your eclipse.exe file and it should come up
looking as it would in the ‘good’ old days, and the icons will to be legible.

I am sure Neon is supposed to have proper SWT full DPI scaling and detection on release, but i tried Neon-M5 today, and it was still
illegible. This tactical fix makes it work for now – hoorah.

Quick note on groovy testing a spock

February 29, 2016 Leave a comment

Been getting to grips with gradle, groovy and spock, on a little project and couldnt figure out how to get the GroovyTestCase power assertions available to spock tests.

So eventually found it you have to add the following import

import static groovy.test.GroovyAssert.*
import static org.assertj.core.api.Assertions.*

this enables you to use the the groovy power asserts (shouldfail, assertFalse, etc ), the other is a fluent assertion library that has some interesting features – you need to update your compile dependencies to include ‘org.assertj:assertj-core:3.0.0’

I have not played with the Hamcrest matchers at this point but probably worth a look as these with Spock too

If you want Gradle to find and run your tests i’ve found its easiest to end your class file nameTest.groovy then you can run single shot tests for example like this

gradle -Dtest.single=DynamicRuleSpecification test

which will run the DynamicRuleSpecificationTest.groovy in your ‘src/test/groovy’ folder

Happy testing

Categories: gradle, Groovy, Testing Tags: ,

silly problems with Spring @Value ‘${}’ with IoC injection

February 23, 2016 Leave a comment

hit some basic problems with Spring injection today worth noting for others

I was trying out @Value injection today in spring and hit some basic issues

1. when you use @Value in groovy and spring – despite the fact that you might want to use a ${} expression, you cant wrap this in “” which you might expect. The Groovy compiler gets in a huff and declares the the value is not a String (technically its a GString in groovy).

to make this work in groovy you have write something like (note single ”)

@Value ('${jmx.rmi.host}')

This is counter intuitive if you are used to the normal “” Gstring interpolation in Groovy. To make it work with “” you have to try

@Value ("${jmx.rmi.host}".toString())

or just use the ” as previously shown.

2. second issue: if injecting values from application.properties in root of your classpath , then note that the properties values in that file default to string, so `x.y.z=”hi”` will return a string including the quotes, which is not what you expect. just leave the strings unadorned to inject correctly.

3. then, if you use param injection alone like this

void setHost ( @Value ('${jmx.rmi.host}') String host)

then you get a null injection (not sure why). To fix this, either

a) move the

@Value ('${jmx.rmi.host}'

to method level, or

b) use @autowired at method level and leave the

@Value ('${jmx.rmi.host}')

at parameter level as well,  to get the injection to occur.

It’s these small nuances that take so much time, hopefully someone else will benefit and save a couple of hours.

4. Lastly, you can lookup properties using the Spring Environment like this. Just use the @Autowired on method or constructor, and do the lookup /type conversion using the env.getRequiredProperty call like this

@Component
class Props {

    private Map props = [:]
    boolean jmxEnabled
    String host

    @Autowired  //test inject the env
    Props (Environment env) {
        jmxEnabled = env.getRequiredProperty(&quot;org.softwood.jmx&quot;, Boolean.class)
        props[jmxEnabled]=jmxEnabled


    }

    //format either use Autowired for method and @value on param
    // or just @value as method injection will work
    @Autowired
    void setHost ( @Value ('${jmx.rmi.host}') String host)  {

        assert host
        println &quot;set host by injection&quot;
        this.host = host
        props[host] = host
    }

}

accessing Google geocode api with groovy

February 23, 2016 Leave a comment

This is just a quick post on how you can get started with the google geocode API services from groovy

you start by visiting Google set to get an authentication key

https://developers.google.com/maps/documentation/geocoding/get-api-key

use the ‘get a key’ button in the second section. this runs a wizard for you and you complete your details. I set up a server key for dev pc as i’m playing and that’s the registered server name i used.

At the end of this process google will generate an API key for you which you should record safely and securely. when coding read this value from a config file, etc so that you don’t encode it directly in your code.

Once setup with this you try the API out. There is a interactive javascript version of this api which i havent used – i’m using the json webservice, and there is an XML version of the service also.

The return result type has been encoded into the base URL, and not using accept headers.

first lets start with location class, that you’ll provide instance of with the address you want to get lat/long for. (you can do this in reverse as well)

class Location {
String houseNumber
String street
String city
String state
String zip
String country

double latitude
double longitude

String toString () {"$street, $city, $zip, $state, $country : latitude:$latitude, longitude:$longitude"}
}

i’m not persisting this put you do so readily as local cache etc.

The web service is located with a url base of

 def base = "https://maps.googleapis.com/maps/api/geocode/json?"

what the geocoder service will do is take a location (with populated record details) and build an address parameter, by URLencoding an array of address data from the location, using the join(‘,’) as the separator.

You then creat a params array for the web service, by taking a map of the address and your server API key (there is an optional components attribute that i have not used here – see google api defn for details). you then collect and join the key=value pairs you build to get the resultant param format for the call.

you then use JsonSlurper to parse the result of the call, (assert it all went ok), and then read the lat, lng values back (google api shows you the structure of the result set) and store these back in the location instance, converting the result to Double as you do so.

class Geocoder {
    def base = "https://maps.googleapis.com/maps/api/geocode/json?"

    void completeLatLong (Location loc){
        def addressFields =  loc.street ? [loc.street,loc.city,loc.zip,loc.state,loc.country] : [loc.city, loc.country]
        def address = addressFields.collect {URLEncoder.encode (it, 'UTF-8')}.join (',')
        def params = [address:address,
                      key:<your api key here>]
        def url = base +params.collect {k,v -> "$k=$v"}.join ('&')

        def response = new JsonSlurper().parse (url.toURL())

        assert response.status == "OK"
        loc.latitude = response.results[0].geometry.location.lat.toDouble()
        loc.longitude = response.results[0].geometry.location.lng.toDouble ()

    }
}

you can now write tests, or simple driver script to use the service (fill in your own street, city, etc.


def loc = [street: "<your street>", city: "<your city>", zip: "<your zip>", state:"<your state>", country:"<your country>"] as Location

def geo = new Geocoder()
geo.completeLatLong (loc)

println loc  //should return completed lat/long from the successful service 

This should return you the loc record with the added geocoding details, which you can use elsewhere

Categories: Groovy
%d bloggers like this: