<< Previous | Home

Test agents in Eclipse by extending AgentBase

I continuously get questions on how I do Java agent development and I'm happy to answer them as I hope that some of the answers I provide means that more and more Domino developers see Java as a strong alternative to LotusScript for background processing. Most times the approach I recommend is a mock object approach that I wrote about waaaaaay back in 2006 (did I really write that 10 years ago?!?!?).

If / when you want to read the posts please start from part no. 1. Here's a link to all 5 parts:

The approach doesn't handle importing the code back into Domino Designer but it does allow you to "mock" the Notes side of the API and allows you to write, test and debug your agents in Eclipse. Then when they're completely done you can import it back into Notes without any changes. This is the approach I would choose and that I still use when writing Java agents here 10 years later.

Hope this helps but if it doesn't please let me know.

Working with routes from the IBM Bluemix CLI

Today I played with routes on IBM Bluemix. Routes are how you access the app on IBM Bluemix so basically they are hostnames mapped to apps. By default apps are assigned a hostname under mybluemix.net but once you've proved a domain belongs to you you may also may custom domain names to your apps. Of course you still need to create a CNAME record in DNS to make it map correctly but you get the point. Working with routes is possible from the GUI but the command line interface (CLI) is more efficient. Below are the commands I use to work with routes. All of the commands assumes you're already logged in... Actual commands in bold.

Listing the routes (as you can see some routes are not bound to apps): cf routes

Getting routes as lekkim ...

space   host                                                domain            apps   
dev     ontime-ibm-connected-2015-verse-demo-contribution   mybluemix.net     IBM ConnectED 2015 Verse Demo Contribution   
dev     otgc-verse                                          mybluemix.net     IBM ConnectED 2015 Verse Demo Contribution   
dev     mikkel-otgcms-test                                  mybluemix.net     Mikkel OTGCMS Test   
dev     mikkel-otgcms-test                                  ontimesuite.com   Mikkel OTGCMS Test   
dev     neodashboard-oauth                                  mybluemix.net     neodashboard-oauth   
dev     spring-boot-demo-mikkel                             mybluemix.net     Spring-Boot-Demo-Mikkel   
dev     engageugdemo                                        mybluemix.net     engageugdemo   
dev     engagedemoapp1                                      mybluemix.net        
dev     engagementdemo1                                     mybluemix.net        
dev     engageugdemoapp                                     mybluemix.net  
Map a route called myapp.ontimesuite.com to the engageugdemo app: cf map-route engageugdemo ontimesuite.com -n myapp
Creating route myapp.ontimesuite.com for org lekkim / space dev as lekkim...
OK

Unmap a route called myapp.ontimesuite.com from the engageugdemo app: cf unmap-route engageugdemo ontimesuite.com -n myapp
Removing route myapp.ontimesuite.com from app engageugdemo in org lekkim / space dev as lekkim...
OK

Permently delete the myapp.ontimesuite.com route from your account: cf delete-route ontimesuite.com -n myapp
Deleting route engageugdemo.ontimesuite.com...
OK

Tags : , , ,

Slides and recorded, narrated, demo from my Engage.ug session on OAuth

Last week at the Engage user group in Eindhoven, The Netherlands, I gave a session on OAuth 2.0, how the protocol works and how easy it is the code against. The demo I showed at the end of the session showed just how easy it is and how little code is required to make a fully functioning OAuth 2.0 Client. Below you'll find the slides on Slideshare as well as a recorded, narrated, demo. The demo walks you through coding an OAuth 2.0 app in Eclipse and deploying it to IBM Bluemix.

Oh and do remember... Never, EVER, use a library until you understand the protocol.

OpenVPN

Have a Synology Diskstation at home which I among other things use as an OpenVPN server. When I'm traveling I enjoy being able to watch Danish TV without any geographical restrictions. I do this by having my OpenVPN profile (ovpn file) tunnel all traffic through the VPN incl. DNS. It also means that I can use it to safely browse if on a questionable wifi such as no-encryption hotel wifi or conference wifi. The two commands you need to add to the configuration generated by the OpenVPN server on the Synology (10.11.12.1 being by DNS in the house) is as follows:

