Sunday, June 26, 2016

Fedora 24 On A Mythlogic Chaos 1313 (aka Clevo w230ST)

Its been a while since I have update this little dusty corner of the interwebs; hopefully I will provide more content regularly.

Works!

Out of the box.    I downloaded the f24x64 workstation/live image, burn't it to an 4GB USB stick, rebooted into setup, and did a 'install' operation.   I did a fresh install; wiping my drives clean from a f23 install. 

You can look back at my f19f20, and f21 installs on same hardware.   I don't recall how I got to f22, but I know I used dnf upgrade to go from f22 to f23.

SNX/Checkpoint VPN

To get SNX/SSL VPN working, basically I followed the exact same stuff I did for f20, and f21:

#Get a JDK & install
su - root
#cd ${HOME}/.mozilla/plugins
#ln -s ${JAVA_HOME}/jre/lib/amd64/libnpjp2.so
#download snx_install.sh  (you should be able to get it from your vpn login webpage under "settings")
su - root
setsebool -P unconfined_mozilla_plugin_transition 0
sh snx_install.sh
yum install /lib/ld-linux.so.2 libX11.so.6 libpam.so.0 libstdc++.so.5 xterm
#(re)start firefox

I used Oracle JDK 1.8.0_92.  

Edge Scrolling on the Trackpad 

There is lots of noise on the interwebs about gnome 3.20 control center not having some options for the track pad, especially edge scrolling.    I use edges for scrolling; so this was a pretty significant issue.   Weeding through all the noise, there does appear to an issue or bug somewhere.   I discovered that the following command line, enables edge scrolling on my rig

xinput set-prop 12 --type=int --format=8 283 0 1 0

The backstory on this gem:  
  1. use xinput --list  to find the id of the touchpad 
  2. use xinput list-props <id> to find the number of the attribute that controls edge scrolling
  3. use xinput set-prop <id> ... <prop number> to 'move' the "1" from left to middle.  Left position must be 2 finger scrolling, middle position seem like edge scrolling, not sure what the last position does..
The list operation provides:

⎡ Virtual core pointer                     id=2 [master pointer  (3)]
⎜   ↳ Virtual core XTEST pointer               id=4 [slave  pointer  (2)]
⎜   ↳ SynPS/2 Synaptics TouchPad               id=12 [slave  pointer  (2)]
⎣ Virtual core keyboard                    id=3 [master keyboard (2)]
    ↳ Virtual core XTEST keyboard              id=5 [slave  keyboard (3)]
    ↳ Power Button                             id=6 [slave  keyboard (3)]
    ↳ Video Bus                                id=7 [slave  keyboard (3)]
    ↳ Video Bus                                id=8 [slave  keyboard (3)]
    ↳ Power Button                             id=9 [slave  keyboard (3)]
    ↳ Sleep Button                             id=10 [slave  keyboard (3)]
    ↳ AT Translated Set 2 keyboard             id=11 [slave  keyboard (3)]

Using the ID from above, in the list props operation, that provides:

Device 'SynPS/2 Synaptics TouchPad':
 Device Enabled (136): 1
 Coordinate Transformation Matrix (138): 1.000000, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 1.000000
 libinput Tapping Enabled (272): 1
 libinput Tapping Enabled Default (273): 0
 libinput Tapping Drag Lock Enabled (274): 0
 libinput Tapping Drag Lock Enabled Default (275): 0
 libinput Accel Speed (276): 0.154412
 libinput Accel Speed Default (277): 0.000000
 libinput Natural Scrolling Enabled (278): 0
 libinput Natural Scrolling Enabled Default (279): 0
 libinput Send Events Modes Available (256): 1, 1
 libinput Send Events Mode Enabled (257): 0, 0
 libinput Send Events Mode Enabled Default (258): 0, 0
 libinput Left Handed Enabled (280): 0
 libinput Left Handed Enabled Default (281): 0
 libinput Scroll Methods Available (282): 1, 1, 0
 libinput Scroll Method Enabled (283): 1, 0, 0
 libinput Scroll Method Enabled Default (284): 1, 0, 0
 libinput Disable While Typing Enabled (285): 1
 libinput Disable While Typing Enabled Default (286): 1
 Device Node (259): "/dev/input/event7"
 Device Product ID (260): 2, 7
 libinput Drag Lock Buttons (287): <no items>
 libinput Horizonal Scroll Enabled (261): 1


