Monday, January 20, 2014

Heading for the clouds

Last week marked the 4th year of my tenure in Jazz for Service Management (it was known by different names at first) , as the lead developer for Registry Services, a data reconciliation service for the multitude of IBM products developed in-house and acquired over the years.

Looking back…

For the first three years I did not write much about the Registry Services experience, other than offering general impressions on leadership and focus on quality in context of the challenges at the time, both in "Guns, Police, Alcohol, and Leadership" and in “On Mountains, Beliefs and Leadership”. In 2013, I did write a more detailed technical account in the Service Management Connect blog.

Without getting into the gritty details of the pace-setting procedural excellence we achieved in these four years (modesty did improve a bit, but the progress we all made in these four years earned us a few seconds of self-congratulatory pats on the back :- ) it is worth noting that over 4000 functional points are now validated in an automated manner in less than 12 hours across key platforms and 24 hours across the complete set of platforms, every single day of the week.

This marked evolution was only possible with disciplined execution within the Agile development method, few steps at a time, guided by stakeholders one sprint demo at a time, honed by team’s feedback one retrospective  session at a time.

I think it will be hard to top the combination of motivation we had from the people executing the tasks with the vision and support from the management team, but four years was also enough time for several people on the team to grow to a level of leadership, skill, and confidence where the smartest thing to do was to make room for a next level of collective growth.

...to look forward

As I started to look for a position to make room for the overall transition, it was to my surprise and delight to hear about the IBM Cloud Operating Environment team just starting to look for a Scrum Master and Dev/Ops lead for its core deployment (based on Pivotal’s Cloud Foundry) . To distill the letter soup, this is essentially IBMs Platform as a Service (PaaS) offering, also known as BlueMix. Within two weeks both teams had lined up the whole transition and starting this week, this is my new professional home.

Cloud and Dev/Ops is a space I have been meaning to enter for a long while. It is an opportunity to work with the most recent technologies in a very competitive space, against established giants, but backed by another giant flexing a multi-billion effort across all of its divisions.

I am looking forward to a brilliant 2014 in company of the BlueMix team, learning how to bring the same level of excellence into a different development model, adapting to the new cultures in our geographically dispersed teams, closing the gaps between development and production deployments (a tooling geek’s paradise) , and moving closer to our customers experience, both in the way we support IBM offerings in BlueMix and watching what development shops around the world will do with it .

Monday, October 28, 2013

Registry Services by the DASHboard light

Quite excited about the prospects of our most recent work on getting Registry Services data (IT resource management) into DASH, the dashboarding component of Jazz for Service Management.

I wrote an entry on the Jazz for Service Management blog:

https://www.ibm.com/developerworks/community/blogs/69ec672c-dd6b-443d-add8-bb9a9a490eba/entry/you_can_see_registry_by_the_dashboard_light?lang=en

The possibilities of integration with datasets from other systems management products offering OSLC interfaces make it really cool.

And there is even a video-recording.

Registry Services data on JazzSM DASH UI

Friday, September 20, 2013

Registry Services on the glass

glassAnother entry related to my current project, Jazz for Service Management. I am quite thrilled about having mixed jQuery and rdfQuery to interact with our OSLC server directly from a web-browser. Look’ma, only 2-tiers:

https://www.ibm.com/developerworks/community/blogs/69ec672c-dd6b-443d-add8-bb9a9a490eba/tags/rsotg?lang=en

Wednesday, September 18, 2013

Renewing expired certificates for wsadmin invocations against WebSphere Application Server

We have a verification lab with about a dozen machines and on a periodic basis we hit a problem where wsadmin cannot connect to an instance of WebSphere Application Server due to a certificate expiration.

Note: This being a closed test environment, this kind of problem can be minimized or avoided altogether by creating the profile in Advanced mode through the Profile Management Tool and choosing longer expiration period than the default one-year period chosen when creating the profile using the manageprofiles command-line tool.

The connection error message returned by wsadmin will not be all that helpful because essentially it does not know why its connection request was refused, but the server logs ($profile/logs/server1/ServerOut.log or TextLog_<timestamp>.log depending on your troubleshooting settings) will contain a very telling message like this:

[9/18/13 10:22:53:664 EDT] 0000001c WSX509TrustMa E   CWPKI0022E: SSL HANDSHAKE FAILURE:  A signer with SubjectDN "CN=hostname, OU=hostNode01Cell, OU=hostNode01, O=IBM, C=US" was sent from target host:port "unknown:0".  The signer may need to be added to local trust store "$profile/AppSrv01/config/cells/hostNode01Cell/nodes/hostNode01/trust.p12" located in SSL configuration alias "NodeDefaultSSLSettings" loaded from SSL configuration file "security.xml".  The extended error message from the SSL handshake exception is: "PKIX path validation failed: java.security.cert.CertPathValidatorException: The certificate expired at Wed Aug 21 21:54:27 EDT 2013; internal cause is:        java.security.cert.CertificateExpiredException: NotAfter: Wed Aug 21 21:
54:27 EDT 2013".

It took me a little while to figure out the keystore used by wsadmin, which turned out to be:

$profile/etc/key.p12

Listing the certificates in the file quickly showed the offending certificate (keep in mind that the default keystore password in WAS is WebAS) :