dhcp-option DNS 10.11.12.1"
redirect-gateway def1

Certificate bananza...

Helped a collegue yesterday for a few hours configuring his system with TLS certificates and showed code to enable authentication using client certificates. All easy enough if you know how... :) Start by creating keys and certificates for a server and a person and create a Domino KYR keystore using the kyrtool from IBM. The below commands were all executed on Linux.

# change dir
cd /local/notesdata/

# generate key and self-signed cert for server
openssl genrsa -out server.key 4096
cat server.key 
openssl req -new -sha256 -key server.key -out server.csr
openssl x509 -req -days 3650 -sha256 -in server.csr -signkey server.key -out server.pem

# use kyrtool to generate kyr-file for Domino (all calls to startup below is actually 
# /opt/ibm/domino/bin/tools/startup
startup /opt/ibm/domino/bin/kyrtool =/local/notesdata/notes.ini
startup /opt/ibm/domino/bin/kyrtool =/local/notesdata/notes.ini create 
          -k ./server.kyr -p password
cat server.key > server.txt
cat server.pem  >> server.txt 
cat server.txt 
startup /opt/ibm/domino/bin/kyrtool =/local/notesdata/notes.ini 
          verify ./server.txt 
startup /opt/ibm/domino/bin/kyrtool =/local/notesdata/notes.ini 
          import all -k ./server.kyr -i ./server.txt
startup /opt/ibm/domino/bin/kyrtool =/local/notesdata/notes.ini 
          show keys -k ./server.kyr 
startup /opt/ibm/domino/bin/kyrtool =/local/notesdata/notes.ini 
          show certs -k ./server.kyr 

# generate PKCS#12 for a user
openssl genrsa -out person.key 4096
openssl req -new -sha256 -key person.key -out person.csr
openssl x509 -req -days 3650 -sha256 -in person.csr -CA server.pem 
          -CAkey server.key -out person.pem -CAcreateserial
openssl x509 -in person.pem -text -noout
openssl pkcs12 -export -out person.p12 -inkey person.key -in person.pem -certfile server.pem
Import the the person.p12 file on a person document in Domino Directory. Now copy server.kyr and server.sth to the Domino data dirctory and create an Internet Sites document using the keystore. Also edit the Internet Site document to allow certificate based authentication. The code below uses the PKCS#12 file to do an authenticated request using certificates as authentication.
package demo.intravision.certauth;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.KeyStore;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;


public class Main {

   public static void main(String[] args) {
      try {
         new Main().run();
         
      } catch (Throwable t) {
         t.printStackTrace();
      }
   }
   
   public void run() throws Exception {
      // get url and open connection
      URL url = new URL("https://secure.krynn.local/testauth.nsf/username.json?open&login");
      HttpURLConnection con = (HttpURLConnection)url.openConnection();
      
      // apply SSL context (sets up the certificate to use for authentication etc)
      this.applySSLContext(con);
      
      // read from url
      BufferedReader reader = new BufferedReader(new InputStreamReader(con.getInputStream(), "UTF-8"));
      StringBuilder b = new StringBuilder();
      String line = null;
      while (null != (line = reader.readLine())) {
         b.append(line).append('\n');
      }
      
      // show data
      System.out.println(b.toString());
      
      // disconnect
      con.disconnect();
   }

   private void applySSLContext(HttpURLConnection con) throws Exception {
      // password
      final char[] password = "password".toCharArray();
      
      // input stream to pkcs12 file
      InputStream certificateInputStream = new FileInputStream("/Users/lekkim/Downloads/aran.p12");
      
      // load key and key manager
      KeyStore ks = KeyStore.getInstance("PKCS12");
      ks.load(certificateInputStream, password);
      KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
      kmf.init(ks, password);
      
      // get trust manager
      X509TrustManager customTrustMgr = this.getTrustManager();
      
      // build ssl context
      SSLContext sc = SSLContext.getInstance("TLSv1.2");
      sc.init(kmf.getKeyManagers(), null == customTrustMgr ? null : new TrustManager[]{customTrustMgr}, null);
      
      // set socket facory if https
      if (con instanceof HttpsURLConnection) {
         HttpsURLConnection httpsCon = (HttpsURLConnection)con; 
         httpsCon.setSSLSocketFactory(sc.getSocketFactory());
      }
   }
   
