Model View Controller (MVC) with JSP and JSTL

In this article we will create a small web application that uses the Model View Controller (MVC) pattern with Java Server Pages (JSP) and JSP Standard Template Library (JSTL). A container like Tomcat is needed to run this combination.

Thanks go out to the author of the JSP – MVC Tutorial, who thought of the sample application that we will use here, the coffee advisor. The user is first presented with a choice in coffee taste she prefers. Pressing a button moves on to a page with advise about the type of coffee to drink based on that taste.

An MVC application has three parts:

  • Model. The model is the domain-specific representation of the data upon which the application operates. In our case this is implemented in the CoffeeExpert class.
  • View. The view renders the model into a form suitable for interaction, typically a user interface element. In our case this is implemented in a JSP file called coffee.jsp.
  • Controller. The controller receives input and initiates a response by making calls on model objects. In our case this is implemented in the CoffeeSelect class.

In addition to these three file we need a web.xml file that tells the container how to map a URL (e.g. /CoffeeSelect.do) into a class to run (e.g. com.example.web.CoffeeSelect). We also need a start page for the user input, which we will call coffee.html. In total this means we should create a  .war file with the following structure:

coffee.html

<html>
    <body>
        <h2>Coffee Advisor Input</h2>
        <form method="POST" action="CoffeeSelect.do">
            <select name="taste" size=1">
                <option value="milky">Milky</option>
                <option value="froffy">Froffy</option>
                <option value="icey">Icey</option>
                <option value="strong">Spaced Out</option>
            </select>
            <br/><br/>
            <input type="Submit"/>
        </form>
    </body>
</html>

CoffeeExpert.java

package com.example.model;

import java.util.*;

public class CoffeeExpert {
    public List<String> getTypes(String taste) {
        List<String> result = new ArrayList<String>();
        if (taste.equals("milky")) {
            result.add("Latte");
            result.add("Cappuccino");
        } else if (taste.equals("froffy")) {
            result.add("Latte");
            result.add("Cappuccino");
            result.add("Frappuccino");
        } else if (taste.equals("icey")) {
            result.add("Frappuccino");
        } else if (taste.equals("strong")) {
            result.add("Espresso");
            result.add("Double espresso");
        } else {
            result.add("Vending machine");
        }
        return (result);
    }
}

CoffeeSelect.java

package com.example.web;

import java.io.IOException;
import java.util.List;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.example.model.CoffeeExpert;

public class CoffeeSelect extends HttpServlet {

    private static final long serialVersionUID = 1L;

    public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
        List<String> types = new CoffeeExpert().getTypes(request.getParameter("taste"));
        request.setAttribute("types", types);
        RequestDispatcher view = request.getRequestDispatcher("coffee.jsp");
        view.forward(request, response);
    }
}

coffee.jsp

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>

<html>
    <body>
        <h2>Coffee Advisor Output</h2>
        <c:forEach var="type" items="${types}">
            <c:out value="${type}"/>
            <br />
        </c:forEach>
    </body>
</html>

web.xml

<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
    version="2.4">

    <servlet>
        <servlet-name>Coffee</servlet-name>
        <servlet-class>com.example.web.CoffeeSelect</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>Coffee</servlet-name>
        <url-pattern>/CoffeeSelect.do</url-pattern>
    </servlet-mapping>
</web-app>

Changing CPU and memory settings on XenServer VMs

You can change the CPU and memory settings of XenServer virtual machines using the API. XenServer allows you to set the priority of the virtual machine CPU (called weight), set a limit on the amount of CPU the virtual machine can use (called cap) and set the amount of memory the virtual machine gets.

CPU priority

You can set the weight parameter to a number between 1 and 65536. The default value is 256, meaning normal priority. A virtual machine with a weight of 512 will get twice as much CPU as a virtual machine with a weight of 256 on a contended XenServer host. The following code sets the weight to 128, meaning that it will get half as much CPU as a normal virtual machine.

Map<String, String> vcpuParameters = new HashMap<String, String>();
vcpuParameters.put("weight", "128");
vm.setVCPUsParams(connection, vcpuParameters);

CPU limit

