0
Webspeed setup on Tomcat
by Riverside Software
The latest versions of OpenEdge allow simple serialization of temp-tables and prodatasets to JSON, and in this context, Webspeed may become more and more popular as it can serve the JSON result directly, without having to rely on Java/ASP/Whatever.
As I'm mainly working with Java, I always have a servlet container ready to run. But the Progress documentation doesn't mention Tomcat as a deployment plaftorm ; here is this guide !
The content of this file is :
This URL assumes that you're running with the default Webspeed broker wsbroker1.
As I'm mainly working with Java, I always have a servlet container ready to run. But the Progress documentation doesn't mention Tomcat as a deployment plaftorm ; here is this guide !
Step 1 : Download Tomcat
This guide is for Tomcat 6, but any other version should work. So grab Tomcat from http://tomcat.apache.org/download-60.cgi and install it (for the Windows installer version) or extract it (for the standalone ZIP file).
In this documentation, $CATALINA_HOME will represent the installation path.
Step 2 : create a new webapp
Create a new directory in $CATALINA_HOME/webapps. This directory has to called webspeed followed by the version number, i.e. if you're running OpenEdge 11.0, the directory will be $CATALINA_HOME/webapps/webspeed110.
In this documentation, $WEBAPP will represent this directory
In this directory, create a subdirectory WEB-INF (case-sensitive).
Step 3 : copy static files
Copy the content of $DLC/webspeed to $WEBAPP, then copy $DLC/bin/cgiip.exe to $WEBAPP/WEB-INF/cgi (create a subdirectory for it).
Step 4 : create web.xml
The file web.xml is the webapp description file :
<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
<servlet>
<servlet-name>cgi</servlet-name>
<servlet-class>org.apache.catalina.servlets.CGIServlet</servlet-class>
<init-param>
<param-name>debug</param-name>
<param-value>0</param-value>
</init-param>
<init-param>
<param-name>cgiPathPrefix</param-name>
<param-value>WEB-INF/cgi</param-value>
</init-param>
<init-param>
<param-name>executable</param-name>
<param-value></param-value>
</init-param>
<init-param>
<param-name>passShellEnvironment</param-name>
<param-value>true</param-value>
</init-param>
<load-on-startup>4</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>cgi</servlet-name>
<url-pattern>/cgi/*</url-pattern>
</servlet-mapping>
</web-app>
Step 5 : privileged application
Create an XML file in $CATALINA_HOME/conf/Catalina/localhost, with the same name as the webapp directory : if you created in step 2 a directory called webspeed110, then create webspeed110.xml.The content of this file is :
<Context privileged="true" />
Step 6 : configure your webspeed broker
This is OpenEdge configuration, and it won't be covered here...Step 7 : play !
Start Tomcat, and go to http://localhost:8080/webspeed110/cgi/cgiip.exe/WService=wsbroker1/workshopThis URL assumes that you're running with the default Webspeed broker wsbroker1.
Bonus step 1 : URL rewriting
Using URL like /webspeed110/cgi/cgiip.exe/WService=wsbroker1/programName can be dangerous, as it gives users the knowledge that CGI is being used and active, allows anybody to change the broker name, and so on...
A Tomcat filter is already available to rewrite URL, available here.
To setup this filter, you'll need to create a new directory $WEBAPP/WEB-INF/lib and drop this JAR file.
Update your web.xml file to declare this filter :
<filter>
<filter-name>UrlRewriteFilter</filter-name>
<filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilter</filter-class>
<init-param>
<param-name>confReloadCheckInterval</param-name>
<param-value>0</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>UrlRewriteFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
Then create a file urlrewrite.xml in $WEBAPP/WEB-INF, with this content :
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE urlrewrite PUBLIC "-//tuckey.org//DTD UrlRewrite 3.2//EN"
"http://tuckey.org/res/dtds/urlrewrite3.2.dtd">
<urlrewrite>
<rule>
<from>/cgiip/(.*)</from>
<to>/cgi/cgiip.exe/WService=wsbroker1/$1</to>
</rule>
<!-- default rules included with urlrewrite -->
<rule>
<note>
The rule means that requests to /test/status/ will be redirected to /rewrite-status
the url will be rewritten.
</note>
<from>/test/status/</from>
<to type="redirect">%{context-path}/rewrite-status</to>
</rule>
<outbound-rule>
<note>
The outbound-rule specifies that when response.encodeURL is called (if you are using JSTL c:url)
the url /rewrite-status will be rewritten to /test/status/.
The above rule and this outbound-rule means that end users should never see the
url /rewrite-status only /test/status/ both in thier location bar and in hyperlinks
in your pages.
</note>
<from>/rewrite-status</from>
<to>/test/status/</to>
</outbound-rule>
</urlrewrite>
Restart Tomcat, and then you'll be able to access the workshop at http://localhost:8080/webspeed110/cgiip/workshop
Bonus step 2 : cgi.bat (and a reminder for myself)
<?xml version="1.0" encoding="ISO-8859-1"?> <web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5"> <servlet> <servlet-name>cgi</servlet-name> <servlet-class>org.apache.catalina.servlets.CGIServlet</servlet-class> <init-param> <param-name>debug</param-name> <param-value>0</param-value> </init-param> <init-param> <param-name>cgiPathPrefix</param-name> <param-value>WEB-INF/cgi</param-value> </init-param> <init-param> <param-name>executable</param-name> <param-value>c:\windows\system32\cmd.exe</param-value> </init-param> <init-param> <param-name>executable-arg-1</param-name> <param-value>/c</param-value> </init-param> <init-param> <param-name>passShellEnvironment</param-name> <param-value>true</param-value> </init-param> <load-on-startup>4</load-on-startup> </servlet> <servlet-mapping> <servlet-name>cgi</servlet-name> <url-pattern>/cgi/*</url-pattern> </servlet-mapping> </web-app>
With cgi.bat like that :
@echo off set DLC=C:\Progress\OPENED~1.5 set PROMSGS=%DLC%\promsgs set WRKDIR=%TEMP% REM 3055 is default port of wsbroker1 %DLC%\bin\cgiip.exe localhost 3055
PUG Challenge 2011 - Amsterdam
by Riverside Software
First of all, many thanks to the PUG committee for setting up such a great event.
Here are my presentations about continuous integration and deployment to vmware/EC2.
Here are my presentations about continuous integration and deployment to vmware/EC2.
Progress Revolution
by Riverside Software
I'm currently attending Progress Revolution in Boston, and waiting for the first session to start ! People who want to discover continuous integration and deployment automation should really attend Mr Preece session "A 21st century revolution in development methods" today afternoon. I'll attend this session and will be available with Brian Preece to answer questions.
PUG UK & Ireland - Spring conference
by Riverside Software
For those who were not able to attend my session at the latest PUG Challenge, I'll do it again in Birmingham on Wednesday 23rd March 2011. As a reminder, my session is about build automation and continuous integration in an OpenEdge environment. Target audience is mainly developers and architects, but managers willing to know how to keep developers working on real code and not on useless things should attend this session !
PUG UK & Ireland - Spring conference
PUG UK & Ireland - Spring conference
PCT 0.18 is released
by Riverside Software
A regression was introduced in 0.17, released a few days ago ; incremental dumps were only working on 10.2A+. A bug fix release (named 0.18, but could have been named 0.17.1) was released yesterday. Download it from Google code !
Return values, exceptions and error status shouldn't be left unread...
by Riverside Software
I just lost three hours. Not really the end of the world, but really annoying when you find it was a stupid mistake, combined with badly written code.
I was working on an enhancement for PCT, allowing database connections to be made either with the standard dbName/dbDir/hostName/portNumber attributes, or with just a paramFile attribute. Just a few lines of code to change so that aliases are not broken, a few new test cases, done in half an hour, everything's working. In fact, no, database connections are done differently with background compilations. Spent two minutes correcting this mistake, copied/pasted test case for this task, and boom... Ran tests again, it works... Ran again, boom...
Test cases working half the time when you're working with thread and forked processes communicating with a main server usually mean that you're running into synchronization issues. Just in case, I take "Java concurrency in practice" from my bookshelf, ready to debug this problem. Adding some debug messages in OpenEdge sessions, trying different combinations, re-doing a complete schema of this inter-process and inter-thread communication, I'm unable to find the cause of the problem.
Until I find the "Ha ha" ! My test case is creating a Progress database, and two spawned sessions are compiling programs. But I'm running those sessions with single user connections. And there's NO ERROR HANDLING FOR CONNECTION FAILURES !!! So depending on the mood of my computer, compilation was sometimes done by the first thread, and sometimes by the second thread. No problem for the first thread, DB connection was OK, but the second thread was never able to connect the database (and so compile programs). But I never got a warning or error message saying that it wasn't able to connect...
Result : just lost time, and I have to modify error handling so that DB connections are gracefully handled. Connection failure was handled in OpenEdge, pushed back to the first OpenEdge procedure, pushed back to the Java thread, and there it was dropped silently.
Error status and exceptions are not there to bother the programmer, it's just that something is wrong. So unless you're absolutely sure that you want to skip this error (and you should document that in your code), just let the exception bubble up (with a RuntimeException if possible in Java) or don't use NO-ERROR in Progress if you don't know what to do with it.
I was working on an enhancement for PCT, allowing database connections to be made either with the standard dbName/dbDir/hostName/portNumber attributes, or with just a paramFile attribute. Just a few lines of code to change so that aliases are not broken, a few new test cases, done in half an hour, everything's working. In fact, no, database connections are done differently with background compilations. Spent two minutes correcting this mistake, copied/pasted test case for this task, and boom... Ran tests again, it works... Ran again, boom...
Test cases working half the time when you're working with thread and forked processes communicating with a main server usually mean that you're running into synchronization issues. Just in case, I take "Java concurrency in practice" from my bookshelf, ready to debug this problem. Adding some debug messages in OpenEdge sessions, trying different combinations, re-doing a complete schema of this inter-process and inter-thread communication, I'm unable to find the cause of the problem.
Until I find the "Ha ha" ! My test case is creating a Progress database, and two spawned sessions are compiling programs. But I'm running those sessions with single user connections. And there's NO ERROR HANDLING FOR CONNECTION FAILURES !!! So depending on the mood of my computer, compilation was sometimes done by the first thread, and sometimes by the second thread. No problem for the first thread, DB connection was OK, but the second thread was never able to connect the database (and so compile programs). But I never got a warning or error message saying that it wasn't able to connect...
Result : just lost time, and I have to modify error handling so that DB connections are gracefully handled. Connection failure was handled in OpenEdge, pushed back to the first OpenEdge procedure, pushed back to the Java thread, and there it was dropped silently.
Error status and exceptions are not there to bother the programmer, it's just that something is wrong. So unless you're absolutely sure that you want to skip this error (and you should document that in your code), just let the exception bubble up (with a RuntimeException if possible in Java) or don't use NO-ERROR in Progress if you don't know what to do with it.
Quick and easy setup of Mercurial server on Windows
by Riverside Software
Installing Mercurial on a Linux server is a matter of minutes (depending on your Linux distro). But I had to install it on a Windows server, and there are subtle pitfalls you're likely to encounter when doing that. This post is by no mean a full and detailed installation process for every configuration, it will just focus on a simple install.
Step 1 : HTTPD install
HTTPD is one of the widely used HTTP server. The Windows version can be downloaded from here. I'm using the 2.2.17 Win32 Binary including OpenSSL 0.9.8o. Choosing a typical install will use C:\Program Files (x86)\Apache Software Foundation\Apache2.2 as the default directory. The only specific step during install is this screen :
Just fill with appropriate values depending on your network.
Step 2 : Python install
Python is needed by Mercurial. You always have to use the same Python version as the one used by Mercurial. The current Mercurial version (1.7.5) is still using 2.6, so download this version from Python website. Even if you're running Win x64, download the x86 version as I encountered some bugs with the 64 bits package (no idea why). Use the default settings for everything (especially installation directory).
Step 3 : Mercurial install
Mercurial compiled for Windows can be downloaded from here. Never use TortoiseHg to setup a Mercurial server, it won't work correctly (and easily). Always download *.win32-py2.6.exe packages, they're easier to setup.
Setup should detect your Python version and so compile Mercurial with Python 2.6.
Step 4 : Create directory structure
This test installation will use 3 differents directories to host repositories. We will use subfolders of C:\Repositories , named /Production, /QA and /Dev
We will keep them empty for now, just create this structure.
Step 5 : HTTPD setup
Create a new file called hgweb.cgi in C:\Program Files (x86)\Apache Software Foundation\Apache2.2\cgi-bin with this content :
Don't forget to restart HTTPD.
Step 6 : Test !
Open your web browser at http://localhost/hg and voilĂ ! You should have this page :
Step 7 : Enjoy
You can now import/clone your repositories
Step 1 : HTTPD install
HTTPD is one of the widely used HTTP server. The Windows version can be downloaded from here. I'm using the 2.2.17 Win32 Binary including OpenSSL 0.9.8o. Choosing a typical install will use C:\Program Files (x86)\Apache Software Foundation\Apache2.2 as the default directory. The only specific step during install is this screen :
Just fill with appropriate values depending on your network.
Step 2 : Python install
Python is needed by Mercurial. You always have to use the same Python version as the one used by Mercurial. The current Mercurial version (1.7.5) is still using 2.6, so download this version from Python website. Even if you're running Win x64, download the x86 version as I encountered some bugs with the 64 bits package (no idea why). Use the default settings for everything (especially installation directory).
Step 3 : Mercurial install
Mercurial compiled for Windows can be downloaded from here. Never use TortoiseHg to setup a Mercurial server, it won't work correctly (and easily). Always download *.win32-py2.6.exe packages, they're easier to setup.
Setup should detect your Python version and so compile Mercurial with Python 2.6.
Step 4 : Create directory structure
This test installation will use 3 differents directories to host repositories. We will use subfolders of C:\Repositories , named /Production, /QA and /Dev
We will keep them empty for now, just create this structure.
Step 5 : HTTPD setup
Create a new file called hgweb.cgi in C:\Program Files (x86)\Apache Software Foundation\Apache2.2\cgi-bin with this content :
#!C:/Python26/python.exe -u
# See also http://mercurial.selenic.com/wiki/PublishingRepositories
# Path to repo or hgweb config to serve (see 'hg help hgweb')
config = "C:/Program Files (x86)/Apache Software Foundation/Apache2.2/cgi-bin/hgweb.config"
# Uncomment and adjust if Mercurial is not installed system-wide:
# import sys; sys.path.insert(0, "SomeDirectory")
# Uncomment to send python tracebacks to the browser if an error occurs:
import cgitb; cgitb.enable()
from mercurial import demandimport; demandimport.enable()
from mercurial.hgweb import hgweb, wsgicgi
application = hgweb(config)
wsgicgi.launch(application)
Create a new file called hgweb.config in C:\Program Files (x86)\Apache Software Foundation\Apache2.2\cgi-bin with this content :
Add this line in C:\Program Files (x86)\Apache Software Foundation\Apache2.2\conf\httpd.conf in the <IfModule alias_module=""> section :[paths]/Production = C:/Repositories/Production/*/QA = C:/Repositories/QA/*/Dev = C:/Repositories/Dev/*[web]allow_push = *style = monobluecontact = mercurial@riverside-software.frpush_ssl = false
This line allows HTTPD to map the /hg query directly to Mercurial (instead of calling /cgi-bin/hgweb.cgi).ScriptAlias /hg "C:/Program Files (x86)/Apache Software Foundation/Apache2.2/cgi-bin/hgweb.cgi
Don't forget to restart HTTPD.
Step 6 : Test !
Open your web browser at http://localhost/hg and voilĂ ! You should have this page :
Step 7 : Enjoy
You can now import/clone your repositories
PCT 0.17 is released
by Riverside Software
I just released a new version of PCT. Almost 16 months after 0.16, it was time to have another standard release, as continuous integration is not something you can rely on in the long term.
Download it from here !
Included is the changelog :
Download it from here !
Included is the changelog :
* Several improvements on PLReader. Still one bug remaining when extracting adecomm.pl
* Removed PLExtract task, in favor of PLFileSet type which can be nested in any FileSet capable task
Only in read tasks, PCTLibrary still needs to be used when creating libraries
* Replaced CRCDifferent with RCodeSelector. Now able to use MD5 to compare r-code
* Another bug when XREF when importing XREF on classes
Bug reported by Sascha Hofmann
* Added environment variables to PCT tasks
* If dlcHome attribute isn't set, try to use DLC property then DLC environment variable
* PCTConnection was not allowing user name with no password
Enhancement by Sascha Hofmann
* Upgrading to ANT 1.8
Edit : To 1.8.1
Edit : To 1.8.2
* Changed the way $DLC/version is parsed
Thanks to Matt Baker for reporting bug and additional infos
* Adding languages and textSegGrowth attributes to PCTCompile and PCTCompileExt tasks
* Corrected warning message when compiling classes
* antlib.xml for pct namespace was not included in JAR file
* Updated documentation for pct namespace
* Changed setPropath to addPropath in PCTRun, so that multiple propath definitions can be combined
* Cleanup when tasks create a new subtask instance. Fixed a bug when using pct namespace
* GC Bug #1 : upgraded pct/_dmpincr.p to 10.2B
* Added PCTVersion task
* If pctX.pl is not available for your version of Progress, fall back to source code
Compilation licence required in this case.
* Reads PCT-SRC property from the command line, to force source code instead of compiled version
* GC Bug #2 : more detailed error messages during connection (patch by Dan Dragut)
PUG Challenge 2010
by Riverside Software
Here is my presentation (From build automation to continuous integration) during PUG Challenge in November 2010.