bash-2.04# keytool -list -storetype PKCS12 -keystore ./profiles/AppSrv01/etc/key.p12 –storepass <password> -v
Keystore type: PKCS12
Keystore provider: IBMJCE
Your keystore contains 1 entry
Alias name: default
Creation date: Aug 22, 2012
Entry type: keyEntry
Certificate chain length: 2
Certificate[1]:
Owner: CN=hostname, OU=hostNode01Cell, OU=hostNode01, O=IBM, C=US
Issuer: CN=hostname, OU=Root Certificate, OU=hostNode01Cell, OU=hostNode01, O=IBM, C=US
Serial number: 2623bc78cd3b
Valid from: 8/21/12 9:54 PM until: 8/21/13 9:54 PM
Certificate fingerprints:
         MD5:  D2:FB:3F:8A:53:6F:19:B2:6C:77:AB:00:AC:40:EC:0B
         SHA1: 64:76:8F:7F:2A:0A:6A:F0:C9:21:86:FF:90:5B:C5:FA:FF:64:61:B4
Certificate[2]:
Owner: CN=hostname, OU=Root Certificate, OU=hostNode01Cell, OU=hostNode01, O=IBM, C=US
Issuer: CN=hostname, OU=Root Certificate, OU=hostNode01Cell, OU=hostNode01, O=IBM, C=US
Serial number: 2622d2d16331
Valid from: 8/21/12 9:54 PM until: 8/18/27 9:54 PM
Certificate fingerprints:
         MD5:  C2:CB:AB:C3:3A:6C:D2:77:6A:87:DA:D7:21:2E:DC:E4
         SHA1: 0C:09:CD:37:96:F8:FE:91:18:92:5A:93:05:AB:15:D6:6D:36:A1:AA

One can (nay, should) use the keytool command-line to recreate the certificate above, but this being a closed test environment where we do not test SSL functionality, and since we did not have any new certificates added to either wsadmin or server keystores since we installed that test system, I did the unthinkable, that is, overwrite the wsadmin keystore with the server keystore.

cp $profile/config/cells/hostNode01Cell/nodes/hostNode01/key.p12 $profile/etc/key.p12

Note: The last step was a very specific decision for a test environment running WebSphere Application Server. **DO NOT** take the last step on a production environment or where company policies do not allow for it, and only after carefully examining the two keystores to ensure all their fields (sans expiration date) are exact matches.

Thursday, May 30, 2013

I am on GitHub…bookmarks, linked data, and more to come.

While writing more extensively for the System Management Connect blog,  I ended up creating some source code examples, which quickly evolved into interesting side projects.

At the same time, formatting these examples into blog editors became a major hassle with ephemeral results. Blog editors are definitely not geared for handling the heavy syntax of source code (yes, yes, good luck with “pre” tags) and even when you achieve good results, they are completely botched months later when the website hosting the blogs makes even the most minute change to their CSS stylesheets.

I am now sharing the code examples in a new GitHub account, at https://github.com/nastacio.

My first project, unimaginatively titled “lctodel”, was developed a couple of years ago and copies bookmarks from a Lotus Connections account to a del.icio.us account (I know, I know, where is the bridge to bit.ly?) .

The second project is still unimaginatively, but less cryptically, dubbed dw.article.rdf. It contains a web-based project that showcases Javascript interactions with my current project (Jazz for Service Management) and is based on jQuery and RDFQuery. I started writing about that exercise here.

Back to GitHub itself, I think more and more it has become a necessity for software developers to organize and publicize their hobbies outside their professional work. In my role I often interview candidates for development positions within the company and I cannot overstate the importance we give to a well-executed technical online presence.

Thursday, April 25, 2013

Iterating through response pages queried from Registry Services using Java

This entry is related to my current project, Jazz for Service Management. Instead of reposting it here, here is a link to the original in the developerWorks website:

Iterating through response pages queried from Registry Services using Java.

Tuesday, February 12, 2013

Base 64 Encoding with Java without Apache Commons

I cannot take credit for this very useful hack, which I saw in concept several years ago. Any project dealing with web development will eventually find itself needing to pass on base authentication headers, which must be encoded in Base64 format.

Apache Commons Base64 is widely adopted as the de-facto Java standard for that kind of encoding, but for various reasons, I prefer to avoid adding new dependencies unless absolutely necessary or beneficial.

In that sense, here is the technique, with the key aspects highlighted in bold:

---

package com.blogspot.sourcepatch;

import java.util.prefs.AbstractPreferences;
import java.util.prefs.BackingStoreException;

public class Base64 {

    private static final Base64 instance = new Base64();
    private static final Base64Encoder encoder = instance.new Base64Encoder();

    /**
     * @return the base64String
     */
    public static String encode(String s) {
        encoder.putByteArray("akey", s.getBytes());
        String result = encoder.getBase64String();
        return result;
    }

    public class Base64Encoder extends AbstractPreferences {

        private String base64String = null;

        public Base64Encoder() {
            super(null, "");
        }

        protected Base64Encoder(AbstractPreferences parent, String name) {
            super(parent, name);
        }

        @Override
        protected void putSpi(String key, String value) {
            base64String = value;
        }

        /**
         * @return the base64String
         */
        public String getBase64String() {
            return base64String;
        }

        @Override
        protected String getSpi(String key) {
            return null;
        }

        @Override
        protected void removeSpi(String key) {
        }

        @Override
        protected void removeNodeSpi() throws BackingStoreException {
        }

        @Override
        protected String[] keysSpi() throws BackingStoreException {
            return null;
        }

        @Override
        protected String[] childrenNamesSpi() throws BackingStoreException {
            return null;
        }

        @Override
        protected AbstractPreferences childSpi(String name) {
            return null;
        }

        protected void syncSpi() throws BackingStoreException {
        }

        @Override
        protected void flushSpi() throws BackingStoreException {
        }

    }

}