You can set the cap parameter to a percentage number. The default value is 0, meaning there is no cap. The value 100 represents one virtual CPU, so half a virtual CPU can be set by using the value 50. The following code sets the cap to 35, meaning that it will not get more than 35 percent of one virtual CPU, even if the physical CPU is not used to its top.

Map<String, String> vcpuParameters = new HashMap<String, String>();
vcpuParameters.put("cap", "35");
vm.setVCPUsParams(connection, vcpuParameters);

Memory

You can set the amount of memory assigned to a virtual machine in bytes. The following code sets the amount of memory to 1 GB (1,073,741,824 bytes).

vm.setMemoryStaticMax(connection, new Long(1073741824));

Installing Sun JDK 6 on Ubuntu 10.04

The Sun JDK can be installed on Ubuntu by adding a repository and installing with apt-get. The following works with the latest versions of both at the time of writing:

sudo add-apt-repository "deb http://archive.canonical.com/ lucid partner"
sudo apt-get update
sudo apt-get install sun-java6-jdk

If the command add-apt-repository is missing, install it with the following command:

sudo apt-get install python-software-properties

With the alternatives system in place, the Java executable is automatically available:

/usr/bin/java -> /etc/alternatives/java
/etc/alternatives/java -> /usr/lib/jvm/java-6-sun/jre/bin/java

Setting up JAVA_HOME can now be done by editing /etc/profile and adding to the bottom:

export JAVA_HOME=/usr/lib/jvm/java-6-sun

Getting CPU, memory, disk and network metrics from XenServer

In a previous article we looked at getting CPU and memory metrics from XenServer. As noted in that article, as of version 5.5 of XenServer, the preferred way of getting virtual machine metrics is through HTTP calls to get RRD XML files. We showed how to revert to the old way of doing things, but in this article we will look into the new, preferred way. This has the added benefit that disk and network metrics are also available, along with a history of metrics.

The first thing to note is that the metrics are not available through the XenServer API. The RRD XML files are stored on the physical machines that currently host the virtual machines. For example, if you have two physical machines (P1 and P2) with two virtual machines running on each of them (V1a, V1b, V2a and V2b), you need to query P1 for the metrics of V1a and V1b and query P2 for the metrics of V2a and V2b. If a virtual machine is not running at the moment, you can get the (old) metrics from the master in the pool.

Each physical machine has an HTTP interface at the following location:

http://machine_name_or_ip/rrd_updates?start=1234567890

The parameter start tells the server to only give metrics starting at this timestamp (seconds since January 1st 1970). The call requires a username and password, which will be asked if you connect through a webbrowser. The following code does this in Java:

Connection connection = new Connection(new URL(MASTER_HOST));
Session.loginWithPassword(connection, USERNAME, PASSWORD, APIVersion.latest().toString());

Map hostRecords = Host.getAllRecords(connection);
for (Host host : hostRecords.keySet()) {
    URL url = new URL("http://" + host.getAddress(connection) + "/rrd_updates?start=" + (System.currentTimeMillis() / 1000 - TIME_WINDOW));
    URLConnection urlConnection = url.openConnection();
    String encoding = new BASE64Encoder().encode((USERNAME + ":" + PASSWORD).getBytes());
    urlConnection.setRequestProperty ("Authorization", "Basic " + encoding);

    String rrdXportData = IOUtils.toString(urlConnection.getInputStream());
}

The code needs two libraries:

  • commons-io-1.4.jar. This package contains the code to get a string containing the data of an inputstream.
  • xenserver-5.5.0-1.jar. This package contains the code to connect to the XenServer pool.

The following constants are used in this piece of code and need to be filled in:

  • MASTER_HOST. This is the IP address or hostname of the master host in the pool.
  • TIME_WINDOW. XenServer will return RRD updates of the last TIME_WINDOW seconds.
  • USERNAME and PASSWORD. These are the credentials for connecting to the master host and the other physical hosts in the pool.

At the end of this piece of code we have the string rrdXportData containing the RRD XML data. Now we need to parse this data to get the metrics we want. The following listing contains the most important parts of this string (edited for clarity):

