Wednesday, June 3, 2015

Visual Studio 2013 Bootstrap + Footable

Hi

VS 2013 comes pre-configured with Bootstrap 3.0 - which is super good for me as I am committed to making all my forms and pages mobile friendly from the beginning.

Today, for an application, I wanted to use the excellent footable plugin Footable plugin. After messing around with VS2013, I found this excellent article on Stackoverflow thats tells you exactly how to add a jquery or another plugin to your project.

Two steps

In bundleconfig.vb (or .cs as the case may be), add the following lines.

ScriptManager.ScriptResourceMapping.AddDefinition("footable", New ScriptResourceDefinition() With {
        .Path = "~/Scripts/footable.js",
        .DebugPath = "~/Scripts/footable.js"})


In Site.Master, reference the Definition "name" you added in the previous step

                <asp:ScriptReference Name="footable" />

In Bundle.config, reference the .css files

    <include path="~/Content/footable.core.css" />

The next step was to add all the footable plugins.  Clearly, I did not want to add a ScriptManager.ScriptResourceMapping.AddDefinitions directive/command/function call for all of them.  Here is what I did, instead

In BundleConfig.vb, I added the following function call

        bundles.Add(New ScriptBundle("~/bundles/Footable").Include(
                    "~/Scripts/footable.js",
                    "~/Scripts/footable.bookmarkable.js",
                    "~/Scripts/footable.filter.js",
                    "~/Scripts/footable.grid.js",
                    "~/Scripts/footable.memory.js",
                    "~/Scripts/footable.paginate.js",
                    "~/Scripts/footable.plugin.template.js",
                    "~/Scripts/footable.sort.js",
                    "~/Scripts/footable.striping.js"
                    ))

And I deleted the previous line from BundleConfig.vb - that I added previously

Then, in Site.Master, at the very top, I added the second line to the asp:PlaceHolder directive

    <asp:PlaceHolder runat="server">
        <%: Scripts.Render("~/bundles/modernizr") %>
        <%: Scripts.Render("~/bundles/Footable") %>
    </asp:PlaceHolder>

That is it.  You can add any jQuery plugin to your ASP.Net project this way and have all your project elements in standard places for VS 2013.

Cheers

Saturday, April 18, 2015

Dreamfactory + Oracle

Hello again

I have been struggling to get Oracle connectivity going from my Bitnami Ubuntu Dreamfactory image.

The instructions at http://blog.dreamfactory.com/how-to-access-your-oracle-database-from-dreamfactory did not work for me.

After following the instructions,

php -m

would not find .so files even though I had made the change in setenv.sh script file.

So, here is what I did to get php to load oci8.so without any errors.

As of Dreamfactory 1.9, you need the 11.1 Oracle client.
The file I downloaded was basic-11.1.0.70-linux-x86_64.zip.
I could not get the rpm file to work.  The conversion of rpm to a deb file using alien did not get the desired results - for apache to load the oci8 extension for PHP.  Did not work for me.

I downloaded the .zip file from Oracle, unzipped them into a temporary folder and moved all the .so files that apache would report as not found into /usr/lib.

Now, php -m command lists out all the modules it loaded.

Next step is to connect to an Oracle database.  Will update.

Cheers

Iyer

Saturday, April 11, 2015

Dreamfactory + Microsoft SQL Server

Hello again

I have spent many hours slaving over connecting Dreamfactory running on Ubuntu to MS SQL Server (or any Linux distribution).

For my own sanity and in the hope that it will help someone, here it is.

If you are using the Bitnami Ubuntu distribution, all you need to do is

sudo apt-get install  php5-sybase unixodbc

Once these and other dependent packages are installed, go into the DSP console, create a new service and use the following tips to access MS SQL Server from your DSP instance.

Name : <your name for the service>
Description : <your description>
Username : <your sql server user name - not tested with Windows Authentication - only SQL Auth>
Password : <your sql server password>

Specify SQL Server hostname and database name so that the "Connection String" ends up looking like this

dblib:host=<your SQL Server Hostname>:1433;dbname=<your database name>

I spent a couple of hours figuring out why DSP would connect to one SQL Server and not another.

