Stephen Smith's Blog

Musings on Machine Learning…

Archive for January 2013

Colorful Companies in Sage 300 ERP

with 7 comments

Introduction

We released Sage 300 ERP 2012 back in September, 2012 and now are preparing to release our Product Update 1. This PU1 will have a number of bug fixes along with a number of new features. In this blog article I’m going to explore one of the new features that allows you to choose the color of the title bar and border on your Sage 300 Windows by company.

Many of our users have data stored in multiple Sage 300 databases. Often they are comparing this data or copying it from one company to the other. Often they end up with several desktops open along with many screens. The company name is always part of the title bar, but this is quite subtle and it’s easy to do tasks in the wrong company as a result. This feature makes it more obvious which window belongs to which company with a stronger visual indicator, namely the color of the title bar and window boarder.

Configuration

You configure the color of the company using Database Setup. The list of companies now includes a column for the company’s color. There is an option you can click to automatically assign colors to all your companies. Or you can clear all the colors and go back to no colors.

dbsetup1

If you want to select each companies color yourself then you do this by editing the individual company.

dbsetup2

Note that when a color is chosen we take over drawing the title bar and window border to draw the color. If you want the natural Window look then don’t select a color and we won’t touch the title bar or border allowing Windows to do its default drawing.

Operation

Once configured you will get Desktops and screens looking like:

colordesktop1

Notice that even the little preview windows when you hover over the taskbar icons show the colors.

Development Notes

Windows doesn’t provide any easy API for coloring the title bar or border of a Window. This area is referred to as the non-client area and the best it gives you is a hook to take over painting the entire area. This means you have to also paint the buttons for minimize, maximize and close as well as the system menu and draw the various states of these. Plus you have to then draw the title text and handle whether to use white or black depending on the color selected.

If you’ve ever run the Chrome or Firefox browsers, you may have noticed that they support themes which among other things take over the drawing of the non-client area. The neat thing then is that since these are open source projects, you can download their source code and see how they do it. The main thing for us was that we got confirmation that there wasn’t an easier way to do it and that what we were doing was a reasonable approach.

For this exercise we wanted to get the right balance of visual difference to not causing too jarring a change. We considered changing things like the form background, but in our opinion this was too drastic and didn’t work well with all color combinations. This approach also doesn’t interfere with the various Windows accessibility options so you can still use high contrast modes and such.

The way we implemented the change was to put the code into the regular desktop, as well as the a4wcontainer. The a4wcontainer acts as a COM host to host our screen ActiveX controls. Each accounting screen is written in Visual Basic and compiled as an ActiveX control. This way it can be embedded in other programs and customized via the API it exposes. But when running normally, when the desktop is asked to run a VB form, it launches a4wcontainer and that then acts as a COM container for hosting the ActiveX control. It is actually the COM container that is responsible for drawing the non-client area, so all we had to do is add the drawing code here to then affect all VB screens.

At this point frequent screen customizers might object. Unless you are an SDK application you won’t get this treatment. If you have embedded a screen in another programming system (say VB) and are distributing it as an EXE then you are the COM container and won’t get the benefit of this treatment. Similarly if you run from VBA, we have no control of drawing the VBA non-client area so again you won’t get this treatment. But our feeling was that the current implementation should handle most of the need and a few exceptions was ok.

Summary

Our first Product Update for Sage 300 ERP 2012 should be out shortly and this article gives a quick overview of one of the usability features that has been added. Hopefully people find this useful and it will help them perform their work more accurately.

Written by smist08

January 26, 2013 at 6:36 pm

Linux is Everywhere

with 4 comments

Introduction

It’s been a long running joke that at the beginning of each year, probably for the last twenty years, someone prognosticates that this will be the year of Linux. Often this is prefaced by the year of the Linux desktop or the year of the Linux server. But somehow in spite of all the hype, most desktops are still Windows as are a good number of servers.

