Monday, November 10, 2014

grails.gsp.enable.reload vs disable.auto.recompile in grails 1.3.7

Needed to make some GUI changes to a project that's developed based on grails 1.3.7.

In grails 2.* , if you edit a gsp file, it'll be automatically compiled in a few seconds, and if you refresh, you'd be able to see the changes in your GUI. But for some reason, it didn't seem to work in the my applications that's based on 1.3.7.

After some investigation, I found that I just needed to add the system property "-Dgrails.gsp.enable.reload=true" to the grails run-app. Then update the gsps and do a refresh of the web page. Unlike grails 2.*, there's nothing in the grails run-app log that indicates the changes to the gsp files have been picked up, and this got me stuck for a while, because I was expecting to see some change in the logs (Maybe the missing of the logs was due to my log4j setting).

The "-Ddisable.auto.recompile" property is to control the auto recompile of the java and groovy classes. And it's accomplished in grails via the following -

        ant.groovyc(destdir:classesDirPath,
                    classpathref:classpathId,
                    encoding:"UTF-8",
                    verbose: grailsSettings.verboseCompile,
                    listfiles: grailsSettings.verboseCompile,
                    excludes: '**/package-info.java') {
            src(path:"${grailsSettings.sourceDir}/groovy")
            src(path:"${basedir}/grails-app/domain")
            src(path:"${basedir}/grails-app/utils")
            src(path:"${grailsSettings.sourceDir}/java")
            javac(classpathref:classpathId, debug:"yes")


Tuesday, October 28, 2014

winrm quickconfig -2144108269 0x80338113 error

Got dragged by a user into an online chat today about a winrm issue. Couldn't find a solution online after rounds of "googling". But finally figured out the problem. Post it below, hope it helps if you are in the same situation-

Symptom:
Users have two winrm server hosts, and not able to run "winrm quickconfig" on either. One of the host is new, so they never run winrm there before. But the other host, users were able to run "winrm quickconfig" a while ago and were able to setup the winrm http  & https listeners there. But now although they can still use "winrm e winrm/config/listener -r:<winrm_server_host>" to see the winrm listener setting from a client host, on the winrm server host itself, they see the following error whenever they run "winrm quickconfig" -
============================
C:\Users>winrm quickconfig
WinRM already is set up to receive requests on this machine.
WSManFault
            Message = The WinRM client sent a request to an HTTP server and got a response saying the requested HTTP URL was not available. This is usually returned by a HTTP server that does not support the WS-Management protocol.

Error number:  -2144108269 0x80338113
==============================

Investigation:
Checked "winrm get winrm/config -r:<winrm_server_host>" from a remote machine. And all looked fine.
Checked "winrm e winrm/config/listener -r:<winrm_server_host>" from a remote machine. All looked fine too, except that besides "127.0.0.1" and "::1", there were two other ips for the host (which usually is only one ip). Turned out that this was not an issue, because the host had 2 nic cards.
But the two ip addresses prompted me to ask the user if there's anything unusual or if anything had been changed in the hosts file. And user realized that an entry for "localhost" had been recently  added to the "etc\hosts" file, which had changed the ip for "localhost" from default 127.0.0.1 to the host's ipv4 address.

Resolution:
Had user comment out the localhost "redirect" line in the etc\hosts file. And user was then able to run the "winrm quickconfig" on the winrm server host without error.




Monday, October 27, 2014

rundeck calling xebialabs overthere for winrm connection

Got a meeting "invitation" from a fearful client regarding how to setup a node in rundeck that uses winrm. 
To survive the meeting, I buried my head into the rundeck and xebialabs overthere  code for the whole afternoon :(  and here's what I figured out -

1. rundeck has a winrm plugin (OTWinRMNodeExecutor class). And the plugin looks for the domain mapping in the $RUNDECK_BASE/krb/domain.properties file. This file could be a simple name/value mapping, with name being the shortened domain name (such as "ABC"), and value being the full qualified domain name (such as "ABC.MYCOMPANYNAME.COM")

the winrm plugin also looks for the $RUNDECK_BASE/krb/realm_kdc.properties file. This file again has a name/value mapping, with name being the realm name(usually the upper case domain name), and the value being the pdc host.

2. Based on the domain name of a node, the plugin would set the following 2 system properties -
java.security.krb5.realm - the realm name( the all upper case host domain name)
java.security.krb5.kdc  - the kdc host name (the kdc defined in the realm_kdc.properties file for the particular domain)

3. the plugin would then invoke the xebialabs overthere CifsConnectionBuilder to make the winrm connection, and pass in all bunch of connection options.

4. CifsConnectionBuilder creates a CifsWinRmConnection which then creates an ApacheHttpComponentsHttpClientHttpConnector and passes in the username & password from the plugin options. ApacheHttpComponentsHttpClientHttpConnector, as the name indicates, is the center of the implementation -
- it checks if the username is of a format "username@domainName". If so, kerberos authentication is considered enabled.
- it creates a httpclient, and registers the KERBEROS and SPNEGO authentication schemes
- it sets the credentials with "httpclient.getCredentialsProvider().setCredentials(...)" for the KERBEROS and SPNEGO schemes
- and of course, it sends SOAP requests and receives responses

5. Both of these documents are great read, although not sure how up-to-date the 2nd link is -
- http://docs.oracle.com/javase/7/docs/technotes/guides/security/jgss/tutorials/KerberosReq.html#SetProps
- http://hc.apache.org/httpcomponents-client-ga/tutorial/html/authentication.html

Hopefully now I can answer a question or two to survive till the next meeting :(

Thursday, October 16, 2014

keon routes for passwordless ssh

Being in a very small team means I not only have to do development, but also have to handle L3 support issues. This client had 2 issues -

1. why in the DEV environment, the passwordless ssh only works for some hosts, but not the others
2. why the passwordless ssh from our UAT server to their UAT server doesn't work for their functional id


After spending 40 minutes on the conference call, on the chat, and staring at their tiny shared screen with super tiny fonts, finally noticed a typo in their public key. The ssh public key should start with "ssh-rsa", somehow, on the hosts that failed passwordless ssh, their public key started with "sh-rsa". They apparently cut off the first "s" when they copied/pasted. A typo costs 4 people 40 minutes each? And it took 3 days for the ticket they opened to reach me, and one of them is a VP. Wonder how much that costs the firm.

Issue #2 seemed a more fair question, because they didn't know that the keon access routes for their functional id needed to be setup from our host group to their host group first. Showed them how to use keon website to check the host groups and access routes, and they were happy to setup the keon routes themselves.

Grails platform-core plugin navigation menu

Took on the responsibility to develop a new application lately and decided to use grails platform-core navigation plugin to implement the 2 level menu I had in mind.

A quick look at the online documentation of the platform-core navigation plugin made me think that it's a 20 minutes job. Started by adding the "compile ":platform-core:1.0.0"" into BuildConfig.groovy, and  adding the <nav:primary/> & <nav:secondary/> tags into main.gsp,  then run "grail run-app". hooray, it worked. All the controller showed up as primary menu items, and their actioned showed up as secondary menu items.  Simple enough!

But here comes the headache, I need to customize the menu so it doesn't show all my controllers & actions, and also need to have some user friendly names for my menu items. So following the online manual, I added "AppNavigation.groovy" file and the navigation closure. But it doesn't work! Adding the following causing grails to generate 2 menu items in the 1st level menu for the same controller(say if I have a controller JanProject) -
           Project(controller:"janProject")
If you think you can remove the duplicate menu item by setting the navigationScope for the JanProject controller to a wildly different name than "app", then you will be surprised to see that when you click on the controller in the primary menu, you get forwarded to the automatically grails generated menu again, with all the default controllers & action names.

After many many tries based on the Github navigation DSL sample online, things just got worse. At one point, I started to suspect that this 1.0.0 version in fact doesn't work at all. But switching back to 1.0.RC3 as someone's instruction online, ended up with connection time out error, because the 1.0.RC3 package can no longer be found?

Then started to google like a mad woman trying to find some online successful samples people can provide for a 2 level menu.  The best I could find is a one level menu. Seems that nobody has posted their success story!

Desperate, I downloaded the source code of the platform-core plugin((which I should have done in the first place, but don't we all like shortcuts?) , the "grails-platform-core-master.zip" file. And read the NavigationImpl.groovy, which parses different types of DSL blocks. Then turned on the debug for this plugin. After tweaking the AppNavigation.groovy 20+ times, run-app 20+ times and checking the debug logs of how NavigationImpl processes it, I finally figured out how this stuff works -
1.  if you define a controller with the same name as your controller, grails will not generate a duplicate one for you.
2. If you want to customize your controller name, use titleText
3. instead of using "visible", all you have to do is to provide a list of actions you want to have menu items created.
4.the navigation scope(say, "abc") defined in your controller will cause the menu flow go into that scope (in this case, "abc"), instead of the default "app".  I know, this sounds very basic, but it's certainly not very obvious when it first started, and certainly takes trial and error to figure out.

So there you go. A 20 minutes' plan turned into a 2 day struggle (partly my fault, why didn't I download the plugin source code earlier?). Glad that I finally figured it out though, and now I can create and customize my grails menu in 2 minutes :)