<xport>
   <meta>
      <start>1273342925</start>
      <step>5</step>
      <end>1273342980</end>
      <rows>13</rows>
      <columns>31</columns>
      <legend>
         <entry>AVERAGE:vm:19ef51bd-2cbc-50d1-3fa2-ad8878699203:cpu0</entry>
         <entry>AVERAGE:vm:19ef51bd-2cbc-50d1-3fa2-ad8878699203:vif_4_tx</entry>
         ...
      </legend>
   </meta>
   <data>
      <row>
         <t>1273342980</t>
         <v>0.0002</v>
         <v>0.0</v>
         ...
      </row>
      <row>
         <t>1273342975</t>
         <v>0.0003</v>
         <v>0.0</v>
         ...
      </row>
      ...
   </data>
</xport>

The following Java code will parse this RRD XML string and make it available in the four variables shown at the top. The variable metricsTimelines contains a hashmap of string to double[]. The string is the metric name (e.g. AVERAGE:vm:19ef51bd-2cbc-50d1-3fa2-ad8878699203:cpu0) and the double[] contains the values for this metric from startTime to endTime with a step size of step. Note that the value at endTime is at position 0 and the value at  startTime is at the end of the array.

int endTime = 0;
HashMap<String, double[]> metricsTimelines = null;
int startTime = 0;
int step = 0;

try {
   DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
   domFactory.setNamespaceAware(true);
   DocumentBuilder builder = domFactory.newDocumentBuilder();
   StringReader stringReader = new StringReader(rrdXportData);
   InputSource inputSource = new InputSource(stringReader);
   Document doc = builder.parse(inputSource);
   stringReader.close();

   ArrayList<ArrayList<String>> dataRows = new ArrayList<ArrayList<String>>();
   ArrayList<String> legends = new ArrayList<String>();
   NodeList xportChildNodes = doc.getDocumentElement().getChildNodes();
   for (int i = 0; i < xportChildNodes.getLength(); i++) {
      Node xportChildNode = xportChildNodes.item(i);
      if (xportChildNode.getNodeName().equals("meta")) {
         NodeList metaChildNodes = xportChildNode.getChildNodes();
         for (int j = 0; j < metaChildNodes.getLength(); j++) {
            Node metaChildNode = metaChildNodes.item(j);
            if (metaChildNode.getNodeName().equals("step")) {
               step = new Integer(metaChildNode.getTextContent()).intValue();
            } else if (metaChildNode.getNodeName().equals("start")) {
               startTime = new Integer(metaChildNode.getTextContent()).intValue();
            } else if (metaChildNode.getNodeName().equals("end")) {
               endTime = new Integer(metaChildNode.getTextContent()).intValue();
            } else if (metaChildNode.getNodeName().equals("legend")) {
               NodeList legendChildNodes = metaChildNode.getChildNodes();
               for (int k = 0; k < legendChildNodes.getLength(); k++) {
                  Node legendChildNode = legendChildNodes.item(k);
                  legends.add(k, legendChildNode.getTextContent());
               }
            }
         }
      } else if (xportChildNode.getNodeName().equals("data")) {
         NodeList dataChildNodes = xportChildNode.getChildNodes();
         for (int j = 0; j < dataChildNodes.getLength(); j++) {
            Node rowNode = dataChildNodes.item(j);
            NodeList rowChildNodes = rowNode.getChildNodes();
            ArrayList<String> dataRow = new ArrayList<String>();
            for (int k = 1; k < rowChildNodes.getLength(); k++) {
               Node rowChildNode = rowChildNodes.item(k);
               dataRow.add(k - 1, rowChildNode.getTextContent());
            }
            dataRows.add(dataRow);
         }
      }
   }

   int nrDataRows = dataRows.size();
   int nrLegends = legends.size();

   metricsTimelines = new HashMap<String, double[]>();
   for (int i = 0; i < nrLegends; i++) {
      metricsTimelines.put(legends.get(i), new double[nrDataRows]);
   }
   for (int i = 0; i < nrLegends; i++) {
      for (int j = 0; j < nrDataRows; j++) {
         double[] values = metricsTimelines.get(legends.get(i));
         values[j] = new Double(dataRows.get(j).get(i)).doubleValue();
      }
   }
} catch (Exception e) {
   e.printStackTrace();
}