I don’t really want to prognosticate that this will necessarily be the year of anything in particular, but recently it appears that everywhere I turn, I see Linux.

Telikin

My wife spent November and December in Arizona with her parents who are snowbirds, since I had quite a bit of business travel going on. Since she was there for 2 months she was determined to get her parents on-line. So they could Google things themselves rather than phoning her, so they could e-mail and use Facebook. So off they went and bought a shiny new Lenovo Windows 8 laptop with a touch screen and all the bells and whistles. This turned out to be quite frustrating and they had all sorts of learning and usage problems. The big one being that the touch interface didn’t work well. So they returned it and got a large screen Windows 7 laptop, which my wife thought would be easier since she knew it better and there was no touch stuff. Didn’t go so well. Then they saw an ad for a Telikin PC which was a special purpose PC for seniors with a touch screen as well as a mouse, with special easy to use software which included senior friendly features like large fonts and large graphics.

Telikin-TLMS18T3202W-PC

This actually worked out quite well. They could do e-mails, browse the web, print, upload photos from their camera and use Facebook. They then asked me about recording audio, so I got a freeware program and went to install it. I imagined that the senior friendly software was just a shell over Windows, and I just needed to figure out how to exit that or run a CMD prompt. No luck. I then Googled the computer and to my surprise found out it was powered by Linux! Apparently Linux is making it into the Desktop in a number of special purpose PCs. I then had to point them to a web site that allowed you to make audio recordings and away they went. Further they seem to be able to keep using it now that they are on their own again, since we returned home.

Android

Of course I couldn’t write an article about Linux taking over without mentioning Google’s Android operating system for phones and tablets. Last September, Google announced that 500 million Android devices have now been activated. That’s an amazing number. Basically Android is proving to be the market leader in both smart phones and tablets. Samsung has experienced tremendous growth with their Android devices.

ChromeOS

For laptops, Google is promoting their ChromeOS which is a minimal Linux based computer that is more oriented being a web browser. Surprisingly ChromeOS based laptops have topped the Amazon best seller lists for laptops in recent months. These are special purpose devices, but are gaining quite a bit of traction.

Tizen

Tizen is another open source Linux based smart phone operating system. This is being promoted as even more open than Android. It is being picked up by several Chinese phone manufacturers as well Samsung has announced they will be releasing Tizen based phones. Partly this is in reaction to Google shipping Google branded devices in competition to their hardware partners.

Ubuntu

Ubuntu has been a leading Linux distribution that has gained quite a bit of traction on the desktop. It is a full distribution of Linux and not one of the special purpose limited sets. Now Ubuntu is developing a smart phone version of their Linux version. The idea is that when the phone is mobile it runs a limited set of programs in a manner similar to Android or Tizen, but when you dock the phone and it’s connected to a monitor, keyboard and mouse, then you get the full Ubuntu distribution. This way your phone is also your laptop and tablet.

This is rather an interesting idea that the phone is your computing core with all your files and programs on it. Then depending on the hardware, connectivity and power you get the subset that is appropriate for that usage.

Raspberry Pi

The Raspberry Pi is a $25 computer that is oriented to hobbyists. It is based on the ARM CPU and runs Linux. The Raspberry Pi doesn’t even come in a box. But since it just recently went on sale, it’s already sold 1 million units. This has certainly woken up the home hardware hobby industry and I suspect the core design of this will end up in many other devices.

800px-RaspberryPi

Everything Else

At the recent CES show, there seemed to be a plethora of special purpose Linux based appliances from intelligent fridges to Linux being the operating system for your car. I don’t know how many of these will be successful but it appears that nearly everything is getting a CPU, memory and connectivity. Whether these have any lasting value or are short term gimmicks is yet to be seen.

Programming

