Japod's blog
Archives
« May 2008
SunMonTueWedThuFriSat
    
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
       
Today
Click me to subscribe
Search

Links
 

View My Stats
Main | Next page »
Friday May 09, 2008
jMaki Putting Data to Jersey

In this post I have described how to make jMaki widgets consume Jersey based web resources. In a read-only manner.

Here I would like to show how to close the circle and make jMaki widgets push an updated information back to the Jersey. Many thanks to Greg Murray who has spent some time with me on Monday to put the following piece of code together.

The most important part of it is emphasized and shows how to actually make a PUT request
using jMaki function doAjax


jmaki.subscribe("/dojo/etable/onCellEdit", function(arg) {
jmaki.doAjax({
url: "/jMakiBackend/webresources/printers/ids/"+arg.row,
headers:[{name:"Accept", value:"application/json"}],
callback:function(ar){
var i = eval("("+ar.responseText+")");
var cols = ["id", "model", "url", "location"]
eval("i." + cols[arg.column]+"='"+arg.value+"'");
jmaki.doAjax({
url: "jMakiBackend/webresources/printers/ids/"+arg.row,
headers:[{name:"Content-type", value:"application/json"}],
method:"PUT",
body : jmaki.json.serialize(i)
})

}
})
})

All you need to make it work is to

Then you should be able to update an information in the table widget and see it updated also in the underlaying web resource representation. I have not tried, but suppose that updating printer ids shouldn't work ;-)


Wednesday Apr 23, 2008
Missing Brackets At JSON One-Element Arrays In Jersey

It is a bit uncomfortable, but if you need to deal with arrays in JSON produced by Jersey,
you will need to provide a custom JAXB context resolver to make sure brackets are properly used
in one-element arrays.

As Reece Garrett pointed out,
the very same issue was hit (and resolved) in Jettison as well.

What is exactly the issue?

Lets say, you have the following JAXB bean


@XmlRootElement
public class ArrayWrapper {
public List<String> list = new LinkedList<String>();
}

and want to get JSON out of it. The issue is, that after


ArrayWrapper aw = new ArrayWrapper();
aw.list.add("one");

you will get


{"list":"one"}

while if you add one more element


aw.list.add("two");

you will get this:


{"list":["one", "two"]}

Please note the missing brackets at the former case.

Solution

In order to have the brackets properly used also for one-element arrays you need to provide your
custom JAXB context through which you can tell the underlying JSON writer what is an array.

It can look like this:


@Provider
public class JAXBContextResolver implements ContextResolver<JAXBContext> {

private JAXBContext context;
private Class[] types = {ArrayWrapper.class};

public JAXBContextResolver() throws Exception {
Map props = new HashMap<String, Object>();
props.put(JSONJAXBContext.JSON_NOTATION, "MAPPED");
props.put(JSONJAXBContext.JSON_ROOT_UNWRAPPING, Boolean.TRUE);
props.put(JSONJAXBContext.JSON_ARRAYS, "[\"list\"]");
this.context = new JSONJAXBContext(types, props);
}

public JAXBContext getContext(Class<?> objectType) {
return (types[0].equals(objectType)) ? context : null;
}
}

JSONJAXBContext.JSON_ARRAYS property here takes a JSON array with names of elements representing arrays
in you JAXB beans. Having the resolver in place for the example above you will now obtain


{"list":["one"]}


Friday Apr 11, 2008
Historicky první setkání Java teamu na Slovensku

Včera jsem měl velkou čest zúčastnit se historicky vůbec prvního setkání tzv. Java Teamu na Slovensku.

Javateam je něco, co v Čechách známe pod pojmem Java User Group. (všimněte si, jak velmi neanglicky/neamericky oba typy označení působí). Vystoupil jsem s prezentací projektu GlassFish -- Java EE 5 aplikačního serveru, přičemž polovinu "slajdů" jsem "převzal" od Martina Grebače a druhou polovinu od Alexis Moussine-Pouchkine(a). "Pánové: ďakujem, merci bien, спасибо!" Výslednou kompilaci slajdů můžete vidět zde.


Sunday Mar 09, 2008
Jersey 0.6 Available On GlassFish Update Center

New features are described in Paul's blog entry here.

See this blog entry (about Jersey module v 0.2.1) describing how to run GlassFish

update center client and get the Jersey module installed.


Saturday Feb 23, 2008
jMaki Widgets Talking To Jersey Resources In JSON

In the recent post, i have announced an improvement in JSON format produced by Jersey.
Here i would like to show how you can easily consume the new format by jMaki widgets.
An example of what you can get is shown below.

Jersey back-end resources are already available within Jersey examples as jMakiBackend web application. You just need to obtain the latest Jersey bundle and then build and deploy the jMakiBackend example via following:


% cd jersey-0.6-ea/examples/jMakiBackend
% ant
% $AS_HOME/bin/asadmin start-domain
% $AS_HOME/bin/asadmin deploy dist/jMakiBackend.war

You can then test your Jersey resources:


% curl http://localhost:8080/jMakiBackend/webresources/printers/jMakiTable
{"columns":[{"id":"id","label":"Printer ID"},
{"id":"model","label":"Model"},{"id":"url","label":"URL"},{"id":"location","label":"Location"}],
"rows":[{"id":"P05","model":"Xerox345","url":"lpd://p05","location":"room 543"},
{"id":"P02","model":"OKI123","url":"lpd://p02","location":"room 12"},
{"id":"P06","model":"Xerox345","url":"lpd://p06","location":"room 203"},
{"id":"P03","model":"OKI123","url":"lpd://p03","location":"room 133"},
{"id":"P01","model":"OKI123","url":"lpd://p01","location":"room 1"}]}


%curl http://localhost:8080/jMakiBackend/webresources/printers/jMakiTree
{"root":{"label":"printers","expanded":true,
"children":[{"label":"Model Xerox345","expanded":true,"children":
[{"label":"P05 @ room 543","expanded":false},
{"label":"P06 @ room 203","expanded":false}]},
{"label":"Model OKI123","expanded":true,"children":
[{"label":"P02 @ room 12","expanded":false},
{"label":"P03 @ room 133","expanded":false},
{"label":"P01 @ room 1","expanded":false}]}]}}

Connecting jMaki widgets is very simple.
You just create a new web application in Netbeans 6 (provided you have jMaki/AJAX plugin already installed), drag and drop Yahoo table or Dojo tree widget to your page and set the widget service parameter to an appropriate URI.

Besides the two jMaki friendly resources, you can also manipulate the underlaying data
via http://localhost:8080/jMakiBackend/webresources/printers/ids/{printerid} URI.
GET, PUT and DELETE HTTP methods are available on it providing access to getting,
creating/updating and deleting particular printer records.


%curl http://localhost:8080/jMakiBackend/webresources/printers/ids/P01
{"id":"P01","model":"OKI123","url":"lpd://p01","location":"room 1"}


%curl -i -X PUT -HContent-type:application/json \
--data '{"id":"P01","model":"OKI123456","url":"lpd://p01.b02","location":"big showroom"}' \
http://localhost:8080/jMakiBackend/webresources/printers/ids/P01
HTTP/1.1 204 No Content
X-Powered-By: Servlet/2.5
Server: Sun Java System Application Server 9.1.1
Date: Sat, 23 Feb 2008 08:15:01 GMT


% curl -i -X DELETE http://localhost:8080/jMakiBackend/webresources/printers/ids/P01
HTTP/1.1 204 No Content
X-Powered-By: Servlet/2.5
Server: Sun Java System Application Server 9.1.1
Date: Sat, 23 Feb 2008 08:17:29 GMT

For detailed information on JAXB beans used for the jMaki models please look at the jMakiBackend example code here and here


Friday Feb 22, 2008
Better JSON Available In Jersey

Since today a better support for JSON data generated out of JAXB beans is available in Jersey.

The main improvement is a simpler default JSON data format.
Badgerfish convention was replaced by a new one, a slightly simplified so called mapped convention from Jettison. JSON convention used for particular beans is now also fully configurable by the end user.
I will show how the configuration could be done below.

The main differences between available formats could be described using the following example.
Lets start with a very simple JAXB bean. You can see the source code, XML output and then
all formats you can get from Jersey resource:


@XmlRootElement
public static class SimpleJaxbBean {
public String name = "Franz";
public String surname = "Kafka";
}

XML output:


<simpleJaxbBean>
<name>Franz</name>
<surname>Kafka</surname>
</simpleJaxbBean>

Badgerfish format:


{"simpleJaxbBean":{"name":{"$":"Franz"},"surname":{"$":"Kafka"}}}

Mapped format (Jettison):


{"simpleJaxbBean":{"name":"Franz","surname":"Kafka"}}

and finally Jersey default format:


{"name":"Franz","surname":"Kafka"}

If you want to control, which format is actually used for which JAXB bean,
you can do it by providing Jersey runtime with your own custom JAXBContext classes
via implementing custom ContextResolver.

You can get inspired by following example:


@Path("/jsonFormats")
public class SimpleJsonResource {
@Provider
public static class JAXBContextResolver implements ContextResolver<JAXBContext> {

private JAXBContext context;
private Class[] types = {SimpleJaxbBean.class};

public JAXBContextResolver() throws Exception {
Map<String, Object> props = new HashMap<String, Object>();
props.put(JSONJAXBContext.JSON_NOTATION, "MAPPED_JETTISON");
props.put(JSONJAXBContext.JSON_ROOT_UNWRAPPING, Boolean.FALSE);
this.context = new JSONJAXBContext(types, props);
}

public JAXBContext getContext(Class<?> objectType) {
return (types[0].equals(objectType)) ? context : null;
}
}

@XmlRootElement
public static class SimpleJaxbBean {
public String name = "Franz";
public String surname = "Kafka";
}

@GET
@ProduceMime({"application/json", "application/xml"})
public SimpleJaxbBean getJson() {
return new SimpleJaxbBean();
}
}

The following options are available for the JSONJAXBContext.JSON_NOTATION
property, where the first one is the default value:


  • MAPPED
  • MAPPED_JETTISON
  • BADGERFISH

In the future i plan to add more properties so that the JSON serialization and deserialization
is highly configurable.