How to export all mapped environments from Natural Studio (SPoD)

A colleague of mine wanted to export all the mapped environments from Natural Studio (SPoD). As we have quite a lot of different environments due to our complex staging concept, manually re-creating this list would be cumbersome.

Map an environment in Natural Studio

Long story short: we didn’t find a way to export the environments from within Natural Studio. However, after a quick search I found this file: %PROGRAMDATA%\Software AG\Natural\6.3\Prof\%USERNAME%.PRU (which translates to C:\ProgramData\Software AG\Natural\6.3\Prof\MACKE.PRU in my case). It contains all the mapped environments in a text format:

Mapping2 = MAP THEHOST 2720 ALIAS=My environment; MACKE * * fuser=(22,123) ;CONNECTED=FALSE

Here’s a quick regular expression to filter the needed parts from the string:

MAP (.+) ([0-9]+) ALIAS=([^;]+); ([^ ]+) \* \* ([^;]*);.*
  • Group 1: Host name (THEHOST)
  • Group 2: Server port (2720)
  • Group 3: Environment name (My environment)
  • Group 4: User ID (MACKE)
  • Group 5: Session parameter (fuser=(22,123))

How to configure a URL Alias for a REST Resource in webMethods Integration Server

After I created my first REST Resource in webMethods Integration Server, I immediately saw potential for improvement regarding the URL under which it was made accessible:

http://localhost:5555/rest/ExamplePackage/Resources/Session

The default URL always starts with rest followed by the fully qualified name of the REST Resource. What bugs me is the latter: the path exposes the internal package structure to the outside. And if – for whatever reason – we decide to change this structure later, all clients need to be changed accordingly. And due to REST’s loose coupling you may not be aware of all consumers of your service and only find out late in the process that you missed to update a caller.

So, what we want is a logical URL instead of a physical one that represents our package structure, e.g.:

http://localhost:5555/User/Session

This logical URL should never change due to an internal restructuring.

URL Aliases

Integration Server provides an easy way of creating such logical URLs: URL Aliases.

You can find the dialog for creating URL Aliases in Integration Server’s web interface under Settings -> URL Aliases:

Creating a URL Alias in webMethods Integration Server

  • Alias
    This is the logical URL you want to define for your REST resource, e.g. User/Session.
  • URL Path
    The Alias above gets expanded to this fully qualified path, e.g. rest/ExamplePackage/Resources/Session.
  • Package
    The Alias will be saved to this package. It resides in an XML file called config/urlalias.cnf in the package’s folder in the file system and can be versioned along with the rest of the package’s contents.

Now I can call the REST Resource via the URL Alias:

curl^
      -u Administrator:manage^
      -X POST^
      -H "Accept: application/json"^
      -H "Content-Type: application/json"^
      -d "{\"Username\":\"Stefan\",\"Password\":\"secr23et\"}"^
      http://localhost:5555/User/Session

Calling a REST Resource via a URL Alias in webMethods Integration Server

Partial Matching

As stated in the REST Developer’s Guide, you may need to activate Partial Matching for your URL Aliases to work. See Integration Server Administrator’s Guide for details.

All you need to do is add this Extended Setting and restart IS:

watt.server.url.alias.partialMatching=true

How to create a REST service in webMethods Integration Server

A while ago I created my first REST service in webMethods Integration Server. It’s quite easy to do and works correctly out of the box. Software AG managed to implement the standards quite well and I didn’t have to go through hours of configuring (like I had to with SOAP webservices).

How to create a REST service in webMethods Integration Server

First of all, you don’t actually create a REST service, but a REST resource. A resource represents a business entity for wich you can call the basic CRUD operations through (multiple) services, that respond to the common HTTP methods (GET, POST, PUT, DELETE). So, a REST resource uses multiple Flow services that implement the logic. These services get called automatically by IS, when the corresponding HTTP call is made by the client.

My example implements a common scenario: Authenticating a user based on its username and password.

The first – and most important – question was, how to name the REST resource. I couldn’t name it User, as one might think at first, because this name doesn’t fit the notion of REST: I don’t create or read a user. The user already has to be there and simply gets authenticated. In a SOAP context I would create a Flow service like AuthenticateUser with Username and Password as parameters. But in REST we can only use the basic CRUD operations. And there is no HTTP method called AUTHENTICATE. So I had to find another name for the resource.

What I ended up with was the concept of a Session. When a user gets authenticated, a Session is created for him. When he logs off, the Session gets destroyed. I can also read the Session to find out, whether the user is already logged in. So it all seemed to make sense now.

After the nomenclature problem is solved, here’s a quick step-by-step guide on how I implemented the REST resource in IS.