Then, a quick telnet <sql server name>:1433 showed me that the Windows Firewall service was not allowing connections through.  Do remember to check that as well.

Cheers










Monday, March 30, 2015

C++ Builder & Dreamfactory - Get Started

Hello Again

I am rather pleased today.  I managed to replicate quickly, the process I had struggled to get right to access Dreamfactory from C++ Builder XE7.  This should apply with syntax corrections to Delhi as well.

I have always been very comfortable with (nee) Borland's development tools.  My affair with them goes back to Turbo C++ 2.0 (if I remember the version correctly).  My first "programme" was a programmer's editor using direct screen access in DOS - which was a big thing in our small community 25 years ago.

There are a number of example that show how to access common, open REST services from Delphi and a few that show how to do that from C++ Builder.

But I could not find any example that showed how Dreamfactory could be accessed from C++ Builder.  Here is a working example.  The objective of this example is to load a table of "City Master" into a ComboBox control.


Create a new form and add the following controls to it

Set 1

ComboBox
RESTClient
RESTRequest
RESTResponse


Set 2

RESTRequest
RESTResponse
RESTResponseDataSetAdapter
FDMemTable

Yes, you need to add TWO RESTRequest and TWO RESTResponse components to the same form.

Ignore the BindingsList1 and BindSourceDB1 for now.

At the end, you should have the following control in your form


  1. RESTClient1
  2. RESTRequest1
  3. RESTResponse1
  4. RESTRequest2
  5. RESTResponse2
  6. RESTResponseDataSetAdapter1
  7. FDMemTable1
  8. cbRequestLocation (this is the ComboBox control)


In the FormCreate event, paste the following code.  This part authenticates your application's session to Dreamfactory and returns a session_id value that we need to store to pass with subsequent calls.

RESTClient1->BaseURL = "http://del-your-dreamfactory-server-name/rest";
RESTRequest1->Method = rmPOST;
RESTRequest1->Resource = "user/session";
RESTRequest1->Params->AddItem("X-DreamFactory-Application-Name", "yourApplicationName", pkHTTPHEADER);
TJSONObject *o = new TJSONObject();
__try {
TJSONObject *o = new TJSONObject();
o->AddPair( new TJSONPair("email","yourUserName"));
o->AddPair( new TJSONPair("password","yourPassword")) ;
RESTRequest1->AddBody(o);
                RESTRequest1->Execute();
}
__finally {
o->Free();
}

When the RESTRequest->Execute() method finishes, it triggers an event. In this event, we extract the value of "session_id" from the JSON and use that to add another HTTP header field for session ID.  Every request to Dreamfactory requires these two HTTP headers to be set.  The first one is simple enough - we have seen that in the previous code example.  Here we add two HTTP headers to our next request - which gets the actual data from Dreamfactory.


  1. X-DreamFactory-Application-Name
  2. X-DreamFactory-Session-Token


void __fastcall TfrmMainMenu::RESTRequest1AfterExecute(TCustomRESTRequest *Sender)

{
String sSessionID;
        // RESTResponse1->JSONText contains the JSON string returned by the authentication above
        // RESTResponse1->JSONText has to be converted to a JSON Object before we can extract values from it
TJSONObject *JSON = (TJSONObject*)TJSONObject::ParseJSONValue(RESTResponse1->JSONText);
       // Get a JSON key/value pair from the JSON object
TJSONPair *pair = JSON->Get("session_id");
       // Get the JSON value part of the key session_id and store it in our variable
sSessionID = pair->Value();
       // The REST service to next consume.  Below, "mssql_utilities" is the Dreamfactory service
       // And car_location" is the table from which we are extracting information
       // We want all rows, so we are not using any condition or filter
RESTRequest2->Resource = "mssql_utilities/car_location";
        // Add the two HTTP headers that are mandatory for getting data from Dreamfactory
RESTRequest2->Params->AddItem("X-DreamFactory-Application-Name", "NDTVi", pkHTTPHEADER);
RESTRequest2->Params->AddItem("X-DreamFactory-Session-Token", sSessionID, pkHTTPHEADER);
        // Call the Dreamfactory server and get the data
RESTRequest2->Execute();

}