As a programmer we want all our programs to run in as many places as possible. These days the market has become quite fragmented between Windows, MacOS, iOS and then all the Linuxes. One way to program for all these devices is to use HTML5/JavaScript since they all have Internet connectivity and good browsers like Firefox or Chrome. Another way is to use Java which runs on all these as well. For Windows, Linux and MacOS you can also use C/C++ and just isolate the operating system dependent parts in separate modules to handle differences in things like mutexes and file locking. Unfortunately besides using HTML5/JavaScript the preferred native way to create User Interfaces is completely different on all of these and tends to lead to very different ways of doing things.

Summary

It seems that Linux has been making inroads slowly in all sorts of places. Now all of a sudden it seems to be everywhere. I think this is a great tribute to what can be accomplished with open source software and how a great many profitable ventures can be based on it.

Written by smist08

January 19, 2013 at 5:55 pm

Azure and PaaS Versus IaaS

with 9 comments

Introduction

Sage 300 ERP has had a cloud version for over ten years now with Sage 300 Online. I blogged a bit about how this offering works here. Basically we offer our on-premise product in the cloud relying on Citrix and Terminal Services technologies to host and allow access. You are basically running your on-premise Windows desktop ERP application in the cloud. The only thing required on the local computer to access the software is the Citrix client component which is available for Window, Mac, iPad, etc. We are currently hosting this in Sage’s Atlanta data center.

We are now looking to produce the next generation of this cloud offering and we are looking to host it in Microsoft Azure rather than our own data center. There are quite a lot of reasons for this, like being able to deploy globally to various Azure datacenters or to take advantage of the Microsoft network which provides quite low latency access to these data centers. But the Azure feature we are going to explore in this blog posting is what does Azure PaaS give us over an IaaS offering? What are the differences and what are the considerations?

IaaS

IaaS stands for Infrastructure as a Service. In this model the provider, typically someone like AWS or Rackspace, provides all the hardware, storage and networking equipment. Then they give you the ability to create virtual machines in this environment (often providing some starting templates of typical servers). It is then up to you to install everything you need to run on these virtual machines and to maintain them fully going forwards, ensuring all patches are installed, upgrading to new versions of the operating system, etc. If you need a database server then it’s up to you to buy and install that database server on one of your virtual machines and it is up to you to maintain this server, back it up, provide geographic redundancy and anything else that is required to keep the data safe.

PaaS

PaaS stands for Platform as a Service. The goal of PaaS is to build on IaaS to have the vendor also take care of maintaining the operating system and the database server. So you don’t need to worry about patches, backing things up and various other chores. Microsoft Azure is an example of a PaaS offering (although they are getting into offering IaaS as well). Below is a diagram showing how the layers are often separated. This also gives the vendor the opportunity to provide more advanced monitoring and management tools for the platforms they are supporting.

Cloud_computing_layers

Complexities of PaaS

That all sounds good but how do you separate out the maintenance of the operating system from the maintenance of the application? Generally the way this is done is that whenever you start a VM you start with a fresh copy of the operating system which is then guaranteed to be at the most recent patch level. In the IaaS model you start with the operating system template once, then everything that happens to that image is stored to disk and if the image is stopped and started you continue from where you left off. In the PaaS model if your image is stopped and started, then it is restarted with a fresh image of the operating system and you need to install all your software before it can start processing.

This is why most PaaS systems tend to be very specialized in the type of applications they can run. Azure is built around running ASP.Net applications. Microsoft provides support in Azure and .Net to easily deploy your ASP.Net application to a new operating system image as it starts up. Similarly Ruby on Rails PaaS vendors provide support for installing the Rails application on their new image as it starts.

But doesn’t that mean you have to transfer huge amounts of files to the environment every time a VM starts? Well actually no. Azure provides a number of non-VM storage mechanisms for storing files in the environment. So for instance you can use blob storage or one of the other storage mechanisms to hold all your files and data. Then the scripts that start the VM would just attach these to the VM when it starts, or your program knows how to use the Azure SDK to connect to these when it runs.

