Sunday, June 10, 2007

Working with JMaki

I recently had an opportunity to use some of the JMaki UI components and it took me some googling to figure out how to pass data dynamically (which is what most of the time you will want and unfortunately all examples use some static data in the JSON format) to the UI components. JMaki's integration with Netbeans makes it really simple to have those nice Web UI components working for you in a jiffy (like grid, tree, menu, captcha, autocomplete etc). Though i am a big fan of DWR (having used the reverse ajax in DWR 2.0 for an event browser application to show events in real-time) for Ajax support in my work, i did like the Ajax-enabled UI Components that come with JMaki. Another nice thing about JMaki is, it provides a common data model for multiple implementations of a certain UI component. For example, you have a Yahoo UI Tree and a dojo toolkit tree component. Since JMaki provides the abstraction by keeping the data models same for both these tree components, so we have the option to switch between these implementations with almost no change to code.

Now going back to the point (the reason i am writing this post after all) ... the JMaki components accept data dynamically in JSON format and though one can create the JSON format string to pass as value attributes to the widgets, it becomes cumbersome for widgets like trees or grid to escape the quotes and construct the strings. To make our lives easy in constructing the JSON formatted dynamic data, JMaki comes bundled with org.json.* classes (JSONObject, JSONArray etc) using which one can create the data to pass in an elegant and maintainable way. You will need to convert the JSONObject or JSONArray types to their Object literal form using the following code which Greg Murray (JMaki project manager) released in reply to one post on JMaki users forum:


/**
* Converts a JSON Object to an Object Literal
*
*
* @param jo
* @param buff
*
* @return
*
* @throws JSONException
*/
public static String jsonToObjectLiteral(JSONObject jo, StringBuffer buff)
throws JSONException
{
if (buff == null) {
buff = new StringBuffer("{");
} else {
buff.append("{");
}

JSONArray names = jo.names();

for (int l = 0; (names != null) && (l < names.length()); l++) {
String key = names.getString(l);
String value = null;

if (jo.optJSONObject(key) != null) {
value = key + ":";
buff.append(value);
jsonToObjectLiteral(jo.optJSONObject(key), buff);
} else if (jo.optJSONArray(key) != null) {
value = key + ":";
buff.append(value);
jsonArrayToString(jo.optJSONArray(key), buff);
} else if (jo.optLong(key, -1) != -1) {
value = key + ":" + jo.get(key) + "";
buff.append(value);
} else if (jo.optDouble(key, -1) != -1) {
value = key + ":" + jo.get(key) + "";
buff.append(value);
} else if (jo.opt(key) != null) {
Object obj = jo.opt(key);

if (obj instanceof Boolean) {
value = key + ":" + jo.getBoolean(key) + "";
} else {
value = key + ":" + "'" + jo.get(key) + "'";
}

buff.append(value);
}

if (l < names.length() - 1) {
buff.append(",");
}
}

buff.append("}");

return buff.toString();
}

/**
* Converts a json array to string.
*
*
* @param ja
* @param buff
*
* @return
*
* @throws JSONException
*/
public static String jsonArrayToString(JSONArray ja, StringBuffer buff)
throws JSONException
{
if (buff == null) {
buff = new StringBuffer("[");
} else {
buff.append("[");
}

for (int key = 0; (ja != null) && (key < ja.length()); key++) {
String value = null;

if (ja.optJSONObject(key) != null) {
jsonToObjectLiteral(ja.optJSONObject(key), buff);
} else if (ja.optJSONArray(key) != null) {
jsonArrayToString(ja.optJSONArray(key), buff);
} else if (ja.optLong(key, -1) != -1) {
value = ja.get(key) + "";
buff.append(value);
} else if (ja.optDouble(key, -1) != -1) {
value = ja.get(key) + "";
buff.append(value);
} else if (ja.optBoolean(key)) {
value = ja.getBoolean(key) + "";
buff.append(value);
} else if (ja.opt(key) != null) {
Object obj = ja.opt(key);

if (obj instanceof Boolean) {
value = ja.getBoolean(key) + "";
} else {
value = "'" + ja.get(key) + "'";
}

buff.append(value);
}

if (key < ja.length() - 1) {
buff.append(",");
}
}

buff.append("]");

return buff.toString();
}


So, after you have your dynamic data put in JSONObject or JSONArray, you can invoke the corresponding conversion method stated above to get the String form of your JSON data ready to be passed to the component.

For instance, in your tree builder code, you will need to do the following (the example is from this post where the solution was posted by Greg Murray):


public static JSONObject buildTreeData(AuthorizedTeams ateams)
throws JSONException {

JSONObject retValue = new JSONObject();
JSONObject root = new JSONObject();
root.put ("title", "Organizations");
root.put ("expanded", true);
JSONArray data = new JSONArray();

Team[] teams = ateams.getTeams();

for (int i=0; i<teams.length; i++) {
JSONObject teamObj = new JSONObject();
teamObj.put("title", teams[i].getTeamName());
teamObj.put("expanded", true);

JSONArray children = new JSONArray();

User[] teamUsers = teams[i].getMembers();
for (int j=0; j<teamUsers.length; j++) {
JSONObject childObj = new JSONObject();
childObj.put("title",teamUsers [j].getUserName());
children.put(childObj);
}
teamObj.put("children", children);
data.put(teamObj);
}
root.put ("children", data);
retValue.put ("root", root);

return jsonToObjectLiteral(retValue, new StringBuffer());
}

Here is the JSP snippet:

<jsp:useBean id="teams"
class="com.myapp.assignment.AuthorizedTeams"
scope="request"/>
<a:widget name="dojo.tree" value="${teams.teamsData}">

4 comments:

Ammu said...

Hi Rajneesh!!

I was using jmaki static yahoo tree control in my application but as the requirement moved ahead we need to populate jMaki tree from the database, I am really confused and need help to move further. I need to create node names and their respective sub-nodes from the database. I will very thankful to get any help on this.

regards
Amair

Anonymous said...

Hi,
I would also appreciate a sample of binding tree to database.

Thanks

Anonymous said...

Making goonzu gold
is the old question : Honestly there is no fast way to make lots of goonzu money
. Sadly enough a lot of the people that all of a sudden come to with millions of goonzu online gold
almost overnight probably duped . Although there are a lot of ways to make lots of cheap goonzu gold
here I will tell you all of the ways that I know and what I do to buy goonzu gold.

As a new player , you may need some game guides or information to enhance yourself.
gw gold is one of the hardest theme for every class at the beginning . You must have a good way to manage yourGuildWars Gold.If yor are a lucky guy ,you can earn so many Guild Wars Gold by yourself . But if you are a not , I just find a nice way to get GuildWars money. If you need , you can buy cheap gw gold at our website .

Anonymous said...

aion chinaaion china gold,
aion cn goldaion chinese gold,
aion gold chinaaion gold chinese,
china aion goldchinese aion gold,
aion china kinaaion chinese kina,
aion kina chinachina aion kina,
aion china buybuy aion china,
aion chinese server

gold
aion cn server

gold
,
aion china server goldchina aion server gold,
chinese aion server

gold
aion chinese server

gold
,
aion cn server kinaaion china server kina,
china aion server kinachinese aion server kina