Stephen Smith's Blog

Musings on Machine Learning…

Posts Tagged ‘REST

Defining SData Feeds for Sage 300 ERP

with 8 comments

Introduction

We introduced SData support with Sage ERP Accpac 6.0A; however, the product as it shipped only defined a few SData feeds that it needed to support the new Web Portal, Data Snapshots, Inquiry Tool and Quotes to Orders features. But Sage 300’s support for SData is based on converting SData Web Service requests into View calls. So it is possible to expose any View (or collection of composed Views) as an SData feed.

In a future version of Sage 300 ERP we will expose all the relevant Views via SData, but in the meantime if you want to use SData with Sage 300, then you need to provide XML files to define the feeds you need.

All the feed definitions are XML files, which means you can read all the existing ones that come with Sage 300 using a normal text editor. Hence you can use the existing ones either as examples or templates for the definitions you need.

One thing to be careful of is that most of the fields in these XML files are case sensitive. This means they must match exactly or they won’t work. When things don’t work, it’s worth looking in the Tomcat\log folder at the relevant SDataServlet.log as this will often point out errors when parsing the XML files.

Class Map Files

The classmap files are a series of XML files located in the sub-folders under: C:\Program Files (x86)\Common Files\Sage\Sage Accpac\Tomcat6\portal\sageERP. The feeds for a given application are stored under the application’s program id and version id directory such as oe60a. Note that these need to be in a folder for an activated application to be read, but within an application you can define feeds that access Views in any application.

All the configuration XML files are loaded into memory by the SDataServlet on startup. So if make any changes to these files, you need to restart the “Sage Accpac Tomcat6” service for your changes to take effect.

You can use these to define custom Java classes to process the SData requests, I’ve covered this a bit in other blog postings, but won’t go into that here, since this article is only considering what can be done by editing XML files.

The classmap defines each SData feed and specifies the class to handle the feed and then a detailed feed definition file called a resourceMap file.

Example – Currency Codes

The currencyCodes resource is implemented by the Java class: ViewResourceKind and is defined by the resource map file: currencyCodeViewMapping.xml. ViewResourceKind is a system provided Java Class for generically converting SData requests into View calls. You can use this to expose most Views (that have data) as SData feeds.

Classmap.xml

<classmap>
<contracts>
<contract name=”accpac”>
<resource name=”currencyCodes” className=”com.sage.orion.sdata.servlet.accpac.ViewResourceKind>
<parameters>
<parameter name=”ResourceMapFile“ value=”currencyCodeViewMapping.xml”/>
</parameters>
</resource>
</contract/>
</contracts>
</classmap>

If you aren’t programming server classes then this is all you need to know about the classmap files.

Resource Map File

Maps an SData resource to a backing family of Accpac Views and fields. These are stored in the resourceMap folder under the folder that holds the classmap file.

By default all fields from the view are exposed as SData Resource Elements.

Has the ability to exclude or include or overwrite Sage 300 fields from the SData resource.

Example – Currency Codes

The currencyCodeViewMapping.xml resource map file contains the following:

<resource name=”currencycode” description=”Currency Codes”>
<viewID>CS0003</viewID>
<pluralName>currencycodes</pluralName>

<includedFields>
<resourceViewField viewFieldName=”CURID” />
<resourceViewField viewFieldName=”CURNAME” name=”Description”/>
<resourceViewField viewFieldName=”DECIMALS” />
<resourceViewField viewFieldName=”SYMBOLPOS” />
<resourceViewField viewFieldName=”THOUSSEP” />
<resourceViewField viewFieldName=”DECSEP” />
<resourceViewField viewFieldName=”NEGDISP” />
<resourceViewField viewFieldName=”SYMBOL” />
</includedFields>
</resource>

The key points are the viewID that maps this feed to the currency codes view CS0003. The URI of the feed is the plural name, namely currencyCodes. Then you can specify the list of fields you want included in the feed. You might specify a shorter list of fields to keep the size of the feed to a minimum. The includedFields section is optional.  I tend to prefer using an excludedFields section to just list the fields I don’t want.

Example – Single Level Resource

SData resource “customer” is defined from the view AR0024.

