Tutorial

Hello World

Let's create our first Meso class named meso:HelloWorld. Create the following file name HelloWorld.meso, and put it in the same directory as where the meso.jar is at:

namespace meso:;
import java:java.lang.System;

public class HelloWorld {

   public static void main(string[] args) {        // starts from here
      System.out.println( "Hello World!" );
   }
}

You do not need to compile the program. To execute it, go to the directory in a terminal and do:

stefan@macpro:~/test$ java -jar meso.jar meso:HelloWorld
Hello World!
stefan@macpro:~/test$ _

The java -jar meso.jar starts the runtime, whereas meso:HelloWorld tells the runtime which UTL to start from. The starting type must have a void main(string[]) method.

Using the namespace

A Meso source file must be stored in a directory correlating to its namespace declared inside, just like how Java organizes source code with packages. For example, to create a Meso class named meso:foo.bar.HelloWorld, the HelloWorld.meso file must be stored under the foo/bar directory:

meso.jar
foo/
  |
  +-- bar/
        |
        +-- HelloWorld.meso

The namespace statement must also have the foo.bar path:

namespace meso:foo.bar;            // adds "foo.bar"
import java:java.lang.System;

public class HelloWorld {

   public static void main(string[] args) {
      System.out.println( "Hello World (again)!" );
   }
}

To execute it, go to the directory where meso.jar is at and do:

stefan@macpro:~/test$ java -jar meso.jar meso:foo.bar.HelloWorld
Hello World (again)!
stefan@macpro:~/test$ _

By default, the runtime will search the source for meso:foo.bar.HelloWorld from the current directory. A config file can make it search from different directories.

A remote object

Let's create a simple network service that returns the sum of two integers. To make things easier, this example will put the remote service at localhost:9900 so that you don't actually need two computers to try it. First, we create the singleton object imop:localhost:9900/bar.Calculator. Its source code is in the file named Calculator.imop stored in the bar directory under where the remote service's Meso runtime will be started. Notice that the file's extension is .imop rather than .meso. Meso source code's extension name must match the namespace's scheme name.

This is the source code in Calculator.imop:

namespace imop:localhost:9900/bar;     // served from localhost:9900

public object Calculator {             // a singleton object

   public int add(int x, int y) {
      return x + y;
   }
}

You also need to tell Meso runtime's IMOP plugin to open a listener for localhost:9900. You do so by giving the runtime a custom configuration file, such as the config.xml file below:

<meso>
   <plugin class="meso.core.lang.MesoPlugin">
      <src path="." />                           <!-- the root of *.meso files -->
   </plugin>

   <plugin class="meso.plugin.java.JavaPlugin">
   </plugin>

   <plugin class="meso.plugin.imop.ImopPlugin">
      <listener address="localhost:9900" />      <!-- opens an IMOP listener -->
      <src path="." />                           <!-- the root of *.imop files -->
   </plugin>
</meso>

Plugins listed in the config file will be enabled in the runtime. Since imop:localhost:9900/bar.Calculator uses only the IMOP scheme, it is safe to remove the first two plugin elements from the config file.

Assume that you use ~/remote as the root directory for the remote service, your directory structure should looks like this:

~/remote/
   |
   +-- meso.jar
   +-- config.xml
   +-- bar/
        |
        +-- Calculator.imop

To start the service, go to the ~/remote directory and start the runtime:

stefan@macpro:~/remote$ java -jar meso.jar -cf config.xml
Meso 1.6.0 Build 2011-1113 with IMOP transport 0.6
Runtime Build $Date: 2011-11-13 17:27:49 -0800 (Sun, 13 Nov 2011) $
INFO: Port 9900 opened
INFO: Authority 'localhost:9900' bound to port 9900
runtime> _

The -cf config.xml argument passes the config file to the runtime. When the runtime is started without specifying a starting UTL like above, it changes to a passive mode waiting for new requests. It is now listening to port 9900 on localhost.

Now let's create a client class meso:foo.Client. Here is the content of the Client.meso file:

namespace meso:foo;
import imop:localhost:9900/bar.Calculator;                  // imports the reference
import java:java.lang.System;

public class Client {

   public static void main(string[] args) {                
      System.out.println(
         "Answer: " + (java:int) Calculator.add( 6, 8 )     // calls the remote object
      );
   }
}

We don't need a custom config file for the client. Assume that you use ~/local as the root directory, your directory structure should look like this:

~/local/
   |
   +-- meso.jar
   +-- foo/
        |
        +-- Client.meso

Now we can start the client:

stefan@macpro:~/local$ java -jar meso.jar meso:foo.Client
Answer: 14
stefan@macpro:~/local$ _

Writing a network program this way is intuitive, isn't it? Better yet, being a strongly-typed language, the internal Meso compiler will verify the type-safety before generating code for the runtime. For example, if we inadvertently missed an integer argument to the add() method in the Client.meso file, as follows:

namespace meso:foo;
import imop:localhost:9900/bar.Calculator;                
import java:java.lang.System;

public class Client {

   public static void main(string[] args) {
      System.out.println(
         "Answer: " + (java:int) Calculator.add( 8 )       // WRONG!!
      );
   }
}

When executing the code, the compiler will throw this error message out:

stefan@macpro:~/local$ java -jar meso.jar meso:foo.Client
Syntax error in source /Users/stefan/local/foo/Client.meso:
[9,45 - 47] The method add(meso:int) is undefined for the type imop:localhost:9900/bar.Calculator
stefan@macpro:~/local$ _

Just as what you would expect in a conventional language. The difference here is that part of the program, namely the imop:localhost:9900/bar.Calculator object, is hosted on a remote machine when the Client is compiling.

To stop the Meso runtime for localhost:9900, just enter exit after the runtime> prompt.