Using Google Visualization API with own data source

The Google Visualization API allows you to create charts and maps based on data you provide. This data can be in a Google Spreadsheet or be something you provide yourself. The visualizations themselves are mostly written in Javascript, although there are some written in Flash.

In this article we will create an HTML page with multiple charts in it and a data source that is generated by a Python program. We start with the HTML page that has two named div’s in it (visualization1 and visualization2), including the Javascript code that loads the two charts into these div’s.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
   <head>
      <meta http-equiv="content-type" content="text/html; charset=utf-8"/>
      <title>
         Google Visualization API
      </title>
      <script type="text/javascript" src="http://www.google.com/jsapi"></script>
      <script type="text/javascript">
         google.load('visualization', '1', {packages: ['columnchart', 'linechart']});
      </script>
      <script type="text/javascript">

         var query1, visualization1;
         var query2, visualization2;

         function initialize() {
            visualization1 = new google.visualization.ColumnChart(document.getElementById('visualization1'));
            query1 = new google.visualization.Query('http://jansipke.nl/res/visualization/chart-data.py');
            query1.setRefreshInterval(5);
            query1.send(drawVisualization1);

            visualization2 = new google.visualization.LineChart(document.getElementById('visualization2'));
            query2 = new google.visualization.Query('http://jansipke.nl/res/visualization/chart-data.py');
            query2.setRefreshInterval(5);
            query2.send(drawVisualization2);
         }

         function drawVisualization1(response) {
            if (response.isError()) {
               alert('Error in query: ' + response.getMessage() + ' ' + response.getDetailedMessage());
               return;
            }
            visualization1.draw(response.getDataTable(), {legend: 'bottom', title: 'ColumnChart'});
         }

         function drawVisualization2(response) {
            if (response.isError()) {
               alert('Error in query: ' + response.getMessage() + ' ' + response.getDetailedMessage());
               return;
            }
            visualization2.draw(response.getDataTable(), {legend: 'bottom', title: 'LineChart'});
         }

         google.setOnLoadCallback(initialize);
      </script>
   </head>
   <body>
      <div>
         <div id="visualization1" style="height: 250px; width: 400px; border: 1px solid; float: left;" />
      </div>
      <div>
         <div id="visualization2" style="height: 250px; width: 400px; border: 1px solid; float: left; margin-left: 10px" />
      </div>
   </body>
</html>

There are two things that you really need to do before this works correctly:

  • Make sure that the parent node of the div that holds your chart, is not also the parent of one of the other div’s that holds a chart. In the HTML page above we surrounded the chart div with another div to accomplish this.
  • The chart is updated with new data every 5 seconds. It is a known bug of the Google Visualization API that the data needs to be fetched from another server then the one that is hosting the HTML page for the refresh to actually work. In the HTML page above the data source chart-data.py is therefore fetched from jansipke.nl and the HTML is fetched from www.jansipke.nl.

We will create our own data source in Python. There is a description of how you should do this on the Writing Your Own Data Source page from Google. One of the most common mistakes in writing these data sources is the need for the program to read the request identifier (reqId) and return this value in the response. The API needs this to distinguish between responses for different charts on the same page.

import cgi, random