PaaS databases are bit easier, since you just create and access your SQL Server databases in Azure SQL just like you would in a regular SQL Server, you just need to know the right information for the connection string to the Azure SQL server. But there are still issues to be aware of. For instance when you create your own set of VMs to make a production system, you can specify them in a VM group and ensure they all run in the same area of the Azure data center. This then ensures any latency of communication between these VMs is very low. But when you switch to the PaaS database server, all the servers that comprise, say Azure SQL all run together in another area of the data center and the latency from your server group to this server group is a bit higher than communications within your own group. Further you are then sharing these servers with other unrelated applications using these servers, so you are relying on the vendor to provide sufficient processing power to keep everything performant. But the best thing about PaaS databases is that you don’t need to worry about tuning the server or backing up all the data.

azure1

Moving Sage 300 ERP to PaaS

But Sage 300 ERP is not an ASP.Net application. So how can we even run in this environment? Fortunately, Microsoft provides both IaaS and PaaS services in the Azure environment. This means we can move our current Sage 300 ERP cloud implementation from our Atlanta datacenter to Azure by using the Azure IaaS infrastructure. We can then start to take advantage of various PaaS services one by one.

The whole Azure infrastructure provides a very rich API which allows you to use PowerShell scripts to control what is going on. Hence the ASP.Net support is really a set of scripts developed to handle typical deployments that is built into the Azure/Visual Studio SDK. From Sage 300 ERP we are developing similar scripts to create and control a Sage 300 ERP deployment. This way we can incorporate PaaS building block into our system. So we can have scripts to start and configure the whole system, scripts to add applications servers and so forth. We can even integrate these into standard DevOps tools such as RightScale or Chef.

Leveraging Azure SQL is perhaps a bit easier since you can use the same access technology we currently use. We have to add a bit of code to our database driver to handle some cases that can happen in the Azure environment but generally using Azure SQL is very similar to using regular SQL.

The system that makes up Sage 300 ERP cloud consists of quite a few VMs all performing various tasks. Switching some of these to PaaS based servers is very straight forward, so we can do this right away. For our application servers that have full Sage 300 ERP installed, we will continue to maintain these as IaaS for the foreseeable future since right now the overhead in installing full Sage 300 ERP is a bit high. But there are features coming in the Azure roadmap which will over time let us migrate these to PaaS as well. To some degree PaaS is still in its early stages and new services are regularly being rolled out and we can take advantage of these new services as they appear.

In our Atlanta data center we operate Sage 300 Cloud on a fixed set of servers that we purchased and as the usage grows we buy another server now and again. With a managed service like Azure we are paying for our infrastructure on a usage basis. However the system is elastic, meaning that we only need to run as many application servers as we need to handle the current load. So if usage is low during the weekend then we can shut down some application servers and save some money. Similarly if we get a big spike in usage we can easily add as many application servers as we need instantly to handle the load (perhaps at year end). Again basically we control all of this with a number of PowerShell Scripts.

Summary

Microsoft Azure is a very rich cloud environment. It provides us with a lot of benefits to help us beef up our Sage 300 ERP Cloud offering. But with the richness, there is quite a bit of work creating scripts to take advantage of it, tuning our application for this environment, as well as a learning curve learning the best ways to leverage all these new PaaS features.

Written by smist08

January 13, 2013 at 12:59 am

The Sage 300 ERP Java API

with 13 comments

Introduction

With version 6.0A of Sage 300 ERP we introduced a native Java API to all the Sage 300 Business Logic (Views). We did this in support of our SData implementation which we wrote in Java. This API allows Java programmers to access all the Sage 300 ERP business logic along the same lines as our .Net API and our COM API. This API isn’t built on top of either COM or .Net, it talks directly to the underlying C DLLs in System Manager. This then provides better performance, as well as allows us to compile this part of the system for Linux with no Microsoft dependencies. Internally we usually refer to this API as SAJava.