<resource name=”customer” description=”AR Customers”>
<viewID>AR0024</viewID>
<pluralName>customers</pluralName>
</resource>

Example –  Multi-Level Resource

SData resource ‘arInvoiceBatch’ is defined from a set of composed views – AR0031, AR0032, AR0033, AR0041 and AR0034.

<resource name=”arInvoiceBatch” description=”AR Batches”>
<viewID>AR0031</viewID>
<pluralName>arInvoiceBatches</pluralName>
<resources>
<resource name=”invoice” description=”AR Invoice”>
<kind>arInvoice</kind>
<viewID>AR0032</viewID>
<resources>
<resource name=”detail” description=”AR Invoice Details”>
<kind>arInvoiceDetail</kind>
<viewID>AR0033</viewID>
<resources>
<resource name=”optional” description=”AR Invoice Detail Optional Fields”>
<kind>arInvoiceDetailOptional</kind>
<viewID>AR0401</viewID>
</resource>
</resources>
</resource>
<resource name=”schedule” description=”AR Invoice Payment Schedules”>
<kind>arInvoiceSchedule</kind>
<viewID>AR0034</viewID>
</resource>
</resources>
</resource>
</resources>
</resource>

Resource Map File Details

Resource Mapping File Attributes / Elements:

name: name of the resource

description: description of the resource.

viewID: The ViewID of the resource. Remember you can get further information on the Views from the Sage 300 ERP Application Object Model (AOM).

pluralName: plural name of the resource.  If undefined then the pluralName = name +”s”.  This will be the URI of the resource.

resources: Collection of sub-resource elements

kind: resource kind name of the resource. Top resource of the resource tree the resource name and the resource kind name should be the same. However for a sub-resource the resource name reflects the name of the property that refers to it in the parent while the kind name is the name that it appears as at the top level of the schema.

includedFields: list of resourceViewFields that are to be included in the resource (by default all fields are included)

excludedFields: list of resourceViewFields that are not to be included in the resource

overridenFields: list of resourceViewFields that are to be overriden in the resource (usually done to change the SData name)

virtualFields: list of resourceViewFields that are to be added to the resource. Note: virtual fields requires extending ViewResourceKind with a custom class that implements these virtual fields.

lookupFields: These are a 6.1A feature that allow you to add fields looked up from another view like to get a description.

Summary

Hopefully this article gives an idea of how to setup additional SData feeds for Sage 300 ERP, without requiring any programming.

Advertisements

Written by smist08

March 3, 2012 at 11:57 pm

Writing Server Side Code for Accpac 6 Web UIs

with 11 comments

We discussed how to create Accpac 6 Web based UIs in https://smist08.wordpress.com/2010/08/14/creating-a-web-form-for-accpac-6/ and how to write code that runs as JavaScript in the Browser in https://smist08.wordpress.com/2010/08/21/client-logic-for-an-accpac-6-web-form/. This blog posting looks at how you can write server side code in Java to assist your UIs do their job more efficiently.