def index(req):
   reqId = None
   if (req.args):
      for arg in req.args.split("&"):
         (key, value) = arg.split("=")
         if (key == "tqx"):
            for parameter in value.split(";"):
               if (parameter.find("%3A") > 0):
                  (par_key, par_value) = parameter.split("%3A")
               if (par_key == "reqId"):
                  reqId = par_value

   a = str(random.randint(1, 3))
   b = str(random.randint(1, 3))
   c = str(random.randint(1, 3))
   d = str(random.randint(1, 3))

   s = ""
   s += "google.visualization.Query.setResponse(\n"
   s += "{\n"
   if (reqId != None):
      s += "   reqId:'" + reqId + "',\n"
   s += "   status:'ok',\n"
   s += "   table:\n"
   s += "   {\n"
   s += "      cols:\n"
   s += "      [\n"
   s += "         {id:'Col1',label:'',type:'string'},\n"
   s += "         {id:'Col2',label:'Label1',type:'number'},\n"
   s += "         {id:'Col3',label:'Label2',type:'number'},\n"
   s += "         {id:'Col4',label:'Label3',type:'number'}\n"
   s += "      ],\n"
   s += "      rows:\n"
   s += "      [\n"
   s += "         {c:[{v:'a',f:'a'},{v:1.0,f:'1'},{v:1.0,f:'1'},{v:" + a + ",f:'1'}]},\n"
   s += "         {c:[{v:'b',f:'b'},{v:2.0,f:'2'},{v:1.5,f:'1'},{v:" + b + ",f:'1'}]},\n"
   s += "         {c:[{v:'c',f:'c'},{v:3.0,f:'3'},{v:2.5,f:'1'},{v:" + c + ",f:'1'}]},\n"
   s += "         {c:[{v:'d',f:'d'},{v:4.0,f:'1'},{v:2.0,f:'1'},{v:" + d + ",f:'1'}]}\n"
   s += "      ]\n"
   s += "   }\n"
   s += "});"

   return s

We can test this data source by following the link without parameters and following the link with the reqId parameter present:

Notice that the first one does not have reqId present in the response, but the second one does.

Update: it seems that the refreshing of data only happens correctly in Firefox and Opera. IE doesn’t refresh at all and Chrome only refreshes once. Oh joy!

Creating web charts using Open Flash Chart

Open Flash Chart gives you the possibility to have Flash based charts on your website without the need to know Flash. All it takes is a JSON file that describes the chart. This JSON file can be a static file that you created yourself with a text editor or dynamically created by a program, e.g. written in Java or Python.

There are several different types of charts that can be displayed. Some of them are shown here:

We start by creating an HTML page that will contain the chart:

<html>
   <head>
      <script type="text/javascript" src="swfobject.js"></script>
      <script type="text/javascript">
         swfobject.embedSWF("open-flash-chart.swf", "my_chart1", "600", "250",
                            "9.0.0", "expressInstall.swf", {"data-file":"chart1.data"});
      </script>
   </head>
   <body>
      <div id="my_chart1"></div>
   </body>
</html>

Then we create a JSON file called chart1.data that describes how the chart should look:

{
  "title":{
    "text":  "Bar Glass Chart",
    "style": "{font-size: 20px; color:#0000ff; font-family: Verdana; text-align: center;}"
  },

  "bg_colour": "#FFFFFF",

  "x_axis":
  {
    "stroke":      1,
    "tick_height": 10,
    "colour":      "#CCCCCC",
    "grid_colour": "#00ff00",
    "labels":
    {
      "labels": ["Server 1", "Server 2", "Server 3"]
    }
  },

  "y_axis":
  {
    "steps":       20,
    "tick_length": 100,
    "colour":      "#CCCCCC",
    "grid_colour": "#00FF00",
    "offset":      0,
    "max":         100
  },

  "elements":
  [
    {
      "type":      "bar_glass",
      "alpha":     0.5,
      "colour":    "#9933CC",
      "text":      "CPU load",
      "font-size": 10,
      "values" :   [90, 60, 70]
    },
    {
      "type":      "bar_glass",
      "alpha":     0.5,
      "colour":    "#CC9933",
      "text":      "Memory usage",
      "font-size": 10,
      "values" :   [60, 70, 90]
    }
  ]
}

Copy the HTML file, the JSON file and the open-flash-chart.swf and swfobject.js files from the Open Flash Chart website to your own webserver and point your webbrowser to the HTML file. The result should look like the chart on this page.

Google Maps icons and circles

It is quite easy to add content to Google Maps by using the API. In this article we will use some icons to mark points of interest and use polygons to emulate circles around a marker.

We want to give Google Maps an address and have a special icon and two circles around this point of interest. A picture says more than a thousand words, so here is the effect we want:

The Map Icon Collection hosts a large set of icons that are free to use in Google Maps. A small sample is shown below:

The following code achieves the effect we want. Take a look at the live result on this page.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:v="urn:schemas-microsoft-com:vml">
  <head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8"/>
    <title>Google Maps test</title>
    <script src="http://maps.google.com/maps?file=api&amp;v=2&amp;sensor=false&amp;key=ABQIAAAArmrLJW3ZXq5P2DWexL7cFRSV6dnYUXLUEsXoSWmGp_LQX0Ln_BRimh_EXlhDUBj_zubkneJU9IiMuw" type="text/javascript"></script>
    <script src="gmaps-circle-overlay.js" type="text/javascript"></script>
    <script type="text/javascript">

    var ICON_LOCATION = "/res/";
    var ICON_BUSINESS = ICON_LOCATION + "business.png";
    var ICON_HOUSE = ICON_LOCATION + "house.png";
    var ICON_WIDTH = 32;
    var ICON_HEIGHT = 37;

    var map = null;
    var geocoder = null;

    function initialize() {
      if (GBrowserIsCompatible()) {
        map = new GMap2(document.getElementById("map_canvas"));
        map.setCenter(new GLatLng(53.199290, 6.523368), 15);
        map.setUIToDefault();

        geocoder = new GClientGeocoder();

        showAddress("Fivelgolaan 10, Groningen, Nederland", ICON_HOUSE);
        showAddress("Peizerweg 200, Groningen, Nederland", ICON_BUSINESS);
      }
    }

    function showAddress(address, image, width, height) {
      if (geocoder) {
        geocoder.getLatLng(address, function(point) {
          if (!point) {
            alert(address + " not found");
          } else {
            var myIcon = new GIcon(G_DEFAULT_ICON);
            myIcon.image = image;
            myIcon.iconSize = new GSize(ICON_WIDTH, ICON_HEIGHT);
            markerOptions = { icon:myIcon };
            marker = new GMarker(point, markerOptions);
            GEvent.addListener(marker, "click", function() {
              map.openInfoWindowHtml(point, address);
            });
            map.addOverlay(marker);
            map.addOverlay(new CircleOverlay(point, 0.2, "#444499", 1, 1, '#444499', 0.25));
            map.addOverlay(new CircleOverlay(point, 0.1, "#FFFF99", 1, 1, '#FFFF99', 0.25));
          }
        });
      }
    }

    </script>
  </head>

  <body onload="initialize()" onunload="GUnload()">
    <div id="map_canvas" style="width: 800px; height: 500px"></div>
  </body>
</html>

The drawing of circles is handled by a stand-alone piece of Javascript by Daws Design. I edited it a bit to have it use kilometres instead of miles.

Getting XenServer VM metrics in Java

XenServer is a product of Citrix that can run virtual machines on a set of physical hosts called a pool. There is an API that allows you to create programs that interact with the XenServer pool. There are some function calls that return metrics of the virtual machines and the physical hosts.

Let us have a look at retrieving the CPU load of a virtual machine (VM). This can be accomplished with the following API call (assuming that vm is of type com.xensource.xenapi.VM and connection is of type com.xensource.xenapi.Connection):

vm.getMetrics(connection).getVCPUsUtilisation(connection)

However, as many have noted, the answer is always 0.0. As of XenServer version 5.5, the way these metrics are stored has changed. The preferred way to get VM metrics now, is to make a direct HTTP call to the physical hosts. This call will return RRD XML files. This makes things more difficult because now there are multiple calls to make, one to the XenServer API and one call per physical host machine. And one needs to dig into these files to get the CPU load, instead of having the value returned in a single call.

There is a way to make the XenServer API behave like it did in version 5.0 and prior. We start by logging into the console of a physical machine and entering:

xe host-list

Note the UUID values of all the physical host machines. Now enter the following command for each UUID:

xe host-param-set uuid=<uuid found in previous command> other-config:rrd_update_interval=1

Now reboot all physical host machines and the VM metric command will work like a charm.

Using OpenJMS within Eclipse

OpenJMS allows you to use the Java Message Service (JMS) without a full-fledged Java Enterprise Edition container. It is an open source implementation of the JMS 1.1 specification.