All the Sage 300 Business Logic objects have the same API, this makes it easier for us to produce these different APIs to facilitate interoperability with all sorts of external systems, allowing the programmers there to write code in a natural manner where any required interop layer is provided by us. The Java API uses a Java Native Interface (JNI) interop layer to talk to our Windows DLLs (or Linux shared objects). This is a one way communication where we only use this to call the DLLs, we never have the DLLs calling our Java code (this direction is often dangerous and leads to the problems often encountered with JNI). Our JNI code handles all the data conversions between Java and C as well as provides exception handling to trap and handle exceptions that can happen in C code (like bad pointers).

I’ve blogged about this API a bit indirectly in the past when talking about how to write server side code for our SData service, for instance here, here and here. Generally to add custom programming to SData feeds you write Java classes that inherit from our standard SData classes to provide this. When you interact with the Views in this environment you use this Java API, but all the libraries are already included and all the details of signing on are handled for you. The framework starts you off at a point where you can directly open and call Views. In this posting we’ll back up a bit to cover full usage, unlike the case where the SData programming framework does a lot of the work for you. So that you can use this API directly in isolation without requiring any other framework.

Getting Started

First to use the Java API, you need to include its jar file into your project. This file is located in the Tomcat\lib folder. This changed a bit between version 6.0A and then the 2012 version. For 6.0A the folder is: C:\Program Files (x86)\Common Files\Sage\Sage ERP Accpac\Tomcat\lib and the file is SystemManager.jar. For the 2012 version the folder is: C:\Program Files (x86)\Common Files\Sage\Sage 300 ERP\Tomcat\lib and the file is com.sage.accpac.sdk.accpac.sajava-6.1.jar. Then you need to import the classes into any source file that uses them via:

import com.sage.accpac.sm.*;

Once you have these things included in your Java project you can start creating objects and calling methods. However due to security you first must sign-on to a session and then create all other objects from this session.

The documentation is in the form of JavaDoc and is located on the DPP Wiki. The 2012 version is here: http://dppwiki.sage300erp.com//javadocs/v6.1/SystemManager/. You can find all the classes, methods and properties here. To access this, you must be part of the Sage 300 ERP Developer Program. A key benefit to joining this program is access to this wiki which contains all the developer documentation that we produce.

Signing On

First you must create a session with some code like:

Session session;
session = new Session(new ProgramSet(), new SharedDataSet(), "ADMIN",
     "ADMIN", "SAMINC", new Date());

This will sign-on your session to the company SAMINC using today’s date as the session date. The ProgramSet and SharedDataSet are used when we deploy in a hosted configuration and run multi-tenant. In this case they must be setup correctly by the system to configure which tenant this session is for. In most normal on-premise applications the indicated calls are fine to give the one default tenant that exists.

Then you must create a program from the session:

Program program;
program = new Program(session, "XZ", "XZ0001", "61A");

If you read my last blog post, this might appear a bit backwards to the COM API where this looks like the session.Init call that comes first. This is true, but the information is required regardless.

Using Views