Accpac 6 Web UIs communicate with the Server using SData (https://smist08.wordpress.com/2009/11/24/sdata-in-sage-erp-accpac-6/ and http://sdata.sage.com/) which is a REST based Web Services protocol. On the Server we run a Java application that converts incoming SData requests into Accpac View calls. Accpac Views are the business logic objects within Accpac. The Accpac business logic is remaining largely unchanged in this new environment and it’s the job of this Java application to convert the new world into the older world.

Theoretically then, you could do much of what we are talking about directly in the Views. We could expose new calculated fields or new functionality directly from the Views. However Views are used by all sorts of things including VB based UIs, macros, import/export as well as by third party applications. We don’t want to clutter up the Views with lots of extra logic needed to support or optimize the new Web based UIs. What we are looking to do is split the code that used to run entirely in VB UIs to half run in the browser and half run on the server. We also want to provide support for our Web based UIs to minimize program size running in the Browser and to minimize the number of RPC (remote procedure calls) they need to make to the server. The current VB UIs call many Views at once to do what they need, but this won’t work so well over the Internet since it will require many SData calls to do things, we really want to consolidate all the info the UI requires in one feed, so it only needs to do one SData call to get everything it needs.

Within the SData server’s configuration are a number of XML files that define all the SData feeds for the various accounting applications. For each application there is a classmap.xml file that lists all the feeds and the Java class that processes that feed. Then for each feed there is a specific resourcemap.xml file that defines various properties or configurations for that feed such as which Views is sits on, or some extra fields to present. To add an SData feed on top of an existing View is easy and just a matter of creating these simple XML files. There is a generic class ViewResourceKind that will provide standard SData functionality for any View. But if you want to add your own functionality you need to extend one of our classes and add your own logic.

The hardest way to implement an SData service is to create a class that implements our SDataResourceKind interface. This interface defines what a class needs to implement in order to be used as an SData feed from our SData application server. Here you need to do all the work, but if you want to implement a feed that hasn’t got anything to do with normal Accpac processing, perhaps this is a way to go. Fortunately we provide a class that implements this interface that you can extend. This is the ViewResourceKind class, mentioned previously, that implements SData on top of a View. This is really intended for data type Views. You can extend this to add fields and/or provide other helpful services for your UI form (or other consumer of your SData feed).

SData provides data type feeds similar to Views built closely over database tables, but it also provides “service” feeds that are similar to Accpac superviews. These feeds are meant to perform service type operations like printing a report, posting a batch or doing a calculation. They can operate asynchronously, meaning the originating call returns immediately, but then can poll the service for status updates (which can be used to update a meter control).

Here is a bit of sample code from the SData service that provides the data for the pie charts in the G/L Balance Sheet data snapshot.

public class GLBALSHTService extends BaseService
{
   private final SDataView            viewGLFSUM;
   private final List<ServiceField>   requestFields;
   private final List<ServiceField>   responseFields;
   private static final String        STR_RSCID  = "GLBALSHTSP";
   private boolean                    bPermitted = false;
   private GLLanguageResourceContents GLLanguageResource;
   public GLBALSHTService(final ApplicationContext applicationContext, final ResourceContextImpl resourceContext,
         final Resource resource, final Service service, final SDataViewSet viewSet)
   {
      super(applicationContext, resourceContext, resource, service, viewSet);
      viewGLFSUM = new SDataView(getResourceContext().getAccpacProgram(), GLFSUM.VIEW, resource);
      bPermitted = getResourceContext().getAccpacProgram().isPermitted(STR_RSCID);
      if (!bPermitted)
      {
         String appVersion;
         String appLang;
         //language dependent resource content is only used when access is not permitted.
         appVersion = resourceContext.getAccpacProgram().getActiveApplications().get(GLLanguageResourceContents.APPL)
               .getAppVersion();
         appLang = viewGLFSUM.getProgram().getSession().getUserLanguage();
         GLLanguageResource = new GLLanguageResourceContents(appVersion, appLang);
      }
      requestFields = new ArrayList<ServiceField>();
      responseFields = new ArrayList<ServiceField>();
      setupRequestFields();
      setupResponseFields();
    }
   @Override
   public void shutdown()
   {
      if (this.viewGLFSUM != null)
         this.viewGLFSUM.dispose();
   }
    private void setupRequestFields()
   {
      requestFields.add(ServiceHelper.viewFieldToServiceField(viewGLFSUM.getFields().get(GLFSUM.IDX_YEAR)));
      requestFields.add(ServiceHelper.viewFieldToServiceField(viewGLFSUM.getFields().get(GLFSUM.IDX_PERIOD)));
      requestFields.add(ServiceHelper.viewFieldToServiceField(viewGLFSUM.getFields().get(GLFSUM.IDX_PERIODS)));
   }
   private void setupResponseFields()
   {
      responseFields.add(ServiceHelper.viewFieldToServiceField(viewGLFSUM.getFields().get(GLFSUM.IDX_ENDDATE)));
      responseFields.add(ServiceHelper.viewFieldToServiceField(viewGLFSUM.getFields().get(GLFSUM.IDX_CASH)));
     // … Lots more response fields defined …
   }
   protected List<ServiceField> createRequestFields(final SDataRequest request)
   {
      return requestFields;
   }
   @Override
   protected List<ServiceField> createResponseFields(final SDataRequest request)
   {
      return responseFields;
   }
   @Override
   protected List<ServiceField> execute(SDataResourceElement payload, SDataRequest request, AsyncStatusListener listener)
   {
      List<ServiceField> list = new ArrayList<ServiceField>();
      if (!bPermitted)
      {
         throw (new RuntimeException(GLLanguageResource.getValue(GlobalContent.ACCESS_DENIED_MSG.toString()), null));
      }
      int errorCode;
      this.viewGLFSUM.recordClear();
      setGLFSUMViewFieldsValue(payload);
      MeterEventListener meterListener = null;
      if (listener != null)
      {
         meterListener = new MeterListener(listener, listener.getProgress().getProgressPct(),
               TrackingPayload.PROGRESSPCT_GET_RESULT);
      }
      errorCode = viewGLFSUM.process(meterListener);
      if (errorCode > 0)
      {
         throw (new RuntimeException(null, null));
      }
      list.add(ServiceHelper.viewFieldToServiceField(viewGLFSUM.getFields().get(GLFSUM.IDX_ENDDATE)));
      list.add(ServiceHelper.viewFieldToServiceField(viewGLFSUM.getFields().get(GLFSUM.IDX_CASH)));
      // … Lots more reponse fields added …
      return list;
   }
 
   /**
    * function to set field value
    */
   private void setGLFSUMViewFieldsValue(SDataResourceElement payload)
   {
      for (SDataResourceElement elem : payload.getContents())
      {
         final String name = elem.getName();
         String value = (String)elem.getValue();
         if (value != null)
         {
            viewGLFSUM.putBySDataPropertyName(name, value, Boolean.FALSE);
         }
      }
   } 
   /**
    * set the default value for the request fields
    */
   @Override
   protected List<ServiceField> createTemplateFields(final SDataRequest request)
   {
      List<ServiceField> list = new ArrayList<ServiceField>();
      this.viewGLFSUM.recordClear(); 
      list.add(ServiceHelper.viewFieldToServiceField(viewGLFSUM.getFields().get(GLFSUM.IDX_YEAR)));
      list.add(ServiceHelper.viewFieldToServiceField(viewGLFSUM.getFields().get(GLFSUM.IDX_PERIOD)));
      return list;
   }
}

 

This service is then defined in the GLServiceMap.xml file under the tomcat\portal directory:

<?xml version="1.0" encoding="UTF-8"?>
<serviceMap>
<services>
       <service
         className="com.sage.accpac.gl60a.common.server.GLBALSHTService">
       </service>
… other definitions …
</services>   
</serviceMap> 

 

In the execute method, notice the View calls to the GLSUM View. You can see calls to recordClear and process. Basically these are calls to our Java JNI layer (Java Native Interface, http://en.wikipedia.org/wiki/Java_Native_Interface). Here we have a hierarchy of classes very similar to what we had in COM for VB programming where you can access all the View methods as well as a selection of convenient other System Manager APIs.

The basic logic here is to first initialize the operation in the constructor, get the input fields from the SData feed (the request fields as in setupRequestFields), perform the various View operations that are required (the execute method) and then setup the response fields to send back to the UI running in the Browser (created in setupResponseFields and then set in the execute method).

Hopefully, this gives a bit of a flavor for what sort of programming goes on the server for helping User Interface programs from an SData point of view.

Written by smist08

August 28, 2010 at 4:21 pm

Posted in sage 300

Tagged with , , , ,

More on SData and Sage ERP Accpac 6

with 11 comments

SData is Sage’s new Web Services standard. It is documented in full at http://sdata.sage.com/. For Sage ERP Accpac 6.x, SData is the interface used by the browser based UI pages to communicate with the Server. Like in Accpac 5.X where the Accpac COM API was the interface used for all UI to Business Logic communication, this role is taken over by SData in 6.x. This means that there is a complete robust REST based Web Services interface to the Sage ERP Accpac application. Anything that can be done from an Accpac User Interface Web Page can also be done via any other program making SData Web Services calls.

REST based Web Services are very simple in how they are constructed, they are built using current Web Standards such as HTTP and Atom. For instance the screen shot below shows typing:

http://bcraccdemo/SDataServlet/sdata/sageERP
/accpac/SAMINC/Customers(‘1200’
)

into the URL field for the Chrome Browser.

This URL is an SData request, it is sent to the server bcraccdemo and the application SDataServlet running there. The rest of the URL is then processed by the Accpac SData provider to return the correct data for customer 1200 (Ronald Black) in XML Atom format, which is then displayed in the Browser window. As you can see, no special infrastructure or programming libraries were required to make this Web Service call. All that was needed was the ability to send an HTTP request and receive the response.

SData is also self describing. Below is a screen shot of asking for the schema of the XML response given above.

When doing update or insert calls you need to provide an XML payload of data similar to the response above of the data to be updated or inserted.  There is also a standard interface for doing services which in Accpac includes things like reporting, day end and posting.

The example above was for customer 1200, however if the (‘1200’) part was removed, SData would have returned all the customers in A/R. In this case you can specify a filter to say return all customers greater than some point or specify which fields to sort the returned data by. SData will also page the data returned, it will return a block of records with links to the previous and next blocks.

Basically SData is a fairly simple protocol to use that should be accessible to almost any programming system. It is rich enough to support all UI operations required by Accpac. And ISV’s can be confident that it is complete enough, since all Accpac UIs rely on it. It is standards based on HTTP, Atom and other Web Standards allowing standards based tools to be used. Generally a very powerful Web Based Interface to greatly enhance Accpac’s intergratability and extensibility. Since SData is being adopted by all Sage Business Applications, learning and using SData with Accpac will teach you how to use SData for any SData equipped application, such as Sage CRM.

Written by smist08

January 18, 2010 at 11:45 pm

Posted in SData

Tagged with , , ,

SData in Sage ERP Accpac 6

with 62 comments

One of the big features in Accpac 6 is SData support. What is SData? SData is a web services protocol based on REST. What is REST? REST is a web services protocol that is very popular among Internet companies. There are basically two main competing standards for web services. One is SOAP which is promoted by Microsoft, Oracle and IBM; this is a fairly heavy duty protocol which requires a fair bit of infrastructure (which is provided by the companies promoting this protocol). The other is REST which was invented as a University Research project and basically uses existing Web Technologies such as HTTP and RSS to implement a web services protocol. The nice thing about REST is that it doesn’t require any extra middleware. You are basically doing everything via standard web URLs. The infrastructure that supports this is basically just the standard Internet. SData is just an extension to REST, similar to Google’s GData which is also based on REST. REST protocols are used by Google, Amazon, eBay, Yahoo and all the main Internet companies. Gartner estimates that 75% of web services in use on the Internet are REST based. REST/SData also provides a standard mechanism for performing CRUD (create, read, update, delete) on all records.

From Accpac, every Accpac View (or Business Logic Object) will be exposed via SData. This provides third party ISVs a complete, efficient Web Services interface to communicate to Accpac with. Also all Sage applications are being made SData aware, meaning that all Sage applications can manipulate SData Web Services (or feeds). For instance here is some Accpac A/R Customer and G/L Account data displayed within a Sage CRM Dashboard using SData.

From a simple wizard you can select any Accpac SData feed and once you’ve chosen a feed, you can select which columns you wish to display. Additionally Sage CRM and Accpac will be converting to use SData for our integration needs, this transition will occur over several versions of both products. In the same way you will be able to access CRM data from Accpac using SData.

All the new Sage ERP Accpac 6 screens are written entirely using SData. This means the screen can access any Accpac Views via SData, but additionally they can access any SData feeds from any product. In Accpac 5.x, the screen controls were mapped via datasource controls to views and view fields. This was great, but it limited you to only connecting our standard controls to fields in Views developed in our SDK. Now that the controls are mapped to a standards based SData fields, it means they will be able to be connected easily to much more data than just Accapc data. Look for other Sage products to start providing SData interfaces in their coming versions.

Sage is publishing SData as a publicly available standard. You can read all about it at: http://sdata.sage.com/.

Written by smist08

November 24, 2009 at 3:29 pm

Posted in SData, Software Architecture

Tagged with , , , ,