After applying the set-prop command, list-props displayed (for attribute 283):

 libinput Scroll Method Enabled (283): 0, 1, 0

Note(s): I pulled all this xinput tweaking from the aforementioned links; I didn't come up with any of this on my own. The attribute number (283) could change, I guess the input id could change too. I don't know if you can just hammer a hard coded value for these things.  Finally, I suppose, it would be easy to whittle up a startup script of some sort that could re-apply this setting on startup or login (setting is lost during reboots).

BumbleBee

As before, I just copied and pasted and otherwise followed the directions from here.  The basic nouveau stuff is working fine and that suits my needs.


Saturday, October 31, 2015

Getting HotswapAgent To Work With Gradle & Netbeans

So I am slightly jealous of  some of the other coder-monkeys I work with:  they take advantage of jrebel to reduce turn around times on webapp work.

For unknown reasons I have never really embraced jrebel.   It is hard to explain why, it seems like a good tool, but I just won't use it.

At any rate, for the uber tedious tasks of formatting HTML views and rough out work of java controllers, a short cut around the full redeploy would greatly improve my through put.

HotswapAgent claims to be an OSS and free solution for hot class updating comparable to jrebel.   I decided to give it a go.

My Parameters

So I don't like my development models and procedures to deviate too much from the official build practices and procedures established for the projects I am working on.  Gradle is my LCD for build and project management.   The rest of the parameters of the experiment follows:
  • JDK 1.8 u 66
  • JBOSS EAP 6.x or Wildfly 8.x or greater (I opted for WF 9.0. as my test project for the exercise would table into ee7; for the Hotswap agent part, I don't think JBOSS vs WF matters). 
  • Gradle, of course; I chose 2.8
  • Hotswap Agent 0.3 - Stable (& DCEVM-light-8u5, more about that latter). 
  • Netbeans 8.1rc2  and gradle support plugin version  1.3.7.2 (but earlier versions will probably work).  
Notice that most of the ingredients above are fairly bleeding edge.   I do think I can ratchet back to more main stream releases of the above stuff and this process should still work.  Oh and it probably doesn't matter a ton, but fwiw; I was doing this on my laptop running Fedora Core 22 (x64).  Finally, it helps to be familiar with gradle and the gradle support in NB. 

Installing HotswapAgent

Go here and follow the directions.  Now, you'll see that one of the first steps is to instrument your jvm with DCEVM.   Further you'll notice that I threw caution to the wind and used the u51 installer on u66.  While this proved to be a working combo (in my case), I had issues (unrelated to the jdk mismatch). 

I don't know why I continue to do this, but 9 times out of 10, while following some recipe from the interwebs (like the HSA quick start directions), I take some short-cut or liberties with the instructions, as if I know better than the instructions. DO NOT DO THIS! It almost always back-fires. Follow the directions or recipe meticulously and reproduce the documented product first. Only after reproducing the results as per the instructions, should you begin your own hacking.

I stuffed the hotswap-agent.jar in a directory called  /opt/HotswapAgent-0.3.    In the "Run your Application" section, the quick start says to start your application the following command line additions:

-XXaltjvm=dcevm -javaagent:PATH_TO_AGENT\hotswap-agent.jar


This translated to:

-XXaltjvm=dcevm -javaagent:/opt/HotswapAgent-0.3/hotswap-agent.jar

I chose to put it in the server properties dialog as suggested here.  It looks like this:



Now starting WL 9.0.1 from NB will output stuff like this:

HOTSWAP AGENT: 17:58:59.760 INFO (org.hotswap.agent.HotswapAgent) - Loading Hotswap agent {0.3.0-SNAPSHOT} - unlimited runtime class redefinition.
HOTSWAP AGENT: 17:59:0.237 INFO (org.hotswap.agent.config.PluginRegistry) - Discovered plugins: [Hotswapper, WatchResources, AnonymousClassPatch, Hibernate, Spring, Jersey2, Jetty, Tomcat, ZK, Logback, JSF, Seam, ELResolver, OsgiEquinox, Proxy, WebObjects, Weld]

These lines will be towards the top of the server output.  There are a couple of other ways to nail in these settings:  hack the standalone.conf (or other suitable conf) or perhaps set the environment variable JAVA_OPTS.

The Gradle Bits

So I will spare all the gory details of how I got to it,  and just present the gradle file that proved to be a working solution for my simple tests.   Some discussion will follow the example:

apply plugin: 'war'

sourceCompatibility = '1.8'
[compileJava, compileTestJava]*.options*.encoding = 'UTF-8'

repositories {
    mavenCentral()
}

dependencies {
    providedCompile 'javax:javaee-api:7.0'
    
    testCompile group: 'junit', name: 'junit', version: '4.10'
}

task wrapper(type: Wrapper) {
    gradleVersion = '2.8'
}

ext.deployBase="/opt/wildfly-9.0.1.Final/standalone/deployments"
ext.deployTarget="$deployBase/$war.archiveName"
ext.dodeployLCFname = "$deployTarget" + ".dodeploy"
ext.deployedLCFname="$deployTarget" + ".deployed"
ext.undeployedLCFname="$deployTarget" + ".undeployed"


task updateResources(type: Copy) {
    from 'src/main/webapp'
    into deployTarget
}

task deployWar(type: Copy){
    
    into deployTarget
    with war
    
    doLast{
        def f = file(dodeployLCFname)
        f.lastModified = System.currentTimeMillis()
        f.createNewFile()        
    }
}

task undeployWar <<{
    delete deployedLCFname
    delete deployTarget
    delete undeployedLCFname
}

Basically this gradle has tasks to (in addition to the normal stuff):

  • deploy an exploded war into the wildfly deployments directory, including the creation of a deployment  life cycle marker file that tells WF to deploy the app in the .war directory.  Pro Tip:  The deploy scanner needs to be turned on (usually defaults to on) and more info about the life cycle marker files is here.
  • undeploy will drop the needed marker file and clean up the exploded war area. 
  • updateResources refreshes the files from the webapp source directory to the exploded war area (more on this later).

How To Use

Mostly follow the directions on the quick start.  Here are the steps using NB actions, menus, or buttons: 


1)  Start WF in debug mode:
2)  Clean and build the WAR project:

3)  Deploy the WAR:
4)  Test your app  to get a base line.
5)  Attach NB Debugger to running WF instance:
6)  Make a change to java file (presumably a file that will noticeably affect the test) and save it.
7)  Use the NB Debugger apply changes:
8)  Retest and observe changes

What About HTML, JSF, or JSP Pages or Other Resources

The non .java things should be hot swappable too.  I had to spend a bit of time hunting this down. HSA has a configuration properties file called hostswap-agent.properties that is supposed to help control a few things.  What the NV pairs do and how to apply them took some work.

For starters, "it [hostswap-agent.properties] goes on your classpath" isn't really helpful.  That statement can mean a bunch of things with the complexities of modern EE servers.   Trial and error lead me to the fact that for a war,  /WEB-INF/classes will work.

Early on in my experiment I was using native NB projects (ANT files) to get this working.    The HSA property 'extraWebappContext' worked for activating updates to resources being immediately available to WF without any extra steps.    I couldn't repeat that result for gradle projects; and thus the task updateResources was needed.

In my sample, I was using JSF so after I touched an facelet (xhtml file), I had to:
and then changes to my resources 'took'.

Areas For Improvement

It is not perfect, but it works and reduces the need to redeploy frequently.   Here are some things that could use some attention and I hope to continue to tinker with:
  • The G4NB plugin allows some customizations of IDE actions to the corresponding gradle  tasks that will be invoked.   Apply code changes could trigger 'updateResources', making the process of hot applying of java and others resources, the same. 
  • The hotswap-agent.properties may still be tunnable so that updateResources isn't needed for stuff like JSF files. 
  • Perhaps there is a way to chain the G4NB IDE action 'build' to invoke 'apply code changes'?
  • updateResources copies all files, regardless of changes; perhaps, there is a way to only refresh files affected by most recent save? 
  • HSA has support for 'autoHowSwap'.   This seems like it gets rid of the need to 'Apply Code Changes' and having a debugger attached to target vm.  If this is the case, then some simple but slick combination of  G4NB IDE action tweaks and gradle tasking could further eliminate some clicks or needed interactions. 
  • What about EARs?  Or wars, with some jars or ejb-jars that need swapping?   HSA has devices for this; but some technical investigation is needed to see how this recipe can include these things. 
  • So a simple gradle task dependency, like deployWar.dependsOn war, would take away the build step. 
  • The gradle stuff could be wrapped up in a plugin or the like, and indeed my 'flyboss' plugin has a stub for exploded deployments that I haven't finished yet.   