Now that you have a program you can start opening and using Views. As an example, let’s look at a method that enters A/R Invoices. Like many things I started with macro recording to get the right Views and some syntax. Macro recording produces VBA code, but it isn’t hard to convert this to Java quickly. Anyone familiar with Sage 300 ERP macro recording will recognize the style and variable names in the following method. This method assumes there are class variables for the program and session that were created as indicated above. The key point of the following example is to show how to open Views, compose Views and then use the Views. For more general information on Sage 300 ERP’s Views have a look at this and this.

    public String enterARInvoices()

    {

        int iEntry;
        int iDetail;
        int numEntries = 20;
        int numDetails = 5;
        String sBatchNum;

        View ARINVOICE1batch = new View(program, "AR0031");
        View ARINVOICE1header = new View(program, "AR0032");
        View ARINVOICE1detail1 = new View(program, "AR0033");
        View ARINVOICE1detail2 = new View(program, "AR0034");
        View ARINVOICE1detail3 = new View(program, "AR0402");
        View ARINVOICE1detail4 = new View(program, "AR0401");
        View ARCUSTOMER1header = new View(program, "AR0024");

        ARINVOICE1batch.compose ( ARINVOICE1header );
        ARINVOICE1header.compose (ARINVOICE1batch, ARINVOICE1detail1, ARINVOICE1detail2, ARINVOICE1detail3, null);
        ARINVOICE1detail1.compose (ARINVOICE1header, ARINVOICE1batch, ARINVOICE1detail4);
        ARINVOICE1detail2.compose (ARINVOICE1header);
        ARINVOICE1detail3.compose (ARINVOICE1header);
        ARINVOICE1detail4.compose (ARINVOICE1detail1);

        // Create the batch

        ARINVOICE1batch.recordGenerate(RecordGenerateMode.Insert);
        ARINVOICE1batch.set("PROCESSCMD","1");      // Process Command

        ARINVOICE1batch.process();
        ARINVOICE1batch.read(false);

        sBatchNum = ARINVOICE1batch.get("CNTBTCH").toString();

        // Loop through creating the entries

        for ( iEntry = 0; iEntry < numEntries; iEntry++ )
        {
            try
            {
                ARINVOICE1detail1.cancel();
                ARINVOICE1detail2.cancel();
                ARINVOICE1header.recordGenerate(RecordGenerateMode.DelayKey);
                ARINVOICE1detail1.recordClear();
                ARINVOICE1detail2.recordClear();

                ARINVOICE1header.set("PROCESSCMD","4");

                ARINVOICE1header.process();

                if ( false == ARCUSTOMER1header.goNext() )
                {
                    ARCUSTOMER1header.goTop();
                }

                ARINVOICE1header.set("IDCUST", "1200");

                for ( iDetail = 0; iDetail < numDetails; iDetail++ )
                {
                    ARINVOICE1detail1.recordClear();
                    ARINVOICE1detail1.recordGenerate (RecordGenerateMode.NoInsert);
                    ARINVOICE1detail1.process();

                    ARINVOICE1detail1.set("IDITEM", "CA-78" );                     // Item Number

                    ARINVOICE1detail1.insert();

                }

                ARINVOICE1header.insert();
            }
            catch( Exception e )
            {
                int count = program.getErrors().getCount();
                if ( 0 == count )
                {
                    e.printStackTrace();                   
                }
                for ( int i = 0; i < count; i++ )
                {
                    System.out.println(program.getErrors().get(i).getMessage());
                }
            }
        }
        ARINVOICE1batch.dispose();
        ARINVOICE1header.dispose();
        ARINVOICE1detail1.dispose();
        ARINVOICE1detail2.dispose();
        ARINVOICE1detail3.dispose();
        ARINVOICE1detail4.dispose();
        ARCUSTOMER1header.dispose();

        return( sBatchNum );
    }

Notice that you can explicitly close things by calling the dispose method. This is usually preferred to waiting for the Java garbage collector to reclaim things, it tends to keep down resource usage if you are opening and closing things a lot.

Errors

If a call fails, there are a couple of cases. If it’s a simple expected thing like reaching the end of records when fetching through them then the routine will return a simple return code that you can easily handle in your code. If something worse happens then the routine will throw an exception. As in other Sage 300 ERP APIs, there is an error stack which will contain possibly a number of error messages explaining what went wrong. In the catch expression above we first check if there are any errors on the error stack, if not then we print the stack trace to allow debugging of what went wrong. Otherwise we loop through the Sage 300 errors and print them for diagnostic purposes. When programming Sage 300 ERP, always make sure you have an error handler as it can give you very good information when debugging your program.

Summary

The Sage 300 ERP Java API gives yet another tool for integrators to integrate to Sage 300 ERP from external systems. It is ideal for Java programmers who would like to write their integration entirely in Java. This is often a benefit when the SDK for the external system is itself written around the Java programming language.