Monday, October 20, 2014

RESTing...

Let's take Informix for RESTing (original version here)

English version
After a couple of tiring weeks I feel it's time for a REST. Naturally I'm playing with words, and I'm referring to the new Informix ability to answer REST API requests. This was introduced recently in version 12. REST is the acronym for REpresental State Transfer. Very basically this is an architecture design that can be used to implement web services, or in a very simplistic manner a way to offer services based on HTTP requests.
IBM gave Informix the ability to answer REST requests. This was implemented using the same listener code that was previously introduced to accept MongoDB API protocol. But now we can start the listener with a different configuration that turns it into a REST gateway. In very generic terms we can map the following HTTP methods to SQL requests:

  • HTTP GET
    Select
  • HTTP POST
    Insert
  • HTTP PUT
    Update
  • HTTP DELETE
    Delete
The setup is very easy. Just locate the file jsonListener-example.properties in your $INFORMIXDIR/etc folder and change a couple of properties. For simplicity I deactivated authentication. The properties I changed were:
  • authentication.enable=false
  • authentication.localhost.bypass.enable=true
  • database.dbspace=dbs1
  • database.locale.default=en_US.819
  • listener.port=30001
    The TCP port where I'll receive REST requests
  • listener.type=rest
    To configure this listener as a REST listener (as opposed to MongoDB API listener)
  • security.sql.passthrough=true
  • url=jdbc:informix-sqli://primary:10020/sysmaster:INFORMIXSERVER=alfama;USER=informix;PASSWORD=password;DB_LOCALE=en_US.819
I saved the new file as jsonListener-rest.properties and then I started the new listener:
java -cp $INFORMIXDIR/bin/jsonListener.jar:/usr/informix/tomcat/tomcat-embed-core.jar com.ibm.nosql.informix.server.ListenerCLI -config $INFORMIXDIR/etc/jsonListener-rest.properties -logfile /usr/informix/logs/alfama.jsonListener-rest.log -start

Now we're in conditions to send REST requests to the database. The answers will be received in JSON format. In order to try this I created a very simple HTML page using some JavaScript. The code is:
<html>
<head>
<title>Informix REST access&lt/title>

<script language="JavaScript" type="text/javascript">

function ajaxget(){
   var mygetrequest=new XMLHttpRequest();
   mygetrequest.onreadystatechange=function(){
      if (mygetrequest.readyState==4){
         if (mygetrequest.status==200 || window.location.href.indexOf("http")==-1){
            document.getElementById("result").innerHTML = mygetrequest.responseText;
         }
         else{
            alert("An error has occured making the request");
         }
      }
    }
    var customerNum = encodeURIComponent(document.getElementById("customerNum").value);
    mygetrequest.open("GET", "http://primary:30001/stores/customer?query="+encodeURIComponent("{customer_num:"+customerNum+"}"), true);
    mygetrequest.send(null);
}

</script>

<body>

<form action="javascript:ajaxget()" method="get">
   <table>
    <tr>
       <td>Customer Num:</td>
       <td><input id="customerNum" name="customerNum" size="30" type="text" /></td>
    </tr>
    <tr>
      <td></td><td><input onclick="ajaxget()" type="button" value="submit" >
</td&gt
    </tr>
   </table>
</form>

<div id="result">
</div>
</body>

This translates into this page:



 And if we type a customer number, let's say "101" and press ENTER or Submit, it will call the REST API which will return a JSON document that we display:



For clarity, the JSON response was:
{
"customer_num":101,
"fname":"Ludwig",
"lname":"Pauli",
"company":"All Sports Supplies",
"address1":"213 Erstwild Court",
"address2": null ,
"city":"Sunnyvale",
"state":"CA",
"zipcode":"94086",
"phone":"408-789-8075"
}
This might sound familiar, as it's the same result you'd get from:
SELECT * FROM customer WHERE customer_num = 101;

How did I do it? Very simply just by sending a GET HTTP request with the following details:
http://primary:30001/stores/customer?query={customer_num:"101"}


Let's split this:
  • primary:30001
    hostname:port where the listener is listening
  • /stores
    The database name
  • /customer
    The table
  • query={customer_num:"101"}
    The "WHERE clause", in this case just
Very simple. For more detailed information please check the JSON compatibility guide. What I'd like to stress is how easy it is to reach Informix and get and put data on it. No drivers. Just the omnipresent language of today, called JavaScript. You can use it in your browsers, or in server side applications using Node.js and any of the well known application development frameworks that use Javascript.