So far, so good.  After this, things get a little involved which is where I spent most of my time.

Hopefully, this will help you.

Select the FDMemTable1 object and in the Object Inspect click the ellipsis on the FieldDefs property.  See image below. The FieldDefs property is circled in red.


When you click on the ellipsis, you can add the columns that your REST call will return.  I like to keep the column name EXACTLY as they are returned by the REST call - which is normally the way they are defined in the database. If you work with SQL Server and with ADO.Net, you may not be used to worrying about the case of column names.  I would suggest you pay attention to this when working with C++ Builder and Dreamfactory.  Makes life easier.  

I have added two columns

Location ID : ftInteger
Location : ftString

Select the correct type from the Object Inspected for the FieldDefs dialog.  Always good to.



This is what the FieldDefs property editor looks like for one column



Now is the "visual" part.  I have not been able to figure out how to do this programatically, which is for some reason, my preferred method.

In the Object Inspector, select TResponseDataAdapter and set the Dataset property to FDMemTable1.  See the image below.



On the form, click the FDMemTable object and call up the LiveBindings designer.  The FDMemTable object shows up as BindSourceDB1 and you can see FDMemTable1 in the second row of this object.

Now, connect the following

1. * from BindSourceDB1 to Synch of cbRequestLocation
2. Location from BindSourceDB1 to Item.Text of cbRequestLocation




That's it.  Voila, run your application and the ComboBox will show the rows from the table.

Of course, you need to replace all user names, password, server names, Dreamfactory service names and tables names and column names with your own.

Subsequent articles will look at how to pass parameters to filter records and order and sort.

Cheers


Saturday, March 14, 2015

Folder Watcher In Linux & Windows

Folder Watcher Or Hot Folders

Linux First - CenOS 5 and 6.

How many times have you wanted to execute an action or run a script or an application when a file appears in a folder?

Called folder watchers or hot folders, these are very useful for batch jobs or jobs that run in serial.  When a file is uploaded to a folder, format that file in xxx fashion and deposit it into yyyy destination or any variation of that.

In Linux, I think it is called the inotify interace and a great implementation is of this is at http://inotify.aiken.cz/?section=common&page=home&lang=en

If you need to watch folders in Linux or other Unix variants, you must look at this.

We implemented a simple solution in our organisation to encode videos from one format to many others by using this.

It was a two step process.

Files would come into a folder over FTP.

Once they landed in the folder, the iNotify interface would run the a script that called ffmpeg to convert videos and would deposit the result into the respective folders - one folder per format - we had two different fomats in their separate format specific folders for the test.

We configured inotify for the destination (converted) video clip folders.  When the files converted by ffmpeg would get saved in the new folders, another event would get fired by the inotify interface and would run an command line FTP command to send the files to other servers.  The script would also make some entries in a MySql database that acted as an media management database for us.

We could easily drop more than 30 clips at a time and the event notification interface worked like a charm.

We tried with files of a few KB upto 300MBytes - everything worked like a dream.

Windows XP+

On Windows, there are many commercial products, but we chose to write our own folder watcher in VB.Net with the FileSystemWatcher class.

In Visual Studio, under the Windows section of the New Project Dialog box, you should find a Windows Service option. Select that, give your service a name and Visual Studio, helpfully, creates a skeleton where filling the blanks in is super easy.

OnStart

This Sub is called when the windows service starts - when you turn on the computer or restart the computer or service.

Here we register one folder to be "watched" by the operating system and then tell the service runtime which "sub"s to execute for two events - when a new file is created or when an existing file is updated.  In our case, both events require the same function to be called but you could have different "sub"s to be called.

    Protected Overrides Sub OnStart(ByVal args() As String)
        ' Add code here to start your service. This method should set things
        ' in motion so your service can do its work.
        Try
            watchfolder = New System.IO.FileSystemWatcher
            watchfolder.Path = getRegString("FolderToWatch")
            watchfolder.Filter = "*.htm"
            watchfolder.NotifyFilter = IO.NotifyFilters.DirectoryName
            watchfolder.NotifyFilter = watchfolder.NotifyFilter Or IO.NotifyFilters.FileName Or NotifyFilters.LastWrite
            watchfolder.NotifyFilter = watchfolder.NotifyFilter Or IO.NotifyFilters.Attributes
            AddHandler watchfolder.Changed, AddressOf weatherUpdate
            AddHandler watchfolder.Created, AddressOf weatherUpdate
            watchfolder.EnableRaisingEvents = True
        Catch ex As Exception
            WriteToEventLog("Could Not Start the service " & ex.Message, "Service1", EventLogEntryType.Error)
        End Try
    End Sub