Step-by-step guide

  • Create a Flow service that implements the logic you need.
    In my case, I created AuthenticateUser as described above (see Best practices for structuring packages in webMethods Integration Server for details on the package’s folder structure).
    Flow service AuthenticateUser
    As the REST resource is merely an additional access layer on top of existing logic (like a Web Service Descriptor), it’s good practice to keep the two concerns – business logic and access logic – separated. Another advantage of this approach is the fact, that you can simply re-use your existing Flow services and only have to add the REST part on top of it.
  • Make sure the Flow service works as expected.
    This step might seem obvious, but if you introduce another layer of complexity in your system, you better make sure the underlying parts already work correctly. Otherwise, the search for potential errors might take very long and you can’t be sure, if it’s really the REST part that goes wrong.
    Successful result of a call to AuthenticateUser
  • Create a REST Resource.
    This is a easy as selecting New -> REST Resource from Designer’s context menu, giving the resource a name and selecting the needed HTTP methods.
    Creating a REST Resource in webMethods Integration Server - Step 1
    Creating a REST Resource in webMethods Integration Server - Step 2
    Here, I used POST, because I want to create a new user session. If you are not exactly sure, which HTTP methods to use, here’s a quick mapping: GET -> read, POST -> create, PUT -> update, DELETE -> delete. Also see Using HTTP Methods for RESTful Services and When should we use PUT and when should we use POST?.
    Creating a REST Resource in webMethods Integration Server - Step 3
    Voilá, we created our first “REST Service”! 🙂
    Creating a REST Resource in webMethods Integration Server - Step 4
  • Define the parameters for the REST services.
    The newly created service _post has no parameters yet (aside from two technical parameters $resourceID and $path, see REST Developer’s Guide for an explanation of those). So you need to add them.
    Adding paramters to the REST service
    In my case, I simply used the same parameters from AuthenticateUser. But they also can be different.
  • Implement the REST service.
    Implementing the _post service is quite simple, because the main logic is already implemented in AuthenticateUser. Therefore, _post can simply call AuthenticateUser and only needs to take care of REST specialties, like setting a meaningful response code. Otherwise, IS returns 200 (see List of HTTP status codes for additional information) even if the authentication was not successful. Fortunately, there is an HTTP code that describes almost exactly what I need: 401 Unauthorized. You can set the response code with the IS service pub.flow:setResponseCode.
    Implementation of the _post service
  • Test the REST service.
    You can now call the _post service directly from Designer and make sure it works.
    Call _post
    Successful response from _post
    Unsuccessful response from _post
  • Test the REST service from outside IS.
    After you made sure, that the _post service works as expected, you can try and call it from outside IS. My tool of choice for this task is curl (which comes with the installation of Git for Windows, by the way). All REST resources are available in IS under the following URL without any further configuration:

    http://server:port/rest/FullyQualifiedResource
    

    Or translated to my example:

    http://localhost:5555/rest/ExamplePackage/Resources/Session
    

    You can call the REST service with this curl command on Windows (on Linux you need to replace ^ with \, see Windows: How to specify multiline command on command prompt?):

    curl^
      -u Administrator:manage^
      -X POST^
      -H "Accept: application/json"^
      -H "Content-Type: application/json"^
      -d "{\"Username\":\"Stefan\",\"Password\":\"secret\"}"^
      http://localhost:5555/rest/ExamplePackage/Resources/Session
    

    IS automatically unwraps the JSON payload and converts it to IS documents. You only need to provide the same document structure and field names as defined in your _post parameters.
    Result of curl call to _post service
    By the way: I had to use double quotes for the JSON payload and needed to escape the quotes inside the JSON data to make it work on Windows. When I used single quotes (e.g. -d '{"Username":"Stefan","Password":"secret"}'), I got this nice error:

    org.codehaus.jackson.JsonParseException:Unexpected character (''' (code 39)): expected a valid value (number, String, array, object, 'true', 'false' or 'null')\n at [Source: com.wm.net.HttpInputStream@74356f93; line: 1, column: 2]
    

And this leaves you with a fully functional REST service in webMethods Integration Server! 🙂

Official Documentation

These documents helped me along the way:

Recommended reading

For a very good introduction to REST I recommend the Pluralsight course REST Fundamentals:


REST Fundamentals – $29.00

REST is an overloaded, and thus misunderstood term in architectural circles these days. This course attempts to clear up some of the misunderstandings about REST as well as provide a more practical approach for designing RESTful solutions – both clients and services. Additionally, the course looks at REST from the perspective of the cloud and describes how REST is well-suited to meet the demands that the cloud brings to bear on a modern architecture.