<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>The Software Gorilla &#187; AppServer</title>
	<atom:link href="http://www.thesoftwaregorilla.com/tag/appserver/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.thesoftwaregorilla.com</link>
	<description>The Software Gorilla</description>
	<lastBuildDate>Thu, 08 Jul 2010 07:23:24 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>Exchange Web Services &#8211; Starting out</title>
		<link>http://www.thesoftwaregorilla.com/2010/04/exchange-web-services-starting-out/</link>
		<comments>http://www.thesoftwaregorilla.com/2010/04/exchange-web-services-starting-out/#comments</comments>
		<pubDate>Tue, 20 Apr 2010 12:28:25 +0000</pubDate>
		<dc:creator>Bruce Gruenbaum</dc:creator>
				<category><![CDATA[Commentary]]></category>
		<category><![CDATA[Exchange Web Services]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[OpenClient]]></category>
		<category><![CDATA[OpenEdge]]></category>
		<category><![CDATA[OpenEdge AppServer]]></category>
		<category><![CDATA[SOA]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[n-tier Development]]></category>
		<category><![CDATA[ABL]]></category>
		<category><![CDATA[Apache ActiveMQ]]></category>
		<category><![CDATA[Application Server]]></category>
		<category><![CDATA[AppServer]]></category>
		<category><![CDATA[EWS]]></category>
		<category><![CDATA[Exchange EWS]]></category>
		<category><![CDATA[Glassfish AppServer]]></category>
		<category><![CDATA[Java OpenClient]]></category>
		<category><![CDATA[Microsoft Exchange 2007]]></category>
		<category><![CDATA[OpenEdge OpenClient]]></category>
		<category><![CDATA[Progress AppServer]]></category>
		<category><![CDATA[Progress OpenClient]]></category>

		<guid isPermaLink="false">http://www.thesoftwaregorilla.com/?p=290</guid>
		<description><![CDATA[A couple of months back, a gentleman who has now become a friend and business partner, came to me and asked me if there was any way to get at all the calendar items in his sales organization's calendars with the intention of integrating it with his Progress OpenEdge CRM system. Jim is using Exchange 2007 for his e-mail and calendaring solutions.

I was aware that Microsoft had released a new API for Exchange in Exchange 2007 called Exchange Web Services (EWS), and so I said that I needed to do a little research on the API, but I was pretty sure that it was possible. Sure enough, MSDN has some documentation of the API and Microsoft is touting it as the replacement for all APIs that communicate with Exchange. Web Services - how hard can it be?
]]></description>
			<content:encoded><![CDATA[<p>Many people make use of different mechanisms for creating e-mail messages. Most of them use some kind of SMTP client to do so. For the more adventurous, there is MAPI that allows you access to a Microsoft Mail based client to do a few things over and above just plain mail. These are things that people do on a daily basis.</p>
<p>A couple of months back, a gentleman who has now become a friend and business partner, Jim Ford of <a href="http://www.fordav.com/" target="_blank">Ford Audio-Visual</a>, came to me and asked me if there was any way to get at all the calendar items in his sales organization&#39;s calendars with the intention of integrating it with his Progress OpenEdge CRM system. Jim is using Exchange 2007 for his e-mail and calendaring solutions.</p>
<p>I was aware that Microsoft had released a new API for Exchange in Exchange 2007 called Exchange Web Services (EWS), and so I said that I needed to do a little research on the API, but I was pretty sure that it was possible. Sure enough, MSDN has&nbsp;some documentation of the API and Microsoft is touting it as the replacement for all APIs that communicate with Exchange. Web Services &#8211; how hard can it be?</p>
<h3>The Production Environment</h3>
<p>In the&nbsp;production environment, an OpenEdge client running on a Unix server&nbsp;needs to initiate a WebService call to Exchange to create, update and delete appointments for sales people. These appointments will be created in the user interface for the CRM application.</p>
<p>Sales people then need to be able to&nbsp;change and&nbsp;delete these appointments from their Outlook clients or their Blackberry/iPhones. Any changes to the appointments need to be recorded as history updates in the CRM system, so Exchange needs to notify the OpenEdge CRM system of these changes.</p>
<p>So the updates to appointments need to happen from both directions and the communication is going to happen cross-platform (Unix to Windows and vice-versa).</p>
<h3>Initial Idea</h3>
<p>My initial plan was to create a prototype that did&nbsp;the two-way&nbsp;communication directly from OpenEdge to EWS. I just wanted to prove that it was possible. The first step was to build an OpenEdge WebServices Client that created a calendar item in the Exchange store. Unfortunately, for various reasons, this is much harder than I thought it would be.</p>
<p>First, the EWS WSDL is not a standard WSDL. EWS is installed as part of the Client Access Server (CAS)&nbsp;component of Exchange. In production, you can have multiple Mailbox Servers and the CAS has to discover which mailbox server services a client. As a result, the URL that is used to actually call EWS is different depending on which Mailbox Server hosts the mailbox. The WSDL therefore does not contain a &quot;service&quot; node and the OpenEdge WSDL parser cannot parse the WSDL. I tried working around that by creating a dummy WSDL with a service node inside it.</p>
<p>The second problem was&nbsp;that I ran into all kinds of problems with the complex type structure that exist in the WSDL. The types and messages live in a separate XSD file and the WSDL parser did not like some of the&nbsp;message definitions as they included optional types.</p>
<p>The last straw was that the connection to EWS is an SSL connection that, by default, wants to use NTLM authentication and I battled for hours to get this to work. I would probably have figured the problem out earlier if I had had some more clear indications from OpenEdge of exactly what the problem was, but I finally decided to go and try the connection from Java.</p>
<h3>The Bible</h3>
<p>Before I started on the Java example, I decided that I should probably test that I could even make this happen in .NET. Even that is no small feat. The examples that come with the Exchange SDK are about as useful as an udder on a bull, and I eventually decided to bite the bullet and look for a book on the subject.</p>
<p>I normally avoid Microsoft Press books because, more often than not, they simply regurgitate the standard Microsoft examples and contribute very little additional value. That is not the case with <a href="http://www.amazon.com/Inside-Microsoft-Exchange-Server-Services/dp/0735623929/ref=sr_1_1?ie=UTF8&amp;s=books&amp;qid=1271763925&amp;sr=8-1" target="_blank"><em>Inside Microsoft Exchange 2007 Web Services</em></a>. Authors David Sterling, Benjamin Spain, Michael Mainer, Mark Taylor, and Huw Upshall have done an outstanding job of creating a book that really gets to the heart of the technology. They are all members of the Exchange development team, and it shows. The book provides enough background information that it is essential reading for anyone trying to do this stuff.</p>
<h3>Java to EWS</h3>
<p>Armed with my new reference, I now set about building a Java client that could create an appointment in Exchange, figuring that I could expose the Java client as a Web Service that OpenEdge could consume.</p>
<p>Now, before you throw your toys out your crib and tell me that that is a very expensive way to do things from a performance point of view, let me just clarify that I would have ended up going down this road eventually, anyway. Ultimately, the solution will be exposed as a service on an ESB, and that ESB is likely to be based on a JMS MOM, like Apache ActiveMQ, or SonicMQ. So this is not a wasted exercise. The reason that I need this on an&nbsp;ESB is that the&nbsp;events that flow in each direction need to be available to other services, too.</p>
<p>Java to EWS was not a lot easier to get working. I still had to work around the WSDL not having a &quot;service&quot; node issue, but Java gives you finer-grained control of the parsing of the WSDL. Moreover, in my initial implementation, I did not use JAX-WS or any other WebServices technologies like Axis. I simply used an HTTP request to the WebService to get through the issues. This made life a whole lot easier.</p>
<p>The SSL problem reared its ugly head again, but this time I quickly learned 2 things:</p>
<ol>
<li>Exchange creates a default certificate for you when you install it. Either you have to install the certificate as a trusted certificate in the certificate store, or you have to set up a certificate authority on your Windows Server and build signed certificates. I went with the former idea and that resolved the first part of the SSL problem.</li>
<li>Exchange is installed to support only NTLM authentication, but NTLM authentication is a pain to work with from non-Microsoft technologies. You can change the settings of the EWS virtual directory on the Microsoft IIS Server that runs on the CAS to support basic and digest authentication. For testing,&nbsp;I set this up as basic, but I now have digest working. I will probably go back and revisit NTLM again later, but it is very hard to find any information to help with solving problems, so I may simply require digest authentication.</li>
</ol>
<p>Once I got past these issues, creating the calendar item was actually very simple.</p>
<h3>OpenEdge through the&nbsp;Java WebService</h3>
<p>The next step&nbsp;was to take what I had created and expose it as a Java Web Service. I went with Glassfish V3 as the application server just to test this and in about a half hour I had the Web Service up and running and <a href="http://www.soapui.org" target="_blank">soapUI</a> was creating appointments through the Java Web Service without any problems.</p>
<p>I then went back to OpenEdge and used its WSDL analyzer to&nbsp;analyze the WSDL. It worked really well. I then built a quick client that called the Java Web Service from OpenEdge and it worked first time.</p>
<h3>Next Steps</h3>
<p>Although this is now a working prototype, it is exactly that &#8211; a prototype. There are several pieces that still have to be proven:</p>
<ol>
<li>I need to&nbsp;subscribe to change updates from Exchange.</li>
<li>I need to&nbsp;get to updates for all sales person&nbsp;mailboxes. This means I need to use Exchange Impersonation and that has a number of security risks associated with it.</li>
<li>I need to make sure these updates get through to OpenEdge efficiently which means I need a test harness that can generate several thousand appointments a minute and have them update the OpenEdge AppServer without breaking it.</li>
</ol>
<h3>Conclusion</h3>
<p>Having said that, I am really excited and very optimistic about how this is turning out. I have learned more about Windows Server, Microsoft Exchange, Active Directory, Exchange Web Services, OpenEdge Web Services, and Java Web Services than I had ever imagined possible.</p>
<p>In the next few weeks I will be providing an update on where I finally ended up with this from an architectural point of view.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.thesoftwaregorilla.com/2010/04/exchange-web-services-starting-out/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>OpenEdge Dynamic OpenClient Java Example</title>
		<link>http://www.thesoftwaregorilla.com/2009/11/openedge-dynamic-openclient-java-example/</link>
		<comments>http://www.thesoftwaregorilla.com/2009/11/openedge-dynamic-openclient-java-example/#comments</comments>
		<pubDate>Tue, 10 Nov 2009 02:27:48 +0000</pubDate>
		<dc:creator>Bruce Gruenbaum</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[OpenClient]]></category>
		<category><![CDATA[OpenEdge]]></category>
		<category><![CDATA[4GL]]></category>
		<category><![CDATA[ABL]]></category>
		<category><![CDATA[Application Server]]></category>
		<category><![CDATA[AppServer]]></category>
		<category><![CDATA[AVM]]></category>
		<category><![CDATA[Dynamic OpenClient]]></category>
		<category><![CDATA[Java OpenClient]]></category>
		<category><![CDATA[OpenEdge OpenClient]]></category>
		<category><![CDATA[Progress]]></category>
		<category><![CDATA[Progress AppServer]]></category>
		<category><![CDATA[Progress OpenClient]]></category>
		<category><![CDATA[PVM]]></category>

		<guid isPermaLink="false">http://www.thesoftwaregorilla.com/?p=90</guid>
		<description><![CDATA[In a previous post, I said I would post an example that demonstrates the use of the OpenEdge Dynamic OpenClient. Well here is the Java version of it. This post is an extensive discussion of the example and how it is structured. Enjoy.]]></description>
			<content:encoded><![CDATA[<p>In a previous post, I said I would post an example that demonstrates the use of the OpenEdge Dynamic OpenClient. Well <a href="http://www.thesoftwaregorilla.com/wp-content/uploads/2009/11/DynamicOpenClient.zip">here is the Java version of it</a>.</p>
<p>It took me a while to get this done, not so much because of the code, but because the documentation that accompanies it is pretty extensive and I have been in the middle of some significant career changes.</p>
<p>This post is long primarily because I walk through the highlights of the what the code does and how this bolsters what I was saying in my earlier post.</p>
<p>Inside the zip file are 2 zip files and&nbsp;3 PDF files:</p>
<ul>
<li><strong>DynamicOpenClientJar.zip</strong> is the compiled version of the code. It contains a jar file, the input.xml, a batch file, and the Progress source code.</li>
<li><strong>DynamicOpenClientJar.pdf</strong> contains setup instructions to set it up and run it.</li>
<li><strong>DynamicOpenClientSrc.zip</strong> is the source code.</li>
<li><strong>DynamicOpenClientSrc.pdf</strong>&nbsp;contains the instructions that&nbsp;that tells you how to set&nbsp;the source code up to work with Eclipse.</li>
<li><strong>DynamicOpenClient.pdf </strong>is a detailed tour of the code and describes how it works.</li>
</ul>
<h4>This is Sample Code</h4>
<p>Before you dig into the code and say &quot;Wow!! This code sucks!!&quot; it is important to understand that this is sample code. There are a lot of things about it that are ugly. Some of the object model needs serious refining. There are cleaner ways of doing the XML&nbsp;parsing and it is nowhere near as defensive as it should be. There are those who believe that bad code samples lead to bad code in production, but there is another line of thought that goes that if you don&#39;t recognize those bad examples, you should not be coding to start with. The point with this code is that it demonstrates concepts and that&#39;s what it was intended to do.</p>
<h4>Code Limitations</h4>
<p>For the sake of brevity, I&nbsp;have deliberately not covered stuff like supporting supporting ProDataSets and all of the different Progress data types.&nbsp;I have covered the most common ones and temp-tables. ProDataSets are really an extension of temp-tables and you can feel free to go and look at the code in a generated proxy to see how they work. I&nbsp;also stopped short of supporting the building of temp-tables from an input XML&nbsp;file. The extra code to do this did not seem like it would really add that much to the example. This code example also does not support persistent procedures because they are a lot more complicated than this code will allow.</p>
<h4>Set it up and try it</h4>
<p>Having said all of that, I wanted to spend some time in this post elaborating on the comments that I made in the earlier post about why Dynamic OpenClient is such a powerful technology, using the example code that I am presenting here. So I am going to assume for the rest of this article that you have at least set up and run the example and that you have the source code accessible to follow along.</p>
<h4>How it Works</h4>
<p><a href="http://www.thesoftwaregorilla.com/wp-content/uploads/2009/08/Sequence-Diagram.jpg" target="_blank"><img align="right" alt="Dynamic Open Client Utility Sequence Diagram - Click for full size" border="0" height="192" hspace="2" src="http://www.thesoftwaregorilla.com/wp-content/uploads/2009/08/Sequence-Diagram.jpg" vspace="2" width="300" /></a>The Dynamic Open&nbsp;Client code takes an XML&nbsp;file and parses it for AppServer connection parameters, R-Code signatures and calls that need to be made to the Progress/OpenEdge R-Code files. The sequence diagram at right (click on it for a full-size image)&nbsp;shows the process.</p>
<p>Once the XML file has been parsed, the utility executes each of the calls and serializes the results of the call&#39;s execution to an internal XML document. Once all the calls have been executed and serialized, the results are written out to another XML file that is specified in the input.xml file. More information on the XML file&#39;s format is in the DynamicOpenClient.pdf file.</p>
<h4>The Main Components</h4>
<p>To understand how this utility works, you need to understand the core of the class model. So let me start by dividing the class model into its major areas.</p>
<p>You can pretty much ignore the <em>com.tsg.common</em> project.&nbsp;It contains&nbsp;an interface -&nbsp;<em>INamedItem</em> &#8211; used&nbsp;by a few classes that&nbsp;simply has a getName() method declaration.&nbsp;<em>INamedItem</em> is&nbsp;implemented by some of the classes in the <em>com.tsg.dynamicopenclient</em> project. This interface is specifically used for objects that may be stored in a <em>com.tsg.common.collections.OrdinalList</em> &#8211; a specialized list that is ordinal like an ArrayList, but expects uniquely named items in the list.&nbsp;<em>OrdinalList</em> is used&nbsp;for things like field lists and parameter lists where the fields need to be in a specific order, but the names have to be unique.</p>
<p>The <em>com.tsg.dynamicopenclient</em> project contains three packages:<a href="http://www.thesoftwaregorilla.com/wp-content/uploads/2009/08/Class-Model.jpg" target="_blank"><img align="right" alt="Dynamic Open Client Sample Utility Class Model" height="200" hspace="2" src="http://www.thesoftwaregorilla.com/wp-content/uploads/2009/08/Class-Model.jpg" vspace="2" width="300" /></a></p>
<ul>
<li><em>com.tsg.dynamicopenclient </em>- This package contains&nbsp;the code that does most of the work;</li>
<li><em>com.tsg.dynamicopenclient.data </em>- This package&nbsp;contains the&nbsp;class hierarchy for parameter and other&nbsp;data element&nbsp;definitions;</li>
<li><em>com.tsg.dynamicopenclient.valueholders </em>- This package contains&nbsp;the class hierarchy for all the value holders that&nbsp;are used to contain&nbsp;the values of input and&nbsp;output parameters.</li>
</ul>
<h5>Data Types</h5>
<p>One of the most&nbsp;important aspects of the&nbsp;communication between the&nbsp;OpenClient and the AppServer, is the mapping of data types from Java to Progress. To&nbsp;make sure that this is done consistently, there is a&nbsp;<em>DataType</em> <em><strong><a href="http://java.sun.com/docs/books/tutorial/java/javaOO/enum.html" target="_blank">enumeration</a></strong></em> in&nbsp;<em>com.tsg.dynamicopenclient</em>.&nbsp;If you have not worked with Java 5, enumerations may be a new concept to you and this one is particularly more so than others. An enumeration is a great way to deal with hard-coded constants and it is particularly useful where a map of constants is necessary. In this&nbsp;particular case we have to map an OpenClient numeric constant to a string representation of the data type, a Java class that can be used to map to that type and a valueholder class that can be used to contain the Java type. The following definition of the INTEGER data type demonstrates the mechanism:</p>
<pre>INTEGER
  (Parameter.PRO_INTEGER, // Progress numeric constant
   Parameter.PRO_INTEGER_NAME, // Progress character constant
   &quot;java.lang.Integer&quot;, // Java class to be used to map
   &quot;com.tsg.dynamicopenclient.valueholders.IntegerValueHolder&quot;),&nbsp;// Dynamic OpenClient valueholder
</pre>
<p>The DataType enumeration has several methods associated with it to retrieve a constant based on the string name of the data type or to obtain the Java class, value holder class&nbsp;or Progress data type constant. It also contains code that will instantiate an object of either the Java class to contain the data type or the value holder. This enumeration truly is at the core of the code.</p>
<h5>Data Elements</h5>
<p>The <em>com.tsg.dynamicopenclient.data</em> package contains a set of classes that define the behavior of data elements. A data element is any item that has a name and a datatype associated with it. Thus, fields and parameters are all data elements. Data elements only store the definition of the element. They do not store the value. The value is stored in a <a href="#ValueHolder">value holder</a>. The abstract base <em>DataElement</em> class contains all the behavior for parsing parameter and field definition information from an XML node.</p>
<p>The <em>Parameter</em> class extends it by providing support for parameter modes (INPUT, INPUT-OUTPUT and OUTPUT)&nbsp;which are mapped in&nbsp;an enumeration called <em>ParameterMode</em> in <em>com.tsg.dynamicopenclient</em>.</p>
<p>The <em>TempTableParameter</em> class extends the <em>Parameter</em> class further by providing support for parsing temp-table definitions from the source code and supporting the construction of ProDataGraphMetaData objects that are used to build the ProDataGraph to transport temp-tables between AppServer and client.</p>
<h5><a name="ValueHolder"></a>Value Holders</h5>
<p>The <em>com.tsg.dynamicopenclient.valueholders</em> package contains a set of classes and an interface that are used to standardize the way that data types are dealt with. Looking at the class model, the value holder hierarchy is to the right of the diagram. This hierarchy leverages the concept of <strong><em><a href="http://java.sun.com/j2se/1.5/pdf/generics-tutorial.pdf" target="_blank">generics</a></em></strong> that was introduced in Java 5.</p>
<p>The <em>IValueHolder</em> interface is the base of the hierarchy and the <em>ValueHolder</em> abstract class contains the generic behavior for value holders. These classes provide support for the Progress UNKNOWN value as well as reasonable default values that match the Progress defaults for its data types.</p>
<p>Value holders are used to set the value of input parameters and to contain the&nbsp;values of output parameters.</p>
<h5>DynamicOpenClient Class</h5>
<p>The DynamicOpenClient class in <em>com.tsg.dynamicopenclient</em> contains the <em>main()</em> method&nbsp;- the entry point to the utility. It starts out by parsing the parameters to determine where the XML file is that contains the signatures and input parameters for the calls. The input.xml file&#39;s structure is detailed in the DynamicOpenClient.pdf file that accompanies the source code. In essence, though, there are 4 types of nodes that are important:</p>
<ul>
<li><strong>dynamicoc</strong> &#8211; This is the root node for the document and it contains an OutputFile attribute that has the name of the file that should be used for the results of the calls.</li>
<li><strong>appserver</strong> &#8211; This node contains the signature and call nodes and a set of attributes that define the connection parameters for the AppServer.</li>
<li><strong>signature</strong> &#8211; This node contains the signature of a call that will be executed against the AppServer. The signature node may contain a set of parameter nodes which will be all of the parameters for a procedure. These parameters must be specified in the order that they are specified in the ABL source code. If the parameter&#39;s&nbsp;DataType attribute&nbsp;is TABLE, the node will contain child nodes that are the field and indexes for the table.</li>
<li><strong>call</strong> &#8211; This node contains a list of calls that need to be executed against the AppServer. Each of them should refer (by means of the Procedure attribute) to a previously specified signature. call Nodes may contain subordinate parametervalue nodes that reference a parameter in the signature by name and specify the value to be used as the input value for that parameter.</li>
</ul>
<p>The following code extract&nbsp;comes from&nbsp;the <em>main()</em> method.</p>
<pre>//Extracted from <strong>main()</strong> method.
//

//Instantiate the CallManager
CallManager manager = CallManager.getInstance();

//Parse the XML file.
try {
	parse(fileName);
}
catch (Exception e) {
	System.out.println(e.getMessage());
	return;
}
.
.
.
Iterator&lt;Call&gt; iter = manager.iterator();
while (iter.hasNext()) {
	Call call = iter.next();&nbsp; //Get the call
	call.executeCall();&nbsp;&nbsp; //Execute the call
	outRoot.appendChild(call.serializeResults(outputDocument));
	iter.remove();
}
.
.
.
try {
	writeResults();&nbsp; // Write the XML results file out to disk.
}
catch (Exception e) {
	System.out.println(e.getMessage());
	return;
}</pre>
<p>Before doing anything else, the code instantiates the Singleton CallManager to hold onto all the data that will be parsed from the XML file.</p>
<p>The <em>main() </em>method calls the static <em>parse() </em>method with the name of the XML file to be parsed. This method parses the XML document and iterates through the four element nodes mentioned above. It also sets up a DOM document that will be used as the output document for the results of the calls.</p>
<p>For each element, it instantiates an object of the appropriate class and passes it the XML node that needs to be instantiated. This&nbsp;object is then added to the CallManager where it will be retrieved later.</p>
<pre>//Extracted from <strong>parse()</strong> method.
//
Node elementNode = null;
while((elementNode = iterator.nextNode()) != null) { // Loop through elements

	// Handle root node.
	if (elementNode.getNodeName().equalsIgnoreCase(XMLStrings.INPUT_ROOT_NODE.toString())) { 	

		// Setup the output file.
		String attrValue = XMLStrings.getAttribute(elementNode, XMLStrings.OUTPUT_FILE_ATTR.toString());
		if (attrValue != null) {
			outputFileName = attrValue;
		}
	}

	// Handle appserver node
	if (elementNode.getNodeName().equalsIgnoreCase(XMLStrings.APPSERVER_NODE.toString()) ) {
		manager.setAppServerConnection(new AppServerConnection(elementNode));
	}

	// Handle signature node
	if (elementNode.getNodeName().equalsIgnoreCase(XMLStrings.SIGNATURE_NODE.toString()) ) {
		manager.setSignature(new Signature(elementNode));
	}

&nbsp;	// Handle call node
	if (elementNode.getNodeName().equalsIgnoreCase(XMLStrings.CALL_NODE.toString()) ) {
		manager.addCall(new Call(elementNode));&nbsp;
 	}
}</pre>
<p>The <em>CallManager</em> implements the <em>Iterable</em> interface for the <em>Call</em> class.&nbsp;Back in the <em>main()</em> method, the next thing we do is iterate through all&nbsp;of the <em>Call</em> objects in the <em>CallManager</em> and we execute the call. This is where the real work happens and a description of it is below. When execution is complete, the parameter values will have been stored in the <em>Call</em> object and a call to <em>serializeResults()</em> will return an XML node that can be appended to the output document. The <em>Call</em> object is then deleted from the list of calls to free up the memory that any temp-tables will occupy.</p>
<p>Once all the calls have been executed, a call is made to writeResults() which writes the output XML document to disk.</p>
<h4>Executing the Call</h4>
<p>A&nbsp;call&nbsp;is actually executed by&nbsp;a call to&nbsp;<em>executeCall()</em>&nbsp;on the <em>Call</em> object. The <em>executeCall()</em> method simply builds a parameter array, calls the <em>runProcedure() </em>method on the AppServerConnection object, builds the output parameter value set and handles any exceptions. The thing that makes this client dynamic is the code in <em>buildParamArray()</em> and <em>buildOutputValues()</em>.</p>
<h5>buildParamArray()</h5>
<p>In order to make a call to the AppServer, the OpenClient needs a procedure name to call and a parameter array (<em>com.progress.openABL.javaproxy.ParamArray</em>) for the call. The parameter array needs to contain a full description of each parameter as well as the value to be set for the parameter. The <em>Call</em> object has a procedure name and it has the values of the input parameters. The name of the procedure maps to a <em>Signature</em> object which can be obtained from the <em>CallManager</em> and it contains the definitions of all of the parameters that are needed for the call. Thus, <em>buildParamArray()</em> obtains the <em>Signature</em> object and builds a <em>ParamArray</em> object with each of the parameter definitions in the <em>Signature</em> object. As it attempts to add each parameter to the <em>ParamArray</em>, it obtains a IValueHolder object to contain the parameter&#39;s input or output parameter value.&nbsp;It then&nbsp;checks for a corresponding input value in the <em>Call</em> object. If it finds a corresponding value it sets the input value in the <em>ParamArray</em> from this value. This is how the <em>Call</em> information in the XML file can specify the parameter values by name in any order and only specify the ones that have values associated with them.</p>
<pre>//Extracted from <strong>buildParamArray()</strong> method.
//

CallManager manager = CallManager.getInstance();
Signature sig = manager.getSignature(getProcedureName()); //Get the signature for this call
if (sig == null) {
	throw new DynamicOpenClientException(...);
}
ParamArray params = new ParamArray(sig.getParameterCount()); //Instantiate a ParamArray object

int idx = 0;

// Iterate through all the parameters in the signature.
for (Parameter param : sig) { 

	// Instantiate an IValueHolder for this data type.
	IValueHolder&lt;?&gt; valueHolder = DataType.getValueHolder(param.getDataType());
	paramValues.add(valueHolder); // Put the value holder into the paramValues list.

	// If we can find a parameter value that was set for this call,
	// set the value of the IValueHolder to the input value.
	if (inputValues.containsKey(param.getName())) {&nbsp;
		valueHolder.setObject(inputValues.get(param.getName()));
	}</pre>
<p>Now that the data we&nbsp;need is available (ie, the parameter type information and input values have been set), we can go about setting the values, but we need to treat the&nbsp;TABLE and TABLE-HANDLE types differently from the the other data types. The reason is that they need a ProDataGraph and its metadata. The code for setting the values is therefore as follows:</p>
<pre>Object value = null;
switch(param.getDataType()) {
	case TABLE:
	case TABLE_HANDLE:
		TempTableParameter ttParam = (TempTableParameter) param;
		ProDataGraphValueHolder graphHolder = (ProDataGraphValueHolder) valueHolder;
		ProDataGraphMetaData metaData = null;
		switch(param.getMode()) {
			case OUTPUT:
				// For a table we need the table structure. TABLE_HANDLE needs null.
				if (param.getDataType() == DataType.TABLE) {
					metaData = ttParam.getProDataGraphMetaData();
				}
				break;
			default:
				value = graphHolder.getProDataGraph();
				metaData = graphHolder.getProDataGraph().getMetaData();
				break;
		}

		// Add a parameter to the ParamArray with the appropriate value.
		params.addParameter(idx, value, ttParam.getMode().getModeCode(),
			ttParam.getDataType().getTypeCode(),
			ttParam.getExtent(),
			metaData);
		break;
	default:
		// Now get the object from the IValueHolder that has the value in it.
		value = valueHolder.get(); 

		// Add a parameter to the ParamArray with the appropriate value.
		params.addParameter(idx, value, param.getMode().getModeCode(),
			param.getDataType().getTypeCode(),
			param.getExtent(),
			(ProDataGraphMetaData) null);
		break;
}
</pre>
<p>The outer switch in this code handles the difference between TABLE, TABLE-HANDLE and other parameters. So skip the first cases and look at the default case (the last 11 lines of this code block from the word &quot;default:&quot; on.&nbsp;All this code does is grab the object that&nbsp;is in&nbsp;<em>ValueHolder</em> and&nbsp;assign it to the value variable. It then adds a parameter specifying the&nbsp;ordinal position (idx), the value, the&nbsp;parameter&nbsp;mode (INPUT, OUTPUT or&nbsp;INPUT-OUTPUT), the Progress DataType Code from the <em>DataType</em>, the extent and a null for the <em>ProDataGraphMetaData</em>.</p>
<p>The TABLE and TABLE-HANDLE&nbsp;cases are slightly more complicated. For a TABLE&nbsp;or TABLE-HANDLE if the parameter is either an INPUT or INPUT-OUTPUT parameter, the value has to be set to the <em>ProDataGraph</em> that will&nbsp;be&nbsp;used to contain the return value. The <em>ProDataGraphMetaData</em> needs to be specified to supply the table structure. In the case of an OUTPUT parameter, a TABLE parameter requires <em>ProDataGraphMetaData</em> but null in the value parameter and in the case of a TABLE-HANDLE, both the metadata and the value need to be null. In both cases, the <em>Parameter</em> object will have been specialized as a <em>TempTableParameter</em> object so that it could build the temp-table structure.</p>
<p>Once the parameters have all been added to the <em>ParamArray</em>, it is returned to the caller (executeCall) and is now ready to invoke the call.</p>
<h5>runProcedure()</h5>
<p>The <em>runProcedure()</em> method call is run on the <em>AppServerConnection</em> object that is contained in the <em>CallManager</em>. The AppServerConnection class performs 2 functions:</p>
<ol>
<li>It stores the AppServer connection parameter values; and</li>
<li>It executes calls against the AppServer.</li>
</ol>
<p>The first thing <em>runProcedure()</em> does is call <em>obtainAppObject()</em>. The <em>OpenAppObject </em>class provides access to AppServer connections from the connection pool and supports all communication with the AppServer. The <em>obtainAppObject()</em> call instantiates a <em>Connection</em> object and then an <em>OpenAppObject</em> if they have not already been instantiated. This establishes the connection to the AppServer.</p>
<p>Once the connection is established, the <em>runProc()</em> method on the <em>OpenAppObject</em> is run with the&nbsp;<em>ParamArray</em> that was passed in and any exceptions are thrown back to the caller.&nbsp;If this code completes successfully, the AppServer call has succeeded.</p>
<h5>buildOutputValues()</h5>
<p>After the call has completed, <em>executeCall()</em> calls <em>buildOutputValues() </em>with the <em>ParamArray</em> that was used&nbsp;in&nbsp;<em>runProcedure()</em>.&nbsp;</p>
<pre>//Extracted from <strong>buildOutputValues()</strong>
//
returnValue = params.getProcReturnString();
if (returnValue == null) {
	returnValue = &quot;null/Unknown (?)&quot;;
}
int idx = 0;
for (Parameter param : sig) { // Loop through each parameter in the signature.
	switch (param.getMode()) { // Check the parameter mode.
		case INPUT_OUTPUT:
		case OUTPUT:

			// Get the value of the parameter from the paramArray.
			Object outputValue = params.getOutputParameter(idx); 

			// Set the value of the parameter in our internal array to be the result
			paramValues.get(idx).setObject(outputValue);
	}
	idx++;
}</pre>
<p>The buildOutputValues() method&nbsp;does 2 things:</p>
<ol>
<li>It obtains the value of the RETURN-VALUE string from Progress; and</li>
<li>It loops through all OUTPUT or INPUT-OUTPUT parameters and sets the value in the <em>IValueHolder</em> from the value in the&nbsp;<em>ParamArray.</em></li>
</ol>
<p>The output parameter values are thus available to the <em>Call</em> object for serialization.&nbsp;</p>
<h4>Why this is so powerful&nbsp;</h4>
<p>That is the crux of the code in the Dynamic OpenClient Sample Utility. It&#39;s not really that complicated and although this is a crude example, it does show the relative ease with which one can build a&nbsp;client that invokes calls for which all signature information is obtained at runtime.</p>
<p>If you work through the associated document that contains a description of running the utility, you will notice how easy it is to edit the ABL code and change temp-table structures or any other signature related information, modify the corresponding signature in the XML file and re-run the utility without changing the Java code.</p>
<p>If you go ahead and automate the generation of the XML signatures into a post-compile operation and post it on a web-server or some other centralized resource, there is never a need to change the Java code unless you discover a bug in it or Progress adds a data type.</p>
<p>There&#39;s another interesting side effect to this. It would not take much effort beyond this to build an automated mechanism for dynamic WSDL generation so that you dynamically expose any ABL procedure as a WebService. Taking it further, exposing it as an EJB or J2EE container or a JMS endpoint would be fairly simple too and would mean very little would ever need to be changed in the plumbing between the client and the server. You see, as far as I am concerned, everything related to ProxyGen is plumbing that should never require a recompile unless the underpinnings change. ProxyGen forces that each time a temp-table definition is changed.</p>
<p>Hopefully this example is useful. I am planning a .NET equivalent later on.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.thesoftwaregorilla.com/2009/11/openedge-dynamic-openclient-java-example/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>OpenEdge Dynamic OpenClient</title>
		<link>http://www.thesoftwaregorilla.com/2009/07/openedge-dynamic-openclient/</link>
		<comments>http://www.thesoftwaregorilla.com/2009/07/openedge-dynamic-openclient/#comments</comments>
		<pubDate>Wed, 29 Jul 2009 20:06:47 +0000</pubDate>
		<dc:creator>Bruce Gruenbaum</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[OpenClient]]></category>
		<category><![CDATA[OpenEdge]]></category>
		<category><![CDATA[n-tier Development]]></category>
		<category><![CDATA[4GL]]></category>
		<category><![CDATA[ABL]]></category>
		<category><![CDATA[Application Server]]></category>
		<category><![CDATA[AppServer]]></category>
		<category><![CDATA[AVM]]></category>
		<category><![CDATA[Dynamic OpenClient]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Java OpenClient]]></category>
		<category><![CDATA[OpenEdge AppServer]]></category>
		<category><![CDATA[OpenEdge OpenClient]]></category>
		<category><![CDATA[Progress]]></category>
		<category><![CDATA[Progress AppServer]]></category>
		<category><![CDATA[Progress OpenClient]]></category>
		<category><![CDATA[PVM]]></category>

		<guid isPermaLink="false">http://www.thesoftwaregorilla.com/?p=75</guid>
		<description><![CDATA[In one of the more recent versions of OpenClient, the API that the OpenClient uses is documented so that it is now possible to dynamically construct the proxy calls at run-time. The overarching benefit in this lies in the ability to now define the temp-table definitions on the fly. The Java/.NET code can now define the temp-table dynamically at run-time so that if a change is made to the definition, the client can deal with the change with no impact on the OpenClient source code.]]></description>
			<content:encoded><![CDATA[<p>I forget how long ago it is that the OpenEdge OpenClient was released. It must be easily close on 10 years, but I am willing to accept that may be an exaggeration. OpenClient is a cool technology.&nbsp;&nbsp;For the&nbsp;uninitiated, the OpenClient is&nbsp;a very powerful&nbsp;library of&nbsp;code and&nbsp;a set of tools that allows&nbsp;.NET, Java and WebService access to the OpenEdge AppServer. It allows you to build&nbsp;your business logic in the OpenEdge ABL&nbsp;and access it from whatever client you choose.</p>
<p>In order for the OpenClient to be able to connect to the AppServer, make a call and return the output parameters, there is a&nbsp;certain amount of code that you need&nbsp;on the client (Java or .NET) that wraps the OpenClient library.&nbsp;In an effort to simplify the&nbsp;process of writing that code,&nbsp;OpenEdge includes&nbsp;a utility called &quot;ProxyGen&quot;&nbsp;that parses the OpenEdge ABL&nbsp;code and generates a&nbsp;proxy class&nbsp;that wraps all of the code needed and exposes it as a simple method call. Once you have generated the proxy, you simply include the generated class in your code (either as a .jar or a .NET assembly, or even directly as source code) and you can make whatever call you need.</p>
<p>The problem with ProxyGen is that you have to regenerate the proxy and potentially rebuild the client each time the ABL&nbsp;procedure changes its signature. That would be&nbsp;okay if the ProDataset and Temp-Table definitions were not part of the signature, but they are and adding a field to a temp-table should not cause a proxy to break.</p>
<p>&quot;Hang on, Bruce,&quot; I can hear you say, &quot;Why is the signature of the temp-table not a change to the signature to the API?&quot; I&#39;m not saying that it isn&#39;t, but I&nbsp;am saying that it is far more difficult to avoid making this mistake. Here&#39;s why:</p>
<p><img align="right" alt="Temp-Table Definitions being included in classes and procedures" height="193" src="http://www.thesoftwaregorilla.com/wp-content/uploads/2009/07/TempTableInclude.jpg" width="500" />Typically, temp-tables that form part of the in-memory data model are defined in include files and then used in procedures and classes as in the&nbsp;attached diagram.</p>
<p>Let&#39;s assume that Procedure1.p and Procedure2.p are deployed to the AppServer and that&nbsp;Procedure1.p accepts the temp-table as an input parameter and Procedure2.p uses it as an input-output parameter.</p>
<p>As a result of a necessary change to the in-memory data model, a field or two are added to&nbsp;the&nbsp;temp-table definition for the purposes of the Class1.cls and Class2.cls.&nbsp; As part of the build, the code is recompiled and the new code deployment to the AppServer is completed successfully. Note that there has been no planned change to the Procedure1.p and Procedure2.p.</p>
<p>The problem that we now face is that the proxies that were generated for the Procedure1.p and Procedure2.p are now invalid. The temp-table definition is no longer correct and a run-time&nbsp;error will now occur for the client when these procedures are called.</p>
<p>Another problem with proxies is the complexity associated with unit-testing and verifying each individual proxy. Each time a proxy is changed, each of the unit tests for each call in the proxy has to be rerun and retested. There is no way to generically test them to verify the Java/.NET code.</p>
<p>In one of the more recent versions of OpenClient, the API that the OpenClient uses is documented so that it is now possible to dynamically construct the proxy calls at run-time. The overarching benefit in this lies in the ability to now define the temp-table definitions on the fly. The Java/.NET code can now&nbsp;define the temp-table dynamically at run-time so that if a change is made to the definition, the client can deal with the change with no impact on the OpenClient source code.</p>
<p>This functionality is, in fact, so powerful that the entire signature, including all&nbsp;parameter definitions,&nbsp;can be discovered and defined at run-time.</p>
<p>This concept becomes even more interesting as you consider using it for WebServices. ProxyGen can generate the WSDL for a procedure that is to be exposed as a WebService, although it suffers from the same issues if the signature changes. The dynamic OpenClient API makes it possible to dynamically generate&nbsp;the WSDL at run-time from the procedure. Obviously there are overheads associated with auto-discovering a procedure&#39;s signature. It makes sense, therefore, to build out this functionality so that the signature discovery is done as seldom as possible.</p>
<p>In a future article I will provide some code samples that show you how to use the Dynamic OpenClient.</p>
<p><strong>UPDATE: </strong>I have subsequently made this code sample available. You can refer to it <a href="/2009/11/openedge-dynamic-openclient-java-example/">here</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.thesoftwaregorilla.com/2009/07/openedge-dynamic-openclient/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>OpenEdge AppServer &#8211; Exposing Progress OpenEdge</title>
		<link>http://www.thesoftwaregorilla.com/2009/04/openedge-appserver-exposing-progress-openedge/</link>
		<comments>http://www.thesoftwaregorilla.com/2009/04/openedge-appserver-exposing-progress-openedge/#comments</comments>
		<pubDate>Fri, 17 Apr 2009 00:00:35 +0000</pubDate>
		<dc:creator>Bruce Gruenbaum</dc:creator>
				<category><![CDATA[Commentary]]></category>
		<category><![CDATA[4GL]]></category>
		<category><![CDATA[ABL]]></category>
		<category><![CDATA[Application Server]]></category>
		<category><![CDATA[AppServer]]></category>
		<category><![CDATA[AVM]]></category>
		<category><![CDATA[Dynamic OpenClient]]></category>
		<category><![CDATA[Java OpenClient]]></category>
		<category><![CDATA[OpenEdge]]></category>
		<category><![CDATA[OpenEdge AppServer]]></category>
		<category><![CDATA[OpenEdge OpenClient]]></category>
		<category><![CDATA[Progress]]></category>
		<category><![CDATA[Progress AppServer]]></category>
		<category><![CDATA[Progress OpenClient]]></category>
		<category><![CDATA[PVM]]></category>

		<guid isPermaLink="false">http://www.intangere.com/tsg/?p=27</guid>
		<description><![CDATA[In 1999 Progress held a user conference in Boston where they showed the any-any-any model. Progress was going to become open. You could connect any client on any platform to any database using a Progress AppServer to handle your business logic. This was a really good idea. The preceding 10 years had taught me that Progress was an outstanding platform for writing the business logic that controlled your application and ensured your data integrity. I was sold. 
]]></description>
			<content:encoded><![CDATA[<p>The last 20 years of my life have ben spent working with <a href="http://www.progress.com/openedge" target="_blank">Progress Software</a> in one form or another. I started work with Progress (now OpenEdge)&nbsp;in 1989 in Progress version 4. I transitioned to it from MicroFocus COBOL after having cut my teeth programming in Basic and COBOL.</p>
<p>I was introduced to Progress while I was working for a small software house in South Africa, <a href="http://www.rdata.co.za/" target="_blank">R-Data</a>. R-Data had split from a company called Independent Software (no relationship to Independent Software in the USA as far as I know) and we re-developed the local government financial system in Progress to provide significantly greater functionality. When we finally rolled out the initial release of the product&nbsp;sometime in late 1990, we were using Progress version 6. I was involved in implementations of this system at several local governments throughout South Africa and also at the Ministry of Works in Malawi on a World Bank development project.</p>
<p>As I sit back and reflect on those days now, the thing that strikes me is that R-Data was based in Cape Town, several thousand miles from Malawi and a long way away from most of its South African customers. Despite this we were able to maintain these systems by means of 2400 baud modems with no on-site technical staff. Progress was just so solid and reliable that we had no problems with it.</p>
<p>Through the rest of the 1990s I&nbsp;did several consulting jobs&nbsp;using Progress and finally, in 1997, I&nbsp;went to work full time for a&nbsp;company that had an interesting&nbsp;problem to deal with. They had satellite offices all&nbsp;around South Africa and a centralized data&nbsp;center. The best&nbsp;network connection&nbsp;they&nbsp;could get for the remote offices&nbsp;was a 64K&nbsp;diginet line. Progress, now in version 8, had released the first version of the Progress AppServer. We decided to see if we could improve the application&#39;s performance using the AppServer. After some work re-architecting the way that we called procedures from the application, we rolled out the changes using the AppServer in late 1997.</p>
<p>I remember getting a phone call from one of the users the next morning. She had just&nbsp;performed an operation that had previously had a 30 &#8211; 45 second latency and was convinced something was wrong because the operation completed in less than a second. That has to be one of my favorite triumphs. The lady was ecstatic when I told her that I had fixed the problem she had been complaining about. The company that I was working for was able to save itself the cost of upgrading its diginet lines &#8211; at that time a very expensive operation in South Africa.</p>
<p>In 1998 I presented our experience at a Progress User Conference in London. Progress released version 9 shortly thereafter and I very quickly realized that the AppServer could be used in conjunction with Java. In 1999 Progress held a user conference in Boston where they showed the any-any-any model. Progress was going to become open. You could connect any client on any platform to any database using a Progress AppServer to handle your business logic. This was a really good idea. The preceding 10 years had taught me that Progress was an outstanding platform for writing the business logic that controlled your application and ensured your data integrity. I was sold.&nbsp;</p>
<p>Then I was offered a job at Progress Software Corporation in the United States and my family and I moved to the US&nbsp;at the end of 1999. The AppServer and its future seemed to be something that I was going to be tied to.</p>
<p>Within 2 weeks of moving to the US, I went to the VP of development at Progress and told him that I believed Progress needed to forget about its focus on the client and concentrate on improving and growing the AppServer that could be used to build the best business applications in the world. Progress needed to provide tools and support to help Java and (then) VB developers to build applications based on the&nbsp;OpenEdge AppServer. I was shot down in flames. Who was this upstart anyway?</p>
<p>Over the next 7 years I worked at Progress on several efforts in their tools development group to help improve the process of building strong business applications. A framework called Progress Dynamics was released. While it held great promise on the business side, the user interface was based on Progress and was clunky. The ideas were revolutionary &#8211; store the UI definition in a repository and you could render it for any platform &#8211; client-server, the web, a mobile device, etc. Unfortunately the product was not well marketed and explained. Initial releases had significant performance problems that were improved later, but it tried to do too much. I still believe that Dynamics had a strong potential future, but it needed better vision to see it through.</p>
<p>Of course, Dynamics was not the only initiative. Progress then decided to use Eclipse to build their equivalent of the JDT &#8211; the PDT &#8211; for developing Progress applications. The PDT was (and is) sold as OpenEdge Architect and while it does a good job of helping you build&nbsp;Progress code, it&nbsp;does little or nothing to help you build applications that use the AppServer.</p>
<p>Eclipse has recognized that the JDT is not enough for Java.&nbsp;You need&nbsp;an&nbsp;Eclipse for Java EE to&nbsp;build&nbsp;enterprise class&nbsp;applications and in the same way that Java EE provides&nbsp;Glassfish as its application server, so the Progress AppServer&nbsp;needs its own set of tools around it so that application development against an AppServer is not that complex.</p>
<p>In&nbsp;2006 Progress embarked on a project to&nbsp;integrate the .NET user interface into the Progress&nbsp;execution&nbsp;environment to provide an improved user interface for Progress.&nbsp;Progress would host the .NET CLR and the user interface would be able to interact directly with Progress objects. At the user conference later that&nbsp;year I presented a preview of what were looking to build in conjunction with&nbsp;the lead architect on the project &#8211; a lady for whom I have&nbsp;immense respect.</p>
<p>The problem, though, with&nbsp;hosting the CLR&nbsp;is that Progress takes on the responsibility of keeping up with what Microsoft is doing and it ties itself to Microsoft platforms.&nbsp;Moreover, no matter how much Progress tries to hide the internals of&nbsp;.NET from its customers, exposing the&nbsp;.NET UI forces those&nbsp;customers to learn something about .NET and its control mechanism.</p>
<p>Progress does not have the budget to spend on UI development that Microsoft does. It&nbsp;does not have the&nbsp;open source community to build out the&nbsp;Rich Client&nbsp;Platform the way that Eclipse does. It also does not have the&nbsp;authority to drive the&nbsp;industry&#39;s UI direction that either Java&nbsp;or .NET do.&nbsp;At the time that I&nbsp;became involved in the .NET integration project, I was of the opinion that Progress should concentrate its resources on exposing the business logic&nbsp;components to Microsoft and Java objects inside the Progress execution environment and&nbsp;let developers choose which of these it wanted to use to&nbsp;build the front-ends to their&nbsp;applications. Ideally, a set of extensions to the Progress OpenClient that would allow easier AppServer-based development.</p>
<p>In terms of development effort from Progress&#39; point of view, the&nbsp;OpenEdge AppServer is all but forgotten. Like WebSpeed before it, Progress&nbsp;has done little to improve and enhance this product so that it can be used in&nbsp;a large, scalable&nbsp;environment. There has been&nbsp;little done&nbsp;to its basic functionality since&nbsp;the&nbsp;last major changes&nbsp;to support a state-free operating mode for WebServices and I believe the release of that was in around 2004.</p>
<p>After I left Progress in July 2006, I joined a company that is using the OpenEdge AppServer in a reasonable sized configuration. I would not call it a big installation, but it is big enough to demonstrate the successes and flaws of the OpenEdge AppServer. In this environment I was forced to contend with communication with the AppServer from a Progress, Java and .NET source.&nbsp;I have learned a lot about the&nbsp;OpenEdge AppServer in this process.</p>
<p>Although the technology is maligned by many for its lack of scalability, I have found that it provides&nbsp;acceptable&nbsp;performance if the application is properly designed to leverage the AppServer. It also provides a very simple way to expose Progress code to&nbsp;other technologies and the communication between Java&nbsp;or .NET and the AppServer&nbsp;is solid &#8211; solid enough to build&nbsp; a commercial application with.&nbsp;</p>
<p>In one of the&nbsp;later versions of OpenEdge 10 (I believe&nbsp;it was 10.0B ), Progress introduced the dynamic OpenClient which does away with the need for a&nbsp;tool called&nbsp;&quot;Proxygen&quot;. Proxygen requires the generation of a Java/.NET class that&nbsp;is incorporated into your Java/.NET code as a library in order to access the remote 4GL/ABL procedure. With the dynamic OpenClient this is no longer necessary and if you build a truly dynamic client, the AppServer becomes an easily accessible tool for deploying business applications.</p>
<p>As a result of the dynamic OpenClient, I am now able to make use of the&nbsp;OpenEdge AppServer and can&nbsp;expose it to Java, .NET, JSP, ASP.NET,&nbsp;&nbsp;OpenESB and&nbsp;PHP. These are just the technologies that I am using right now. Moreover, I can get at the&nbsp;OpenEdge AppServer from Eclipse, Eclipse RCP applications, Eclipse eRCP and Eclipse RAP. This gives me the portability to move my user interface to&nbsp;virtually any modern&nbsp;desktop and I can&nbsp;avoid having to&nbsp;be tied into Microsoft Vista. Heck, one of the&nbsp;applications I have built runs on my Mac.&nbsp;</p>
<p>What&#39;s interesting is that the tools that I have built for myself to be able to do this have ended up being plugins to Eclipse or add-ins to Visual Studio. There are not a lot of them, but they greatly simplify my ability to build applications based on the Progress AppServer &#8211; the technology that Progress saw as its strategic direction in 1999.</p>
<p>Ten years later, it seems that Progress has never realized that vision.&nbsp;The thing that Progress developers need to do is build better business applications. Their&nbsp;focus&nbsp;is the business logic. The business logic runs&nbsp;on an AppServer. Developing, testing and deploying&nbsp;code&nbsp;for the AppServer is still really hard for&nbsp;a Progress developer to do &#8211; much harder than it is for a Java developer building business logic to run on Glassfish.&nbsp;True, any client on any platform can talk to any database&nbsp;through the Progress AppServer, but the technology to do it is still in its infancy ten years later.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.thesoftwaregorilla.com/2009/04/openedge-appserver-exposing-progress-openedge/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