OnStop

Magically, this is the Sub called when the service is stopped by you or the operating system.  Put any clean up code in here.

    Protected Overrides Sub OnStop()
        watchfolder.EnableRaisingEvents = False
        ' Add code here to perform any tear-down necessary to stop your service.
    End Sub

The Event Handler 

This is the "sub" that actually does the work - as registered with the AddHandler command in the OnStart Sub above.

    Private Sub weatherUpdate(ByVal source As Object, ByVal e As System.IO.FileSystemEventArgs)
         'Update a database
         'Convert the file
         'Send the file by FTP to someplace else
         'Send an e-mail
         'Or whatever else you want to do with the file
    End Sub

Hope this helps someone

Cheers

There Are Managers And There Are Managers - Are You The Latter?



In the movie Casino Royale, Vesper Lynd tells James Bond that "there are dinner jackets and there are jackets. THIS is the latter".  

This quick note is about the former - managers and not dinner jackets.  More boring than dinner jackets. But as common.

How to spot insecure managers…and some ways of dealing with them

Many of us have managers who are insecure about their position, their work, targets and their teams. Such managers can negatively impact the ability of teams to focus and deliver results that businesses need. They will go after top performers in their teams and try to subdue and depress their achievements. Such bosses have a few common characteristics. Here are a few tips on how to spot them.  

1. Micro manage

Managers who feel threatened and insecure tend to try to show who the boss is. Constantly questioning work done and milestones achieved is the only way they know to achieve a sense of control over their good performers. They lack the confidence to let their team members take decisions and be responsible and accountable.  

2. Keep out

When threatened, insecure managers will keep their good performers out of new projects or try to get them out of projects and work they are currently involved in. They will sideline good performers and undermine their work and authority among other team members.  

3. Hide achievements

Insecure bosses will try to hide performances of their top performers from theirs own managers. They try to project all achievements as their own and will downplay contribution of individual team members.  

4. Take credit

This is the probably single biggest common trait amongst managers who are threatened by their team members. They take undue credit for the work of their team and will project themselves as key contributors.  

5. Lack vision

Insecure managers typically lack a clear vision, will not set clear directions for their teams and will keep changing their minds on what projects to undertake and how to finish them. Their priorities will keep changing and their teams will be confused and overworked due to constantly changing directions. 

6. Routine

Managers who feel threatened will often take refuge in the comfort of the known. They will stick to routine work and not encourage their teams to try new avenues of learning and achievement. For many such managers, just enough is good enough. They lack the motivation to do more and do better. 

7. Career damaging

The worst managers will damage your career by limiting position and remuneration growth. They may even try to convince their managers to get rid of you. 

 8. Absence of meritocracy

Insecure managers tend to promote cronies instead of outstanding performers. They prefer to employ and work with non-performers or workers who are of a lesser intellect than themselves - if that was even possible. 

There are some simple ways to "manage" such managers on a daily and long term basis.  

1. Communicate

Communicate your progress clearly and calmly. Setup frequent and regular meetings with your manager and update him on the work you are doing. Highlight how that work benefits the company and the team which includes the manager. 

2. Speak up

Voice your concern. Do not be shy of telling your manager that you are unhappy with his approach or lack of it. 

3. Record

Keep clear records with timelines set and achieved, targets set and achieved, final outcomes and the benefits that have or will accrue. 

4. Escalate

In the worst case, take HR or senior management into confidence and update them with clear and concise data on how you have been sidelined and how your achievements have been kept from them. 

5. Data

Back up your claims with authentic records of project deliveries, client testimonials, genuine feedback from peers, co-workers and managers of other departments. 

6. Focus