Versão Portuguesa
Depois de um par de semanas bem cansativas, penso que é tempo para REST. Sim, estou a brincar com as palavras, e refiro-me à nova funcionalidade do Informix para responder a pedidos REST. Isto foi introduzido recentemente na versão 12. REST é o acrónimo para REpresental State Transfer. De forma muito simples isto é uma arquitetura que permite disponibilizar web services baseados em pedidos HTTP.
A IBM deu ao Informix a possibilidade de responder a pedidos REST. Isto foi implementado usando o mesmo código Java que permite ter um listener para a API do MongoDB. Mas agora podemos iniciar o listener com um ficheiro de configuração diferente que o torna num gateway REST. De uma forma ainda muito genérica podemos mapear os seguintes métodos HTTP nos respectivos tipos de instrução SQL:
  • HTTP GET
    Select
  • HTTP POST
    Insert
  • HTTP PUT
    Update
  • HTTP DELETE
    Delete
A configuração é muito fácil. Basta procurar o ficheiro jsonListener-example.properties em $INFORMIXDIR/etc e mudar algumas propriedades. Por simplicidade desactivei a autenticação. As propriedades que mudei foram::
  • authentication.enable=false
  • authentication.localhost.bypass.enable=true
  • database.dbspace=dbs1
  • database.locale.default=en_US.819
  • listener.port=30001
      O porto TCP onde irei receber os pedidos REST
  • listener.type=rest
    To configure this listener as a REST listener (as opposed to MongoDB API listener)
  • security.sql.passthrough=true
  • url=jdbc:informix-sqli://primary:10020/sysmaster:INFORMIXSERVER=alfama;USER=informix;PASSWORD=password;DB_LOCALE=en_US.819
Gravei o novo ficheiro com o nome jsonListener-rest.properties e depois lancei o novo listener:
java -cp $INFORMIXDIR/bin/jsonListener.jar:/usr/informix/tomcat/tomcat-embed-core.jar com.ibm.nosql.informix.server.ListenerCLI -config $INFORMIXDIR/etc/jsonListener-rest.properties -logfile /usr/informix/logs/alfama.jsonListener-rest.log -start

Estamos agora em condições de enviar pedidos REST para a base de dados. As respostas serão recebidas em formato JSON. Para testar isto criei uma página HTML muito simples, com uma função em JavaScript. Eis o código:
<html>
<head>
<title>Informix REST access&lt/title>

<script language="JavaScript" type="text/javascript">

function ajaxget(){
   var mygetrequest=new XMLHttpRequest();
   mygetrequest.onreadystatechange=function(){
      if (mygetrequest.readyState==4){
         if (mygetrequest.status==200 || window.location.href.indexOf("http")==-1){
            document.getElementById("result").innerHTML = mygetrequest.responseText;
         }
         else{
            alert("An error has occured making the request");
         }
      }
    }
    var customerNum = encodeURIComponent(document.getElementById("customerNum").value);
    mygetrequest.open("GET", "http://primary:30001/stores/customer?query="+encodeURIComponent("{customer_num:"+customerNum+"}"), true);
    mygetrequest.send(null);
}

</script>

<body>

<form action="javascript:ajaxget()" method="get">
   <table>
    <tr>
       <td>Customer Num:</td>
       <td><input id="customerNum" name="customerNum" size="30" type="text" /></td>
    </tr>
    <tr>
      <td></td><td><input onclick="ajaxget()" type="button" value="submit" >
</td&gt
    </tr>
   </table>
</form>

<div id="result">
</div>
</body>

Isto traduz-se na seguinte página:



E se inserirmos um número de cliente, digamos o "101" e dermos ENTER ou Submit, o código irá chamar a REST API, que por sua vez retorna um documento JSON que mostramos abaixo:



Por clareza, a resposta JSON foi:
{
"customer_num":101,
"fname":"Ludwig",
"lname":"Pauli",
"company":"All Sports Supplies",
"address1":"213 Erstwild Court",
"address2": null ,
"city":"Sunnyvale",
"state":"CA",
"zipcode":"94086",
"phone":"408-789-8075"
}
Isto pode parecer familiar, pois é o mesmo resultado que se obtém com:
SELECT * FROM customer WHERE customer_num = 101;

Como é que o fiz? Muito simplesmente enviando um pedido HTTP GET com os seguintes detalhes:
http://primary:30001/stores/customer?query={customer_num:"101"}

Vamos partir isto:
  • primary:30001
    Nome da máquina e porto onde o listener está à escuta
  • /stores
    O nome da base de dados
  • /customer
    A tabela
  • query={customer_num:"101"}
    A cláusula "WHERE", neste caso apenas com um filtro na coluna customer_num com o ovalor 101
Muito simples. Para informação mais detalhada consulte o guia de compatibilidade JSON. O que gostaria de salientar é quão fácil é alcançar o Informix e obter ou enviar dados para ele. Sem drivers. Apenas com a linguagem omnipresente dos dias de hoje, o JavaScript. Pode usá-la nos browsers ou do lado do servidor com Node.js e qualquer uma das suas famreworks de desenvolvimento aplicacional que usam JavaScript