   private X509TrustManager getTrustManager() throws Exception {
      // returning null uses the trust from the JVM cacerts keystore
      if ("1".equals("2")) return null;
      
      // define trust manager
      X509TrustManager customTrustMgr = new X509TrustManager() {
          @Override
          public X509Certificate[] getAcceptedIssuers() {
             return new X509Certificate[]{};
          }

          @Override
          public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
          }

          @Override
          public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
          }
      };
      return customTrustMgr;
   }
}

Custom widgets for IBM Connections v.5.5 and what the "themes" attribute mean

Starting with IBM Connections v. 5.5 a new required attribute was added to the widgets-config.xml file that controls how widgets are rendered for Profiles and Communities. IBM addresses the issue by referring to a technote (Custom widgets not displaying correctly after migrating to IBM Connections 5.5) that mentions just adding an attribute. The fact that simply requiring customers to add static text is lunacy for a product - if you need something where a static text will do for most cases and it's not there then simply assume the value. Don't break installations because some developer or product manager didn't think... End rant...

Anyways - I looked into this for the OnTime widgets and it turns out that the "themes" attribute actually points to WebSphere Portal themes and control where a user may drop widgets. Starting with IBM Connections v. 5.5 users may not only drag'n'drop widgets up and down in the center column but also move widgets to the left and right column. Furthermore with the addition of custom layouts ("Change Layout" for the community owners) a new "banner" location has been added. The banner location stretches from left to right above the right column giving the widget as much horizontal space as an iWidget shown in fullpage mode gets. The value of the "themes" attribute is described by IBM to contain the following values: wpthemeThin, wpthemeNarrow, wpthemeWide and wpthemeBanner, The image below describes there locations in the UI (click the image for a larger image):

So the attribute is actually quite interesting. Adding the "themes" attribute and setting it to "wpthemeWide wpwhemeBanner" I can actually control what the OnTime Group Calendar widget (shown center in the image above) may only be in the "wpthemeWide" and "wpthemeBanner" locations but not in the "wpthemeThin" or "wpthemeNarrow" locations as they are too -- well -- narrow and thin. Sweet!

It's a shame that you can still drop a widget in an unsupported configuration. The user will see a explanation of this not being possible after the fact (and the widget will not render) but being blocked all together would be better. The image below shows the OnTime widget in an unsupported location. A widget which is mandated in Profiles or Communities may still not be moved around and the "themes" attribute does not apply which again is why mandating the attribute be defined is crazy...

If only IBM had a mail client...

Over the last year we've seen more and more customers move to Microsoft Office 365 for mail and calendaring. The funny thing is that very few users actually end up using the webmail experience but almost all end up in Outlook. This made me think that IBM could probably still be competitive in the mail market including for the people who prefer a rich client if it wasn't for IBM Notes. The client is simply too bloated, too slow and too difficult to centrally manage and update. Oh and then there's the name "Notes" which for many still is a showstopper.

So what if IBM actually had a mail only client? What if they had a mail only client - think IBM Notes with only mail, calendaring, contacts and to-dos. Keep replication, require Windows Shared Login (i.e. SSO with the operating system) and I think it would be a winner. Extensibility would be nice for us ISV's but currently I would prefer customers to stay with IBM and having to use a web browser for applications.

If IBM had that they could actually still be a player in a market where many customers are moving to Office 365 but all complain about the cost and the performance. In many cases the IBM Connections Cloud is cheaper and WAY more performant as Office 365 is dog slow. All in all I still see IBM as a better play. If only they had a mail client...

Introduction to OAuth - the technology you need but never really learned

OAuth is core to integrations these days but I see many developers that try and use OAuth without really understanding the protocol. The protocol is very easy to understand so I created this presentation to try and explain it in easy, visual, chunks. I'll present on the topic tomorrow (Friday 6 November 2015) at the Social Connections IX conference in Stuttgart, Germany. I hope you'll come see it live if you are at the conference.