Project Structure

This sample was exceedingly simple and followed normal  maven/gradle source code organization.   Here is a quick picture of the file organization:


Saturday, February 7, 2015

Gradle Plugin for JBOSS and Wildfly: the flyboss Plugin

So in previous efforts I had worked on a gradle plugin that does some simple stuff with wildfly.   Go see post shere and here to review that.    As mentioned, I felt this plugin could work equally well against JBOSS 7x and JBOSS eap 6x.

While I continued with some light work on this and stuff IRL was pushing me more towards JBOSS EAP 6x; I felt that I should refactor things a bit to make sure it would truly work on jboss and wildfly.   More or less I copy/forked it and created a 'gradle-flyboss-plugin'.

The code for this plugin & post is github at https://github.com/fwelland/gradle-flyboss-plugin.

The Changes

The plugin really didn't change much in function; it still just does start and stops and deploys for archives to a local app server.     However the code has been tweaked to support working with either jboss or wildfly and I made a few internal simplifications and changes as well as laid some foundations for future work.

A Sample

The follow build file is from a multi-part gradle project.  This build file is a standalone or add on build that provides some simple start/stop tasks as well as a deploy (and undeploy) of an artifact in another sub-project.

apply plugin: 'flyboss'
buildscript {
    repositories {
        maven {
            url 'http://dl.bintray.com/fwelland/FredsStuff'
        }
    }   
    dependencies {
        classpath 'org.fhw:gradle-flyboss-plugin:0.1'
    }
}
flyboss {
   appserver_home = '/opt/jboss'
   path_to_deployable =  tasks.getByPath(':main:ear:ear').archivePath
}
deploy.dependsOn  ':main:ear:ear'
task build (dependsOn: deploy )

Some Notes

Like my previous wildfly effort, I am using travis-ci for continuous integration builds.    Also like before I am publishing a plugin jar to BinTray; the latest version will be here:  http://dl.bintray.com/fwelland/FredsStuff.


Sunday, December 21, 2014

Fedora 21 on a Mythlogic Chaos 1313 (aka Clevo W230ST)

Works!

Out of the box.    I downloaded the f21x64 live image, burn't it to an 8GB USB stick, rebooted into setup, and did a 'install' operation.   The pure install time was like 20 minutes.  After that, everything seemed to work. 

You can look back at my f19 and f20 installs on same hardware.   Those installs went really well too, but I did a tweak or two post install.  After about 36 hours, I haven't had to do much. 

SNX/Checkpoint VPN

To get SNX/SSL VPN working, basically I followed the exact same stuff I did for f20:

#Get a JDK & install
su - root
#cd ${HOME}/.mozilla/plugins
#ln -s ${JAVA_HOME}/jre/lib/amd64/libnpjp2.so
#download snx_install.sh  (you should be able to get it from your vpn login webpage under "settings")
su - root
setsebool -P unconfined_mozilla_plugin_transition 0
sh snx_install.sh
yum install /lib/ld-linux.so.2 libX11.so.6 libpam.so.0 libstdc++.so.5 xterm
#(re)start firefox

This time I used OpenJDK 1.8_25.   Rather than sym-linking the plugin file, I had to yum install icedtea-web to get java plugin stuffs for firefox.    After that (and a firefox restart), I had working java applets in firefox.    The rest of the instructions, are needed to get SNX to work properly.  

How I Prep For a New Fedora

I like to do a clean install with each Fedora release; it is just what I do.  I have an exceedingly simple backup strategy:
  1. tar/gz up directories I want to save & restore
  2. move the tar.gz file to a USB drive or network drive
  3. repeat on other directories
I do this for /home/<my_user_name>, /root and /opt.   I have a simple script for doing this:

#!/bin/bash
targ_dir=/run/media/fwelland/BackupData
tm_str=`date +"weedeater_home_%m_%d_%Y"`
echo $tm_str
cd ${targ_dir}
mkdir $tm_str
cd $tm_str
tar czvf home_dir.tar.gz --exclude=./gvfs/* /home/fwelland/  2>&1 >tar.log 

The restore is simple:
  1. copy tar.gz from attached storage into some temporary direcory
  2. un-tar-gz it
  3. move directories and files into new home dir directories
  4. clean up any leftovers where un-tarring happened. 
HTH!

A Update After 4 Days

After using it for a bit, here a few things I noticed.

Random Hang on Resume

Probably 70% time, I slam the clam shut and set my laptop aside rather than power down.   Under earlier fedoras, my laptop would just resume back to the lock screen after opening the clam.   This is still the case under f21, but I'd say 2/5ths of the time the screen is a locked and takes no input.   Nothing, I can't switch to a VC or ctl-alt-bkspace or any input; well except for the power button.    

This problem was very similar to what I saw under f20 on same laptop.  I decide to hang loose for a bit on trouble shooting this as I new I'd be doing BumbleBee and that seemed to solve the issue under f20.

BumbleBee

As before, I just copied and pasted and otherwise followed the directions from here; I was shooting for the the proprietary nvidia drivers.   It didn't work.    I did some trouble shooting and found that the nvidia driver wasn't there or anywhere  (random log message somewhere suggested 'nvidia not found'). 

More research and I found that I actually applied some RPMs out of order  (did bumble-nvidia before bbswitch and bumblbee) and that the nvidia driver builds some vital hunk of code either on install or maybe first use (or maybe after first reboot, after install).     For whatever reason, this didn't happen.   I cleaned out the rpms and reapplied them in order and rebooted and retested 'optirun glxgears'.    Still didn't work; but during the TI  (tech investigation), I did seem some nvidia stuff doing some sort of build.   

More TI.  Bumblebee seemed to be 'running' but optirun wouldn't 'go'; something about "failed to get session".   More TI and logs said something about no permission to /dev/tty0 and some googling lead to this, this and this.     I disable SELINUX (how?) and rebooted.    All is well now.    Hangs on resume have stopped too.





Tuesday, September 30, 2014

My Gradle Wildfly Plugin, 'Continued'

I have been toying around with a custom gradle plugin to perform some basic administrative activities against a local wildfly application server.   This project is more of a learning experience for me, but it could be useful to others.   I have the basic stuff working and it is free for the taking at this github repo.

Recently I decided to add more stuff to it and make it a bit more general purpose and configurable.   While doing some of this work; I also wanted to practice some 'contentious delivery' stuff.

IRL, I am involved in a project that "does CD".   In a nutshell, the project's application CD pipeline does:
  1. merged pull-requests trigger a jenkins pipeline
  2. gradle builds and runs unit and integration tests 
  3. gradle makes an RPM that is pushed to nexus
  4. an infrastructure pipeline merges into this application pipeline
  5. cucumber does acceptance tests over the RPM artifact
  6. puppet automates the build out of whole new application stacks for testing and then to production.  
So I wanted to approximate some of this stuff with my toy plugin.  This is what I did.

The code for this post is github at https://github.com/fwelland/gradle-wildfly-plugin.

spock

So after I got something working and I decided to evolve it some, I also thought it would be good to practice keeping up a good set of tests for the plugin.  Since SPOCK has been on my short list of things to checkout and the inspiration for this plugin, gradle-cargo-plugin , uses it; I decide to take the plunge.

In brief, spock is a groovy based testing framework.   It can act like JUNIT tests and it also is a bit BDD like.  In this post, I am focusing on the CD stuff so I will not go into details of spock.  Go read about it here and check out the little bits of spock I have in this plugin.

bintray

Here is the old way 'client' gradle projects were using this plugin.
buildscript {
    repositories {
        flatDir {
            dirs '../gradle-wildfly-plugin/build/libs'
        }
    }    
    dependencies {
        classpath name: 'gradle-wildfly-plugin'
    }
}
But what I really wanted was something like this:
buildscript {
    repositories {
        maven {
            url 'http://some.place.com/SomeRepo'
        }
    }    
    dependencies {
        classpath 'org.fhw:gradle-wildfly-plugin:0.2'
    }
}
I turned to BinTray as a place to set up my own maven like repo.   After some playing around with BinTray and the help of the bintry/gradle plugin, I was able to land on this bit of gradle to publish builds:
bintray {
    user = uzer
    key = creds

    filesSpec { 
        from 'build/libs'
        into "org/fhw/gradle-wildfly-plugin/$version"
        include '*.jar'
    }
    
    dryRun = false 
    publish = true 
    pkg {
        repo = 'FredsStuff'
        name = 'gradle-wildfly-plugin'
        desc = 'simple gradle plugin for basic jboss manipulation on a workstation!'
        websiteUrl = 'http://stupidfredtricks.blogspot.com/2014/08/a-simple-gradle-plugin-for-wildfly-and.html'
        vcsUrl = 'https://github.com/fwelland/gradle-wildfly-plugin.git'
        licenses = ['Apache-2.0']
        labels = ['gradle', 'wildfly', 'java', 'jboss']             
    }
}

travis-ci

travis-ci is a CD service for github projects (and some other things too).  Here are the basics steps to 'do' travis:

  1. make a travis account  and log in
  2. in travis-ci turn on CI for the github repo 
  3. put a yaml file in root of github repo
  4. push code to github repo
Most of this is document in more detail here.     What is most interesting is my .travis.yml.

language: groovy
jdk:
- oraclejdk7 
after_success: 
- ./gradlew  bintrayUpload -PbtIdentity="${btIdentity}" -PbtIDCreds="${btIDCreds}"
env:
  global:
  - secure: e1ChIoTY48SBhN.......
  - secure: Uxp73loI5NIIhB.......

Here is a quick break down of what's going on:
  1. its a groovy project
  2. its using oracle jdk 7
  3. it invokes the bintrayUpload task after a successful build
  4. it has some encrypted environment variables
So to make that encrypted environment variable stuff you'll need to have ruby installed and use gem to install the travis cli.    Here is a quick example:

travis encrypt btIDCreds=gook-to-encrypt-here --add

Here is more documentation on this process.    Notice the '--add' switch will hammer this into your .travis.yml for you.  Why encrypt?   Well, the .travis.yml sits in the root of my repo which is public.   

Finally the after_success block, re-runs gradle executing the bintrayUpload task.    Notice, that I had to add -P arguments to gradle command-line to 'resubmit' build properties from the .travis.yml environment.

One other little piece of magic

So when running and/or testing the gradle.build locally, the natural way to handle and provide user specific gradle build parameters is NV pairs in $HOME/.gradle/gradle.properties.   In travis, there really isn't $HOME/gradle/gradle.properties; so these values need to be provided in another way.   As implied above, travis-ci will provide environment to the gradle.build.   So one can either always use environment variables or provide simple groovy expression to see if there is a gradle properties value or fall back on the environment variables
def uzer = hasProperty('btIdentity') ? btIdentity : System.getenv('btIdentity')
def creds = hasProperty('btIDCreds') ? btIDCreds : System.getenv('btIDCreds')

Thursday, August 7, 2014

A Simple Gradle plugin for Wildfly (and probably jboss)

When doing EE prototype work, I like convenient ways to deploy and redeploy archives to my target app-server.   I use Netbeans, primarily, and its native build system has a pretty good set of features and plugins integrating IDE and app-server work.

For work that I plan to share, I  like to use a non-IDE based build system and gradle is my weapon of choice these days.   Gradle works well with most of the IDEs out there and it is great LCD for sharing work with out forcing my IDE preferences upon others.   It also has lots of plugins for all sorts of things; including app-server integration plugins.

Finally, I have been using Wildfly 8.x for much of my prototyping work and for my latest POC I wanted some gradle tasks do some basic local app-server control stuff  (start, stop, deploy, undeploy).  

Cargo has a nice gradle plugin that seems to handle much of those tasks for wildfly, as well as many other app-servers.     However, it seems to lack a simple local re-deploy feature.    So I decided to take on a new POC:  build my own simple gradle/wildfly plugin.

Where To Start?

Well, here is a great place to start.   Really, just do some of the samples in this chapter; it will provide the basics.  From there I browsed the source of some of the countless gradle plugins on github.   Since this was more about getting my feet wet writing a gradle plugin, I adopted a simple set of design elements and compromises:
  • Only going to concern myself with local wildfly and the 'standalone' configuration
  • Only going to allow for some configuration of wildfly parameters, in the fist iteration
  • Only going to execute 'standalone.sh' and ‘jboss-cli.sh’ to provide plugin implementation.
  • Only pay attention to deployment or EARs and WARS, right now and ignore deployments or redeployments of data sources or other configuration elements.
  • Probably going to consider making it work for JBOSS AS 7x, and JBOSS EAP 6x, too; since simple administration for all of these is just about the same.

How Does it Work?

So the gradle custom plugin documentation lays out much of what you need to know; so I will not rehash that stuff here. But here are some general steps:Extend the plugin class
  1. Choose the plugin implementation language. I chose to implement this plugin in Groovy. Gradle plugins can also be implemented in Java or Scala (or perhaps other VM languages).
  2. Build a simple project area.   This project area pretty much follows normal gradle directory conventions but groovy code goes into a root called ‘groovy’:
  3. Make an exceedingly simple build.gradle to build the plugin code:
  4. apply plugin: 'groovy'
    
    dependencies {
        compile gradleApi()
        compile localGroovy()
    }
    
  5. Extend the gradle Plugin class in a groovy class.
  6. The plugin extension has an 'apply' lifecycle method to override. This is where tasks are registered and the extension is added to a project. Other initialization activities can go in the apply method too. Sample:
  7. package org.fhw.gradle.wildfly
    
    import org.gradle.api.Project
    import org.gradle.api.Plugin
    
    class WildFlyPlugin implements Plugin {
            
        @Override
        void apply(Project project) {        
                    
            project.extensions.create("wildfly", WildFlyPluginExtension)        
            project.task('start', type: StartWildFlyTask)
            project.task('stop', type: StopWildFlyTask)        
            project.task('deploy', type: DeployWildFlyTask)                
            project.task('undeploy', type: UndeployWildFlyTask)
        }       
    }
    
  8. Make an extension class to serves as a template of what properties can be configured in a closure of the build file that uses the plugin. Like this:
  9. package org.fhw.gradle.wildfly
    
    class WildFlyPluginExtension {
        def String wildfly_home = '/opt/wildfly'
        def String start_script = 'standalone.sh'    
        def String cli_script = 'jboss-cli.sh'
        def String start_regex = '^.*started in.*- Started.*$'    
        def String path_to_deployable = null 
        def String deployment_name = null 
    }  
    
  10. Provide implementation of the registered tasks. Here is a sample:
  11. package org.fhw.gradle.wildfly
    
    import org.gradle.api.tasks.TaskAction
    import org.gradle.api.tasks.Input
    import org.gradle.api.DefaultTask
    import org.apache.tools.ant.taskdefs.condition.Os
    
    class StartWildFlyTask extends BaseWildFlyTask {
                 
        @TaskAction
        def start() {
            def binDir = getWildFlyBinDir()
            if( ! isUp() )
            {        
                ProcessBuilder builder = new ProcessBuilder(getStarterScript())
                builder.directory(new File(binDir))                    
                builder.redirectErrorStream(true)
                Process process = builder.start()            
                InputStream stdout = process.getInputStream()
                BufferedReader reader = new BufferedReader(new InputStreamReader(stdout)) 
                def reggie = getStartRegex()
                def line
                while ((line = reader.readLine()) != null) {
                    if (line.matches(reggie)) {
                        println line
                        break
                    }
                }            
            }
            else
            {
                println "seems like wildfly is already started."
            }
        }
    }
    
  12. Wrap all of the above into a jar with a gradle-plugins properties file used to indicate the class(es) that provide the new plugin. Here is a sample plugin properties file:
  13. implementation-class= org.fhw.gradle.wildfly.WildFlyPlugin
    
  14. Apply the plugin in a gradle build file that needs basic start/stop/deploy/undeploy tasks for Wildfly. Here is a sample:
  15. apply plugin: 'ear'
    apply plugin: 'wildfly'
    
    buildscript {         //this bit points to a dir that has the jar containing the built plugin. 
        repositories {
            flatDir {
                dirs '../gradle-wildfly-plugin/build/libs'   
            }
        }    
        dependencies {
            classpath name: 'gradle-wildfly-plugin'
        }
    }
    
    // other stuff….
    
    wildfly    //this bit is a closure where this build can customize the task behaviour some. 
    {
       wildfly_home = '/opt/wildfly-8.1.0.Final'
       deployment_name = 'Schlepp'
    }
    

That is the very basic anatomy of a gradle plugin! At this point, in the ‘client’ build file has new tasks are available:
$ gradle tasks
:tasks

------------------------------------------------------------
All tasks runnable from root project
------------------------------------------------------------

Build tasks
-----------
assemble - Assembles the outputs of this project.
build - Assembles and tests this project.

//snip for brevity 

Other tasks
-----------
deploy
start
stop
undeploy
wrapper - Creates and deploys the Gradle wrapper to the current directory.

//snip for brevity 

BUILD SUCCESSFUL
The code for this post is github at https://github.com/fwelland/gradle-wildfly-plugin.

What's Next?

This example hopefully shows that it is pretty easy to create a custom plugin for gradle.  As mentioned earlier, this plugin really is just for interacting with local Wildfly instance.  It will probably also work with most JBOSS 7+ versions (and its variants) too.  In the near future I plan to (or may consider doing):
  • add in more configuration properties about the target wildfly install
  • put a copy of it somewhere to get rid of funky directory reference for plugin implementation
  • build some unit-like tests to exercise the plugin
  • shore up deploy tasks so that other archive types can be deployed
  • maybe de-brand it from wildfly and make more generic to cover jboss too
  • others?

Sunday, July 13, 2014

Java Hack to Scrape Passwords from GNOME Keyring & Chrome.

You already know I use linux most of the time and its pretty easy to tell I use Chrome too.   Well what you may not know is that I am also an Android user and flash custom roms from time to time.    Oh, and I also have lots passwords for various sites and things I use.

A few years ago, I started using UPM as a password manager on my phones & roms.    It is simple and works well for my needs.    I have always be able to back-up and restore UPM and its data, using Titanium Backup Pro.    However, this broke with my first foray installing an android 4.4.x rom on my Galaxy Note 2.   I lost all my passwords.    I had about 50 or 60.

Most of these passwords (and user names) were 'safe' as chrome has it own simplistic password manager that on linux is backed by the GNOME KeyRing.   I could simply create a new UPM data-base and copy and paste them from Chrome.  So I started, and then after about 3  C-n-P options I began to search for an export option as UPM supports a csv import.

Suitable, IMHO, export widgets for chrome don't exist; nor could I find one for seahorse or gnome key ring. So I thought I would build something on my own; how hard could it be?

Fast Forward and Skipping Details

Turns out it really isn't that hard, but locating needed ingredients and some simple instructions about GTK/Gnome hacking java is a bit time consuming.  After much effort I found this GITHUB project and a fork of that project, here.

With that later project I whittled up this:

package fhw;

import java.util.*;
import net.revelc.gnome.keyring.*; 

public class  UPMCSVDump
{
  public static void main(String[] args) throws GnomeKeyringException {
    GnomeKeyring gk = new GnomeKeyring("UPMCSVDump");
    String keyring = gk.getDefaultKeyring();
    Set ids = gk.getIds(keyring);
    String name;
    String userName;
    String userSecret;
    String url; 
    for(Integer id : ids)
    {
        GnomeKeyringItem gki = gk.getItem(keyring, id, true);
        //System.out.println(gki.toString(true));
        userName = null; 
        userSecret = null;
        name = null; 
        url = null; 
        //account name,user id,password,url,notes
        name = gki.getDisplayName();
        userSecret = gki.getSecret();
        for(GnomeKeyringItem.Attribute a : gki.getAttributes())
        {
            String s = a.getName();
            if("username_value".equalsIgnoreCase(s))
            {
                userName = a.getValue().toString();
            } 
            else if("action_url".equalsIgnoreCase(s))
            {
                url = a.getValue().toString();
            }
        }
        System.out.println(String.format("%s,%s,%s,%s,%s",name,userName,userSecret,url,""));
    }     
  }
}

No Magic Here

It is so simple, it is almost not worthy of sharing; but I did it in case some other poor soul winds up in the same situation.   Source and Gradle project can be found here:  https://github.com/fwelland/UPMCSVDump

2 TIPs

  1. Run this program on linux, logged in as the user whose key ring you need to extract.   Oh and you know, you should be in a gnome session that has already unlocked the key ring. 
  2. If you use UPM, maybe use its import/export features rather than relying on android backups and tools like Titanium.