RESTful Web Service - How To???

rgansevles:
Omar,

Do you have elements on the form?

Try use a form with the ws_* methods and no UI elements on the form.

Rob

I need to get some data out of an existing application using Resful and have just tested the servoy_sample_rest_ws solution. Like Omar I am also getting a 500 error in the demo both with and without elements on the WS_* form. When displayed in the smart client the form with elements correctly shows there is data, so I am slightly confused as to why it would throw a 500 error in the browser, there is data, the is a form and the database is connected.

SO to clarify:

  • should there be elements on the form ?? as reading Robs comments it appears not ?
  • Is there anything that needs to be set up as far as the plugin in concerned or should this work immediately ?
  • I have navigated to the example page http://localhost:8080/examples/restfulws_testpage.html which is what I am using to test
  • the response is attached but in short the server is reporting and internal error

If you have a 500 error, then you should have some exceptions in your servoy_log.txt. Have you looked in there?

Thanks Patrick - the first thing I should have done is re boot the server and on doing this it fixed the problem. Having said which the XML returned throws an error as being incomplete when viewed in Safari - Closing tags missing

Safari Response:

This page contains the following errors:
error on line 2 at column 20: Extra content at the end of the document
Below is a rendering of the page up to the first error.

This is the actual response:

<?xml version="1.0" encoding="UTF-8"?>
<array>null</array><array>1</array><array>2</array><array>3</array><array>4</array><array>5</array><array>6</array><array>7</array><array>9</array><array>10</array><array>11</array><array>12</array><array>13</array><array>14</array><array>15</array><array>16</array><array>17</array>

I have not tested this in JQuery but wonder if it needs wrapping or something ?? any thoughts appreciated

Cheers
Gordon

Well formed XML has usually only one root element. In your case it is missing…

I suppose you are returning an array, but I think the rest_ws plugin is expecting an object, so maybe you should encapsulate your array inside a simple object in your ws_ method, something like:

var obj = {root: myArray};
return obj;

Actually looking at the plugin code, you can also return an XML object, so you can create it yourself the way you want it, but make sure that it has only one root element.

ptalbot:
Well formed XML has usually only one root element. In your case it is missing…

I suppose you are returning an array, but I think the rest_ws plugin is expecting an object, so maybe you should encapsulate your array inside a simple object in your ws_ method, something like:

var obj = {root: myArray};

return obj;

Hi Patrick
I thought it would be useful to continue this thread as I am sure others would use the outcome. I have tested restful against the Servoy demo app which is how I got the previous example - so that is the result of the demo. I have put in a trial script to simply return to the console what Servoy is outputting and got:

Servoy Console
{id:6,firstName:Michael,lastName:Suyama}

Firefox Input:
http://localhost:8080/servoy-service/re … mployees/6

Firefox Console:
Error: junk after document element
Source File: http://localhost:8080/servoy-service/re … mployees/6
Line: 2, Column: 11
Source Code:
6SuyamaMichael

Servoy Function - as per Servoy Resful Demo

function ws_read(id)
{
	if (id)
	{
		// read 1 employee
		if (foundset.find())
		{
			foundset.employeeid = id
			if (foundset.search() == 1)
			{
				var emp = new Object()
				emp.id = foundset.employeeid
				emp.firstName = foundset.firstname
				emp.lastName = foundset.lastname
				return emp // response body
			}
		}
	}
	else
	{
		// list employee ids
		foundset.sort("employeeid asc")
		if (foundset.loadAllRecords())
		{
			var empids = new Array()
			for (i = 1; i <= foundset.getSize(); i++)
			{
				empids[i] = foundset.getRecord(i).employeeid
			}
			return empids // response body
		}
	}

	// not found or cannot search
	return null;
}

…and finally I am trying to call it with and $.ajax call

$.ajax({url:‘http://localhost:8080/servoy-service/rest_ws/servoy_sample_rest_ws/ws_employees/’,
//dataType:‘JSON’,
success: function(data) {
alert(‘success’);
},
error: function(){
alert(‘fail’);
}
});

So overall what I think is going on here is what is being fed into the restful plugin in an object which is in turn formatted as JSON if viewed in the Servoy Console. When this is parsed by the browser its converted to what looks like XML with the tail missing. I have tried a number of approaches to fix this and thus far its bouncing off. The reason I think this would be generally useful is IF it could be made to work then those wishing to use apps like JQuery, JQMobile and JQTouch would be able to get Servoy to handle the data and the JQ to deal with the UI.

Cheers
Gordon

I’ve been working a lot with RESTful web services in the past few weeks, and I have it functioning fairly well…

Testing in a browser is a nightmare, and i’ve found it easiest to use the WizTools RESTClient - a little java app that allows you to test all sorts of web requests and see the results - http://code.google.com/p/rest-client/

Here’s a quick snippet that should work…