Always stay focused on your work, maintain highest standard of quality and help your manager prioritize work with logical and business reasons to change priorities and deadlines. 

7. Value

Estimate value to business of work being done in the team and highlight the most impactful work that the team can do to ensure maximum business benefit. 

8. Clarity

Ask for clear directions. If your work involves research or trying out new ways of solving problems, ask your manager for clarity on expected outcomes. This will give you a broad field to work on towards the expected results. Try to see the big picture and use your work to contribute to the big picture. 

9. Stay Positive

Stay positive and calm throughout your interaction with your manager. Take notes of what was spoken and decided and record them in a formal communication for future action and reference. Keep happy.

10. Separate

In the extreme case, consider if going to HR or your manager's superior with a request for separation of you or your team from your manager.  If your work is distinct enough from the rest of the team that reports to your manager, you may be able to make a case for such separation. This is a slightly more direct and stronger version of point four.

Cheers

The True Spirit Of A Tragedy


I have seen two riots in my life.  I was very young when the anti-Sikh riots happened in Delhi in the wake of Indira Gandhi’s killing in 1984.  Mumbai in 1992 after the Babri Masjid was brought down was the second.  In those early years of my life, the only source of information, news and rhetoric was the morning newspaper and the state-controlled television with its once a day news bulletin.  We knew what we saw. In 1992, that changed as we watched the BBC on cable television.  NDTV’s 24 hour news channel would not make its debut for another 6 years.
 
To believe what we heard and saw on television or on the Internet was an alien concept. Besieged as we are now by television channels, web sites, radio and the morning, afternoon and evening newspapers, we truly get instant gratification of our need to be fed news of events as they unfold and as they happen.  We cannot wait for the morning newspaper.  That’s the next morning, for God’s sake!
 
But what is the news we are being fed?  We are told how the blasts happened over and over again.  We are kept updated on how many people died and how many were injured.  We are told every time that the official figures are way under the actual as many cases of death and injury are unreported. Every detail of where and when and all the theories expounded by a seemingly clueless government and police are repeated ad nauseam.  What kind of a need in us does it fill to know how many died or how many injured?  How does a higher death or injured count make a tragedy better or worse?
 
In the past few years, we have seen the explosion of the Internet as a communication medium.  We have celebrities posting their OMGs on various web sites.  And all of us go “Wow!  How nice” and “What a good person”.  Is posting on a website reflective of the spirit of a city?  Or is not posting on a site reflective of the lack of spirit or the presence of a negative spirit?
 
While it is important to make your thoughts felt and your voice heard, how many of them actually went out and helped someone?  Did I go to Mumbai and help anyone?  I did not.  Did I post on a web site on what a great tragedy it was?  I did not.  Does that make me a lesser mortal or even an un-spirited one?  I don’t know.  I am just not connected.  Just as I did not connect to the two riots because I was not affected. 
 
I got on with my life the same day or the next day.  I had to.  I had to get to work or to school.  Like me, millions of people in Mumbai just have to get to work.  They do not have a choice.  Do we expect them to stay at home?  Thousands of daily wage workers have no option but to get to work.  Their evening meal depends on their working every day.  
 
In the two tragedies I was close to, I saw people helping others selflessly, without any consideration for their own safety or for the cost, their effort, their time that the assistance took.
 
These are the people who make or break the spirit of a city.   These people are everywhere.  They were as much in Delhi in 1984 as in Mumbai in 1992 and later. They are present all over the world.
 
The spirit of the city is not one that shows up on twitter or facebook.  The spirit of the city is not that the people have got on with their lives.    The spirit of the city is not a few celebrities posting on web sites.  The spirit of a city is not those celebrities condemning the tragedy on national television or holding candlelight vigils.
 
The spirit of the city is in that taxi driver who drove an injured and dying person to hospital without charging and probably saved his life or at least his dignity after death.  The spirit of the city is reflected in  those few who picked up the injured and took them to the nearest vehicle, building, hospital, shelter and did not care about soiling their clothes.   The spirit of the city is in the police men, firemen, the general public who helped the affected pick up the pieces.
 
The spirit of the city is in what you do for the city and the people who make up the city. Not in the noises you make.

Cheers