We start by installing and starting OpenJMS. On Windows this is done by extracting the .zip file, going to the bin directory and calling startup.bat. On Linux this is done by extracting the .tar.gz file, going to the bin directory and calling startup.sh.

The next part is creating a Java project in Eclipse. Make sure to create the following directories:

  • bin, containing your own Java .class files
  • etc, containing the JNDI configuration file
  • lib, containing all required .jar library files
  • src, containing your own Java .java files

Start by copying all .jar files from the OpenJMS distribution to the lib directory and tell Eclipse to use these .jar files. Also add the etc directory to the build path. This ensures that the JNDI configuration file that we will create shortly is used at runtime.

Now create the JNDI configuration file that will tell our application where to find the running OpenJMS server. Create a file called jndi.properties with the following content:

java.naming.factory.initial=org.exolab.jms.jndi.InitialContextFactory
java.naming.provider.url=tcp://localhost:3035

Finally, we move on to the actual Java code that makes use of this groundwork. We create a message sender that sends a message to the topic topic1. This is a topic name that is available in OpenJMS by default.

MessageSender.java

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.naming.Context;
import javax.naming.InitialContext;

public class JMSSender {

   public void start() {
      Context context = null;
      Connection connection = null;
      MessageProducer sender = null;
      try {
         context = new InitialContext();
         ConnectionFactory factory = (ConnectionFactory) context.lookup("ConnectionFactory");
         connection = factory.createConnection();
         connection.start();

         Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
         Destination destination = (Destination) context.lookup("topic1");
         sender = session.createProducer(destination);
         sender.send(session.createTextMessage("Hello World!"));
      } catch (Exception e) {
      } finally {
         try {
            if (sender != null) sender.close();
            if (connection != null) connection.close();
            if (context != null) context.close();
         } catch (Exception e) {
         }
      }
   }

   public static void main(String[] args) {
      JMSSender jmsSender = new JMSSender();
      jmsSender.start();
   }
}

MessageReceiver.java

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageListener;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

public class JMSReceiver {

   public void start() throws JMSException, NamingException {
      Context context = null;
      Connection connection = null;
      MessageConsumer receiver = null;
      try {
         context = new InitialContext();
         ConnectionFactory factory = (ConnectionFactory) context.lookup("ConnectionFactory");
         connection = factory.createConnection();
         Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
         Destination destination = (Destination) context.lookup("topic1");

         receiver = session.createConsumer(destination);
         receiver.setMessageListener(new MessageListener() {
            public void onMessage(Message message) {
               TextMessage text = (TextMessage) message;
               try {
                  System.out.println("Received message: " + text.getText());
               } catch (JMSException e) {
               }
            }
         });

         connection.start();
      } catch (Exception e) {
      }
   }

   public static void main(String[] args) {
      JMSReceiver jmsReceiver = new JMSReceiver();
      jmsReceiver.start();
   }
}

Now start the JMSReceiver application and then the JMSSender application. If all goes well, the JMSReceiver application should print the text:

Received message: Hello World!

Using the sage mathematical software system


This article describes the installation and simple usage of the Sage mathematical software system. Sage is free, open-source math software that supports research and teaching in algebra, geometry, number theory, cryptography, numerical computation, and related areas.

We start by installing Sage on Ubuntu:

sudo apt-get install sagemath

Let’s take a look at what the Sage commandprompt can give us:

sage

This will present you with a prompt that says “sage:”. You can type things here that Sage will try to understand and solve. For example, if we type “2+3″, Sage will respond with “5″:

sage: 2+3
5

Now let’s try to solve something a bit more difficult:

sage: a, b = var('a, b')
sage: solve([a + b == 12, a - b == 6], [a, b])
[[a == 9, b == 3]]

There are numerous functions you can use. We will show some of them here:

sage: factor(60)
2^2 * 3 * 5

sage: is_prime(1234567891)
True

sage: gcd(100, 24)
4

Using some Python magic, we can do things like:

sage: [factor(n) for n in range(2, 10)]
[2, 3, 2^2, 5, 2 * 3, 7, 2^3, 3^2]