function ws_read(){


		//simple sql query to grab all the columns from the companies table...
		
		var sql = 'SELECT * FROM companies'
		
		//create a new dataset using the sql query
		var ds = databaseManager.getDataSetByQuery(controller.getServerName(),sql,null,-1) 
		
		//create a new object you'll return to the client
		var r = new Object()
		
		//loop through the rows of the results of the sql query
		for(var i=1; i<= ds.getMaxRowIndex(); i++){
			
			//for each row, create a new company object
			var newCompany = new Object()
				
				//loop through the columns from the result set
				for(var j=1; j<=ds.getMaxColumnIndex(); j++){
			
				//add each column name and value to the newCompany object 
				newCompany[ds.getColumnName(j)] = ds.getValue(i,j) }
			
			
			//add each company to the object you are returning...
			r[i] = newCompany
			
			

			
			}
//return the object to the client
return r
}

Great thanks for the post, I will give it a try.

If you get that working, then you can abstract it a little bit more

just declare the parameters you want to catch, and then you can use them inside the method… in this case i’m just passing the table name i want to run the query on. the challenge of the RESTful stuff is designing an intelligent way of handling parameters, so you don’t have to write hundreds of different methods. The thing i keep reading about REST is that it’s about nouns, not verbs… so you should think in terms of manipulating objects at locations, i.e. "…rest_ws/baseForm/employees/123 rather than verbs “…rest_ws/baseForm/addNewEmployeeMethod”

//url is .../rest_ws/formName/tableName

function ws_read(tableName){



		//grab the passed parameter and add it on to the sql query. be careful here with formatting!
				

		var sql = 'SELECT * FROM ' + tableName
		
		//create a new dataset using the sql query
		var ds = databaseManager.getDataSetByQuery(controller.getServerName(),sql,null,-1) 
               
               //etc

Hello everyone,

I’m having trouble returning a properly formatted XML. I did a simple excercise following robwormald’s example. This is the code:

function ws_read(){
							
						var retVal = new Object();

						var objCustomer = new Object();
						objCustomer.name = "Giuliana Casanova";
						objCustomer.age = 22;
						objCustomer.gender= "F";
						objCustomer.address= "Sun Avenue, Earl Street No.1839"
						
						retVal[1] = objCustomer;
						
						objCustomer = new Object();
						objCustomer.name = "Matt Marineikis";
						objCustomer.age = 31;
						objCustomer.gender= "M";
						objCustomer.address = "West Huntington Ave. CT21231"
						
						retVal[2] = objCustomer;
						
						return retVal;
}

However, that code returns this:

<?xml version="1.0" encoding="UTF-8"?>
<2>
  <address>West Huntington Ave. CT21231</address>
  <age>31.0</age>
  <name>Matt Marineikis</name>
  <gender>M</gender>
</2>
<1>
  <address>Sun Avenue, Earl Street No.1839</address>
  <age>22.0</age>
  <name>Giuliana Casanova</name>
  <gender>F</gender>
</1>

As you can see, it doesn’t return a proper XML, since it lacks a unique root element. Am I missing something?

Thanks,
jd2p

You define your retVal as an object, but then you use it as an array.
While it’s perfectly legal JavaScript code, the chances are that the Java code that will transform your object to XML is seeing it as an array.

You could try:

function ws_read(){
                     
                  var retVal = new Object();
                  retVal.customers = new Array();

                  var objCustomer = new Object();
                  objCustomer.name = "Giuliana Casanova";
                  objCustomer.age = 22;
                  objCustomer.gender= "F";
                  objCustomer.address= "Sun Avenue, Earl Street No.1839"
                  
                  retVal.customers.push(objCustomer);
                  
                  objCustomer = new Object();
                  objCustomer.name = "Matt Marineikis";
                  objCustomer.age = 31;
                  objCustomer.gender= "M";
                  objCustomer.address = "West Huntington Ave. CT21231"
                  
                  retVal.customers.push(objCustomer);
                  
                  return retVal;
}

This way, you return an object with one property (which will be your root), and Java will treat it as an object and not an array.

Hope this helps,

Excellent Patrick, you set me in the right direction!

I just did a little tweak to have a single root node, this is how left it:

var retVal = new Object();
retVal.customers = new Object();
retVal.customers.customer = new Array();

var objCustomer = new Object();
objCustomer.name = "Giuliana Casanova";
objCustomer.age = 22;
objCustomer.gender= "F";
objCustomer.address= "Sun Avenue, Earl Street No.1839"

retVal.customers.customer.push(objCustomer);

objCustomer = new Object();
objCustomer.name = "Matt Marineikis";
objCustomer.age = 31;
objCustomer.gender= "M";
objCustomer.address = "West Huntington Ave. CT21231"

retVal.customers.customer.push(objCustomer);
	                  
return retVal;

And that returned a properly formatted XML.

Thanks Patrick!