Your first SMODL-application

This tutorial shows how to use Smodl Development Suite to create a SMODL application implementing standard CRUD (Create-Retrieve-Update-Delete) functionality. It describes and explains features of SMODL and Smodl Development Suite, as well as demonstrating the smooth integration with Eclipse.

The tutorial takes a so-called "contract-first" approach where you develop and work with a model and code is automatically generated from the model by tools. Changes are applied to the model and tools re-generate the relevant code. This is different from the so-called "contract-last" approach where code is written and maintained, and a model is derived from the code1. Both approaches are in fact supported by Smodl Development Suite, but this tutorial follows the first. Please refer to this document for how to use  Smodl Development Suite in a "contract-last" approach.

Software Requirements

To use Smodl Development Suite you neeed the following (refer to test matrix in release notes for details):

* – SOAP support requires JDK 1.4 which is endorsed with JAXP 1.3. However, SOAP support is beyond the scope of this tutorial.

Please refer to Eclipse tutorials at http://www.eclipse.org for details about how to use Eclipse in general and for downloading a copy of Eclipse (if you have not already done so). Screenshots in this document are from Eclipse SDK version 3.4.1 "Ganymede".

Visit this page for instructions of how to install Smodl Development Suite. Screenshots in this tutorial may be taken from slightly different versions of Smodl Development Suite but should all be relevant for the latest version. If this is not the case, please contact us and let us know!

  1. Create a new project and enable SMODL

    Create a new Java-project, and make sure to add “src” to the list of source-folders for the project. Right-click on the newly created project and choose the "Add Smodl Nature" action from the context-menu to enable SMODL for this project.

    Enabling SMODL for a project

    Enabling SMODL installs the SMODL Builder and adds some libraries to the "Java Build Path" of the project – refer to pictures below.

    SMODL Builder in project-properties view

    The libraries added to your project are necessary to make your project compile and run within Eclipse.

    Java build-path when SMODL is enabled

    In the list below first two libraries contain accordingly SMODL model and the runtime engine for the Smodl Development Suite Eclipse plugin. The rest – are the third-party libraries.

    1. SMODL model com.runitsoft.smodl.model_1.1.4.jar
    2. the runtime com.runitsoft.smodl.javaruntime_1.1.4.jar
    3. Java Activation Framework activation.jar required by SAAJ
    4. SAAJ libraries saaj-api.jar
    5. SAAJ libraries saaj-impl.jar
    6. Xml pull parser xpp3-min-1.1.3.4.M.jar

    If you later choose to disable SMODL for this project, just right-click on the project and choose "Remove Smodl Nature". The SMODL Builder will be removed but the runtime libraries will persist. The libraries can, however, be removed and changed manually like any other properties of the project, and the SMODL builder can be enabled and disabled like any other Eclipse-builder.

    It is assumed that the reader knows the various consequences of changing properties of a project. Please refer to Eclipse documentation for further details about builders and runtime libraries.

  2. Create the SMODL file

    Our example is a simple registry of employees. Create a new file called “Crud.smodl” in the "src" directory (or any other source-directory) in your project (see picture below) and paste in the xml listed below (note that the SMODL-file may be opened by an XML-editor, in which case you need to switch to the source-view of the editor in order to paste text into it).

    When saving the file, it is verified by the SMODL Builder. This verification is done every time you save the file after changing it. Any errors or warnings from the SMODL Builder are reported to the appropriate view in Eclipse. Automatic code-generation (see e.g. below) will be triggered only after successful verification by the SMODL Builder.

    Creating new SMODL file


    A quick introduction to SMODL (optional)

    The xml-dialect in the listing above is SMODL. SMODL is designed to be self-explanatory, but it may be useful to clarify our example at this point (see the SMODL Language Reference for further details).

    In our example, a DTO called Employee is defined with fields “id”, "name”, “title”, “salary” and “birthdate”. All fields are by default required to have real, non-null values, however in the example above the attribute “nullable” is set for “salary” and “birthdate”, allowing them to also have the value null (see also below). Datatypes used are “string”, “int” and “dateTime”. The former two should be fairly obvious, and “dateTime” is a date or time in the ISO-8601 format3.

    Furthermore, observe that our example implements four methods. The method create() requires an Employee-object as parameter and returns a boolean value. Of course, the exact semantics of create() is not clear from this model, but it is sufficient to generate code to deal with the method and its parameters in a  network-application. To describe semantically what create() does, use the <doc> tag, e.g.

    <method name="create">
    <doc>Creates the record, returning flag to indicate whether it succeeded or not</doc>
    <arg name="data" type="Employee"/>
    <result type="bool"/>
    </method>

    As mentioned, fields in a DTO are by default required to contain non-null values, but can be null if the attribute “nullable” is set. SMODL can also define other restrictions for data in a DTO, including min/max length of strings and regular expressions which the value should match. Please refer to the technical documentation and formal specification for further details and examples.

    The attribute "nullable" can in fact be set on all elements denoting values, including parameters and return-values of methods. A method with the nullable-attribute set on a parameter indicates that it will work even if the value of this parameter is null when calling the method4. If the return-value of a method has the nullable-attribute set, it indicates that this method may return null and consequently the client should be able to deal with this.

    Looking at this from the other angle: If the nullable-attribute is not set on a parameter of a method, the implementor of this method does not have to worry about receiving null because the runtime engine will ensure that this never happens. A method declaring its return-value to be not nullable guarantees that the client will always receive a proper, non-null value from the method.

    All requirements on DTOs are verified by the runtime engine on the server before the implementation of the method is invoked. This protects your service-implementation from unexpected data and provides accurate runtime errors if appropriate.

    Moreover, if the client is using a client-toolkit generated by Smodl Development Suite, these requirements are verified on the client before any communication takes place. This leads to reduced network-traffic, reduced load on your server and avoids polluting your server logs with messages about unexpected data from clients. But most importantly, client-toolkits provide accurate messages on the client, minimizing frustration among the client programmers and load on your support-team while a new client is being developed!

  3. Enable automatic code-generation

    By default, all code-generation from SMODL-files is disabled. Prepare code generation by going to Package Explorer in Eclipse and add the package "org.smodl.tutorial". Then, open the property-page for the file Crud.smodl, choose the SMODL pane and the “Java Module” tab and check the box “Generate interface” (see picture below).

    Make sure "Target Path for interface" points to an existing source folder as defined previously, and make sure to place the interface in an existing package ("org.smodl.tutorial" in our example). You can also choose whether to generate DTOs with public fields, public set/get methods, or both. Observe how the example-code in the tab changes when selecting different combinations. In our example, however, we choose public fields only. Close the property-page.

    Enabling server-side code generation

    Code for the server is now generated by the SMODL builder and thereafter compiled by the Java builder installed in your Eclipse project. Note that every time you change and save the SMODL file or manually rebuild the project, code for the server is re-generated and re-compiled, smoothly integrating into the familiar workflow of Eclipse.

    Note that if you make any changes to the generated files, these will be overwritten when the SMODL file is changed and code is re-generated...

    What is generated for the server?

    In our example, two pieces of code are generated: A Java interface called CRUD and a Java class describing the Employee-object (the DTO). Both are written into one file unless other specified on the property-page for Crud.smodl. This file will look similar to the listing below

    /*
    ***********************************************************************
    * This file is automatically generated by Smodl Development Suite. *
    * *
    * Don't change it manually unless you really know what you are doing! *
    ***********************************************************************
    */
    package org.smodl.tutorial;

    /**
    * Interface to specify Java bindings to functionality provided by CRUD service.
    */

    public interface CRUD
    {
    public Boolean create(Employee data);

    public Employee retrieve(String id);

    public Boolean update(String id, Employee data);

    public Employee delete(String id);

    public static class Employee
    {
    public String id;
    public String name;
    public String title;
    public Integer salary;
    public java.util.Date birthdate;
    }

    public static final String _SMODL_DEFINITION=
    "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"+
    "<service name=\"CRUD\" xmlns=\"http://smodl.org/v1\">\n"+
    "\n"+
    "<method name=\"create\">\n"+
    "\t<arg name=\"data\" type=\"Employee\"/>\n"+
    "\t<result type=\"bool\"/>\n"+
    "</method>\n"+
    "\n"+
    "<method name=\"retrieve\">\n"+
    "\t<arg name=\"id\" type=\"string\"/>\n"+
    "\t<result type=\"Employee\" nullable=\"true\"/>\n"+
    "</method>\n"+
    "\n"+
    "<method name=\"update\">\n"+
    "\t<arg name=\"id\" type=\"string\"/>\n"+
    "\t<arg name=\"data\" type=\"Employee\"/>\n"+
    "\t<result type=\"bool\"/>\n"+
    "</method>\n"+
    "\n"+
    "<method name=\"delete\">\n"+
    "\t<arg name=\"id\" type=\"string\"/>\n"+
    "\t<result type=\"Employee\" nullable=\"true\"/>\n"+
    "</method>\n"+
    "\n"+
    "<struct name=\"Employee\">\n"+
    "\t<field name=\"id\" type=\"string\"/>\n"+
    "\t<field name=\"name\" type=\"string\"/>\n"+
    "\t<field name=\"title\" type=\"string\"/>\n"+
    "\t<field name=\"salary\" type=\"int\" nullable=\"true\"/>\n"+
    "\t<field name=\"birthdate\" type=\"dateTime\" nullable=\"true\"/>\n"+
    "</struct>\n"+
    "</service> ";
    }


    The Smodl Development Suite can be used to generate DTOs for various projects. To make the generated code more portable we shall now generate the interface and the DTO in separate files. Again, open the property-page for the Crud.smodl, choose the SMODL pane and the “Java Module” tab and check the box “Separate class for DTOs?”. Insert fully quialified name for the DTO class (see picture below). Observe how the example-code in the tab changes when checking the box “Separate class for DTOs?”.

    Generate DTO in a separate file

    Note that the SMODL itself is embedded in the generated interface – this is to simplify deployment. Before we can deploy a service, however, it must be implemented, which is described in the next section.

  4. Write the server–side implementation

    At this point we shall write the implementation of our CRUD service. In real life we would use JDBC, some other database-API, or possibly a persistence-framework like Hibernate to store our data. However, proper ways to store data are beyond the scope of this tutorial so we'll just use a Hashtable. In Eclipse, prepare by adding the package "org.smodl.tutorial.impl" from your Package Explorer. Then add to it a new class and make it implement the CRUD-interface. Also make sure to select “Inherited abstract methods” (see image below).

    Generate CrudImpl class

    Working Java-code is listed below and should be simple to understand. Most of the code is generated for you by Eclipse – fill in the missing parts by e.g. copying from this text and paste it into Eclipse.

    Some points must be emphasized here:

    Most real-life Web services also require some level of security. SMODL has been designed to work with whatever security-mechanism your platform provides. You can for example set up authentication by client-certificates when using Tomcat or JBoss, or when using Apache in a simple LAMP stack. Or you can just use standard http authentication on your server. Intentionally, SMODL does not enforce security of its own, but rather provides freedom in this area. Authentication-information can be passed from the runtime engine to your service-implementation which can deal with it in the most suitable way.

    The SMODL-runtime also supports authorized execution of service methods. The security limitations that applied on service method calls are based on the role validation mechanism. Please review the article for more information.

  5. Change the SMODL file to improve the API (optional, but illustrative)

    While implementing the update() method, it becomes clear that the id actually could be determined from the corresponding field in the Employee-object. Thus, the parameter 'id' of the update() method is redundant. A good rule-of-thumb is that APIs which will be used by other people should be as simple and unambiguous as possible. Now, remove the id-parameter from update() (change the SMODL-file so that the update-method is described like below).

    <method name="update">
    <arg name="data" type="Employee"/>
    <result type="bool"/>
    </method>

    Save the SMODL file and observe how the interface CRUD changes immediately and how CrudImpl immediately is marked erroneous in Eclipse (the interface changed, thus the class implementing it must be changed accordingly). Correct CrudImpl (remove the first parameter from update()) and save your changes.

    The example above illustrates one of the major benefits of Smodl Development Suite: If you decide to refactor the API of a SMODL Web service, code is automatically re-generated and necessary changes in your implementation is highlighted! A simple change like described above improves the Web service by reducing the number of parameters to a method. It also prevents possible confusion for the client programmer using the service (“Why do I have to pass id as a separate parameter when it's already contained in the other parameter? Are these different ids??”). When implementing Web services using modern, iterative development methodologies, developers are likely to identify redundant or missing parameters, methods, etc. which were not discovered at design-time. A simple and powerful tool to deal with refactoring is crucial to ensure that changes are implemented safely, which is what Smodl Development Suite provides.

    Note how the "model-first" approach works here: The model is the entity being maintained, and code is a product of it. Smodl Development Suite assures that changing the model becomes safe and simple, lowering the threshold of improving it.

  6. Run your service locally

    Run as SMODL service We have included a simple, standalone Http-server with Smodl Development Suite, allowing you to run a SMODL application directly from Eclipse without installing Tomcat, JBoss or other full-featured servers. Of course, a real Web service will probably utilize the infrastructure provided by a servlet container or application server, but for initial testing this integrated Http server is sufficient.5 Please refer to appropriate documentation for how to implement and deploy a SMODL service in other server-environments.

    In order to launch your service from Eclipse, go to the Package View, right-click on the file "CrudImpl.java" and choose "Run As" (or "Debug As") then "Standalone SMODL Service" (see picture on the right). A launch-configuration (see picture below) is displayed....

    The Smodl launch-configuration

    ... is a normal Eclipse launch-configuration, which means that it can be saved, deleted, modified, etc. like any other launch-configuration in Eclipse. Smodl Development Suite will re-use any existing Smodl launch-configuration if it matches the service you are launching. Most of the tabs in the Smodl launch-configuration are identical to the corresponding tabs in the standard Eclipse Java launch-configuration, but we have added two:

    In the "Smodl" tab, the "Project" field identifies which project to launch the service in context of. The "Target Implementation" field identifies the class implementing the service ("CrudImpl" in our example). And finally, the (optional) "Smodl Model" field identifies the SMODL model explicitly. The latter is only necessary if your target implementation is a class not implementing the interface generated by Smodl Development Suite (e.g. if you follow the  "contract-last" approach). In the picture below, the value in the "Smodl Model" field shows that the target implementation already contains information about the model. This is because the model is embedded in the generated interface as described earlier. You can, however, override the embedded model by explicitly providing another model, but this assumes you know what you are doing, and this subject is beyond the scope of this tutorial.

    Automatically generated Run-config

    By default the standalone Http server listens to port 9080. However, the launch-configuration window includes a tab – "Standalone Server" – (see image below) where the  listening port can be changed. Another nice feature on this tab is the ability to specify a static page folder to serve static content. Activate the static page support by selecting the "Serve static files?" box and specify the root-directory to serve. Finally, the  standalone Http server will log all incoming and outgoing messages to the Eclipse console (or stdout, if run outside Eclipse) if the a checkbox called "Verbose?" is selected.

    Standalone Server tab of a launch-configuration

    The standalone Http server uses normal Java-mechanisms to determine content-types of static files. However, Java by default has a rather limited map of content-types; frequently used types like "application/javascript" and "text/css" are typically not present. If the client you are using expects proper content-type information (like e.g. a browser) you may have to add mappings for your files in the JRE that you use. You can do this you by editing the file called "content-types.properties" in the "lib" directory of your JRE, or you can specify your own mapping using the system-property indicated here. Note that there is an open bug (#608) registered in Smodl Development Suite to improve this.

    The generated launch-configuration contains values derived from the service you are launching. If you launch a service by right-clicking on your implementation-class, it will be used as target-implementation. If you launch by right-clicking on the SMODL file itself, you need to identify the implementation.

    After pushing the "Run" button (or "Debug" button if you are debugging), the service is deployed and run in the standalone Http server. The server accepts connections from the local host only which is considered satisfactory for the tutorial's purposes(*).The runtime library serves all defined methods over JSON, SOAP and XML-RPC which can be accessed using the following URLs:

    JSON: http://localhost:9080/service/JSON
    SOAP: http://localhost:9080/service/SOAP
    XML-RPC: http://localhost:9080/service/XML-RPC

    Moreover, WSDL6 describing the service and its SOAP binding can be obtained from the following URL:

    WSDL: http://localhost:9080/service/SOAP?wsdl

    To retrieve the SMODL model being run by a service use the following URL:

    SMODL: http://localhost:9080/service/JSON?smodl

    Client toolkits (code to be used on some client-platform) generated by Smodl Development Suite will use JSON-RPC for communication, as we consider this to be the simplest and most compact of the three protocols. The next section describes how to generate and use such toolkits.

    * If you really want other hosts to access your service, go to the "Arguments"-tab and add "-a" in "Program Arguments". However, keep in mind that any firewall-related settings may prevent other hosts to connect to your computer no matter how the standalone server is run.

  7. Enable automatic code-generation for the client

    From the Package Explorer view, create the package "org.smodl.tutorial.client" to hold client-related code. Open the property page for the SMODL file and choose the “Java Module” tab. Select the checkbox “Generate client factory” and fill in values as shown in the picture below. Note that “Target Path for client code" is also set to “src” in order to keep things simple. Close the property page.

    Enabling client-side code generation

    A class called org.smodl.tutorial.client.CRUDFactory is now generated. It contains only the static method create() which is to be called by clients to obtain a proxy to the service. The input parameter to the create-method is the URL on which the service runs, in our example this is "http://localhost:9080/service/JSON" (recall from the previous section that automatically generated clients will use the JSON-RPC protocol).

    Using the setup described in the previous section, the following code can be used from a client to access the example service (note the URL used in the create() method). Use the Package Explorer view to create the class org.smodl.tutorial.client.CrudClient, then copy the code below and paste it into the class.

    In order to test the service, run the server as described above, then run the code listed above as any other Java application in Eclipse, e.g. by right-clicking the file org.smodl.tutorial.client.CrudClient.java in Package Explorer view and choose "Run As" and "Java Application".

    Clients for other languages and environments

    One of the strengths of SMODL Development Suite is that it generates client-toolkits for different languages and environments. Included in the current version are toolkit-generators for Java and PHP, please refer to this document for details of how to write and use a PHP client.

    As SMODL Development Suite evolves, plugins to generate client-toolkits for other languages will be added.

  8. Generate WSDL file

    SMODL Development Suite offers convenient way to generate WSDL-files from SMODL. Namely, in a properties view for the SMODL file the reader can determine various properties such as "Target Path", "WSDL File Name", "WSDL Service Binding URL". The view also offers a way to store the DTOs and the service in separate files by specifying a file name for schema location, see the image below.

    Generate WSDL files from SMODL

  9. Exercises (optional)

    You are now ready to experiment with SMODL! Suggested below are a number of changes you can do to this example to get a better feeling of how SMODL Development Suite works. All these changes are likely to be encountered while developing a real application. Have fun!



1 If you search on e.g. www.Google.com for the terms "contract first approach" or "contract last approach", you will find a lot of interesting arguments in favour of both paradigms.

2Data Transfer Object” – please refer to almost any text about design patterns for distributed systems, or do a Google-search for the term.

3 See http://www.iso.org/iso/en/prods-services/popstds/datesandtime.html for further details.

4 This typically involves code like: if (param != null) { do-something } else { do-something-else }

5 The standalone server can also be used in production, if desired, but is not intended to replace a full-featured servlet-container or application-server.

6 Web Services Description Language. See e.g. Wikipedias definition or the glossary at <soaprpc />