Wednesday August 19, 2009
GlassFish
Monitoring allows you to monitor the state of various runtime
components of the application server. This information is used to
identify performance bottlenecks and tuning the system for optimal
performance, to aid capacity planning, to predict failures, to do root
cause analysis in case of failures and sometimes to just ensure that
everything is functioning as expected.
GlassFish Management allows you to manage the running Application
Server instance such as query/create/delete resources (JDBC, JMS, etc),
stop/restart the instance, rotate the log and other similar functions.
GlassFish v3 exposes Monitoring and Management data using a REST
Interface. This Tip
Of The Day (TOTD) shows how
to play with this new functionality. Rajeshwar's blog
has lot of useful information on this topic.
Most of the functionality available in
web-based Admin Console and CLI (asadmin) is now available using the
REST interface. Both of these are pre-built
tools that ships with the GlassFish bundle. The REST interface is a
lower level API that enables toolkit developers and IT administrators
to write their custom scripts/clients using language of their choice
such as Java, JavaScript, Ruby or Groovy.
The default URL for the REST interface of monitoring is
"http://localhost:4848/monitoring/domain" and for the management is
"http://localhost:4848/management/domain". Each URL provides an XML,
JSON and HTML representation of the
resources. If a web browser is used then a HTML representation is
returned and displayed nicely in the browser. Rajeshwar's
blog described a Java
client written using Jersey
Client APIs that can be used to make all the
GET/PUT/POST/DELETE requests. This blog will use something more basic,
and extremely popular,
to make all the RESTful invocations - cURL.
At this time the monitoring resources are read-only (GET) and
management can
be done using GET/POST/DELETE methods. POST is used for creating and
updating resources/objects and the updates can be partial.
Lets get started.
| ~/tools/glassfish/v3/2023/glassfishv3 >./bin/asadmin start-domain
--verbose Aug 19, 2009 9:52:45 AM com.sun.enterprise.admin.launcher.GFLauncherLogger info INFO: JVM invocation command line: /System/Library/Frameworks/JavaVM.framework/Versions/1.6/Home/bin/java -cp . . . INFO: felix.fileinstall.dir /Users/arungupta/tools/glassfish/v3/2023/glassfishv3/glassfish/domains/domain1/autodeploy-bundles Aug 19, 2009 9:53:05 AM INFO: felix.fileinstall.debug 1 Aug 19, 2009 9:53:05 AM INFO: felix.fileinstall.bundles.new.start true |
| ~/tools/glassfish/v3/2023/glassfishv3 >curl -H "Accept:
application/json" http://localhost:4848/monitoring/domain -v * About to connect() to localhost port 4848 (#0) * Trying ::1... connected * Connected to localhost (::1) port 4848 (#0) > GET /monitoring/domain HTTP/1.1 > User-Agent: curl/7.16.3 (powerpc-apple-darwin9.0) libcurl/7.16.3 OpenSSL/0.9.7l zlib/1.2.3 > Host: localhost:4848 > Accept: application/json > < HTTP/1.1 200 OK < Content-Type: application/json < Transfer-Encoding: chunked < Date: Wed, 19 Aug 2009 17:40:29 GMT < {Domain:{},"child-resources":["http://localhost:4848/monitoring/domain/server"]} * Connection #0 to host localhost left intact * Closing connection #0 |
| {Domain:{},"child-resources":["http://localhost:4848/monitoring/domain/server"]} |
| ~/tools/glassfish/v3/2023/glassfishv3 >curl -H "Accept: application/xml"
http://localhost:4848/monitoring/domain -v * About to connect() to localhost port 4848 (#0) * Trying ::1... connected * Connected to localhost (::1) port 4848 (#0) > GET /monitoring/domain HTTP/1.1 > User-Agent: curl/7.16.3 (powerpc-apple-darwin9.0) libcurl/7.16.3 OpenSSL/0.9.7l zlib/1.2.3 > Host: localhost:4848 > Accept: application/xml > < HTTP/1.1 200 OK < Content-Type: application/xml < Transfer-Encoding: chunked < Date: Wed, 19 Aug 2009 17:43:51 GMT < <Domain> <child-resource>http://localhost:4848/monitoring/domain/server</child-resource> </Domain> * Connection #0 to host localhost left intact * Closing connection #0 |
| <Domain> <child-resource>http://localhost:4848/monitoring/domain/server</child-resource> </Domain> |

| </tools/glassfish/v3/2023/glassfishv3
>curl -H "Accept:
application/json" http://localhost:4848/monitoring/domain/server -v * About to connect() to localhost port 4848 (#0) * Trying ::1... connected * Connected to localhost (::1) port 4848 (#0) > GET /monitoring/domain/server HTTP/1.1 > User-Agent: curl/7.16.3 (powerpc-apple-darwin9.0) libcurl/7.16.3 OpenSSL/0.9.7l zlib/1.2.3 > Host: localhost:4848 > Accept: application/json > < HTTP/1.1 200 OK < Content-Type: application/json < Transfer-Encoding: chunked < Date: Wed, 19 Aug 2009 17:56:41 GMT < {Server:{},"child-resources":["http://localhost:4848/monitoring/domain/server/webintegration", "http://localhost:4848/monitoring/domain/server/transaction-service", "http://localhost:4848/monitoring/domain/server/network", "http://localhost:4848/monitoring/domain/server/jvm", "http://localhost:4848/monitoring/domain/server/web", "http://localhost:4848/monitoring/domain/server/realm", "http://localhost:4848/monitoring/domain/server/http-service"]} * Connection #0 to host localhost left intact * Closing connection #0 |

| ~/tools/glassfish/v3/2023/glassfishv3 >curl -X OPTIONS
http://localhost:4848/management/domain -v * About to connect() to localhost port 4848 (#0) * Trying ::1... connected * Connected to localhost (::1) port 4848 (#0) > OPTIONS /management/domain HTTP/1.1 > User-Agent: curl/7.16.3 (powerpc-apple-darwin9.0) libcurl/7.16.3 OpenSSL/0.9.7l zlib/1.2.3 > Host: localhost:4848 > Accept: */* > < HTTP/1.1 200 OK < Content-Type: application/json < Transfer-Encoding: chunked < Date: Wed, 19 Aug 2009 18:07:14 GMT < { "Method":"GET" "Method":"PUT" } * Connection #0 to host localhost left intact * Closing connection #0 |
| ~/tools/glassfish/v3/2023/glassfishv3 >curl -H "Accept:
application/json" http://localhost:4848/management/domain -v * About to connect() to localhost port 4848 (#0) * Trying ::1... connected * Connected to localhost (::1) port 4848 (#0) > GET /management/domain HTTP/1.1 > User-Agent: curl/7.16.3 (powerpc-apple-darwin9.0) libcurl/7.16.3 OpenSSL/0.9.7l zlib/1.2.3 > Host: localhost:4848 > Accept: application/json > < HTTP/1.1 200 OK < Content-Type: application/json < Transfer-Encoding: chunked < Date: Wed, 19 Aug 2009 18:14:46 GMT < {Domain:{"log-root" : "${com.sun.aas.instanceRoot}/logs","application-root" : "${com.sun.aas.instanceRoot}/applications","locale" : "","version" : "re-continuous"},"child-resources":["http://localhost:4848/management/domain/configs", "http://localhost:4848/management/domain/resources","http://localhost:4848/management/domain/servers", "http://localhost:4848/management/domain/property","http://localhost:4848/management/domain/applications", "http://localhost:4848/management/domain/system-applications","http://localhost:4848/management/domain/stop", "http://localhost:4848/management/domain/restart","http://localhost:4848/management/domain/uptime", "http://localhost:4848/management/domain/version","http://localhost:4848/management/domain/rotate-log", "http://localhost:4848/management/domain/host-port"]} * Connection #0 to host localhost left intact * Closing connection #0 |
| curl -H "Accept: application/json" http://localhost:4848/management/domain/host-port -v |
| {"GetHostAndPort":{"value" : "dhcp-usca14-132-79.SFBay.Sun.COM:8080"}} |
| curl -H "Accept: application/json" http://localhost:4848/management/domain/system-applications/application/__admingui -v |
| {__admingui:{"libraries" : "","availability-enabled" : "false","enabled" : "true","context-root" : "","location" : "${com.sun.aas.installRootURI}/lib/install/applications/__admingui","description" : "","name" : "__admingui","directory-deployed" : "true","object-type" : "system-admin"},"child-resources":["http://localhost:4848/management/domain/system-applications/application/__admingui/module"]} |
| curl -H "Accept: application/json" http://localhost:4848/management/domain/configs/config/server-config/monitoring-service/module-monitoring-levels -v |
| {ModuleMonitoringLevels:{"transaction-service" : "OFF","ejb-container" : "OFF","jdbc-connection-pool" : "OFF","orb" : "OFF","http-service" : "OFF","connector-connection-pool" : "OFF","jms-service" : "OFF","connector-service" : "OFF","jvm" : "OFF","thread-pool" : "OFF","web-container" : "OFF"},"child-resources":[]} |
| ~/tools/glassfish/v3/2023/glassfishv3 >curl -X POST -d
"web-container=ON" -H "Accept: application/json"
http://localhost:4848/management/domain/configs/config/server-config/monitoring-service/module-monitoring-levels
-v * About to connect() to localhost port 4848 (#0) * Trying ::1... connected * Connected to localhost (::1) port 4848 (#0) > POST /management/domain/configs/config/server-config/monitoring-service/module-monitoring-levels HTTP/1.1 > User-Agent: curl/7.16.3 (powerpc-apple-darwin9.0) libcurl/7.16.3 OpenSSL/0.9.7l zlib/1.2.3 > Host: localhost:4848 > Accept: application/json > Content-Length: 16 > Content-Type: application/x-www-form-urlencoded > < HTTP/1.1 200 OK < Content-Type: application/json < Transfer-Encoding: chunked < Date: Wed, 19 Aug 2009 22:01:31 GMT < * Connection #0 to host localhost left intact * Closing connection #0 "http://localhost:4848/management/domain/configs/config/server-config/monitoring-service/module-monitoring-levels" updated successfully |
| ~/tools/glassfish/v3/2023/glassfishv3 >curl -H "Accept:
application/json"
http://localhost:4848/management/domain/configs/config/server-config/monitoring-service/module-monitoring-levels
-v * About to connect() to localhost port 4848 (#0) * Trying ::1... connected * Connected to localhost (::1) port 4848 (#0) > GET /management/domain/configs/config/server-config/monitoring-service/module-monitoring-levels HTTP/1.1 > User-Agent: curl/7.16.3 (powerpc-apple-darwin9.0) libcurl/7.16.3 OpenSSL/0.9.7l zlib/1.2.3 > Host: localhost:4848 > Accept: application/json > < HTTP/1.1 200 OK < Content-Type: application/json < Transfer-Encoding: chunked < Date: Wed, 19 Aug 2009 22:36:47 GMT < * Connection #0 to host localhost left intact * Closing connection #0 {ModuleMonitoringLevels:{"transaction-service" : "OFF","ejb-container" : "OFF","jdbc-connection-pool" : "OFF","orb" : "OFF","http-service" : "OFF","connector-connection-pool" : "OFF","jms-service" : "OFF","connector-service" : "OFF","jvm" : "OFF","thread-pool" : "OFF","web-container" : "ON"},"child-resources":[]} |
| curl -H "Accept: application/json" http://localhost:4848/management/domain/stop -v |
| curl -H "Accept: application/json" http://localhost:4848/management/domain/restart -v |
| curl -H "Accept: application/json" http://localhost:4848/management/domain/resources -v |
| {Resources:{},"child-resources":["http://localhost:4848/management/domain/resources/jdbc-connection-pool", "http://localhost:4848/management/domain/resources/jdbc-resource"]} |
| curl -H "Accept: application/json" http://localhost:4848/management/domain/resources/jdbc/connection-pool -v |
| {JdbcConnectionPool:{},"child-resources":["http://localhost:4848/management/domain/resources/jdbc-connection-pool/__TimerPool", "http://localhost:4848/management/domain/resources/jdbc-connection-pool/DerbyPool"]} |
| curl "Accept: application/json" http://localhost:4848/management/domain/resources/jdbc-resource -v |
| {JdbcResource:{},"child-resources":["http://localhost:4848/management/domain/resources/jdbc-resource/jdbc/__TimerPool", "http://localhost:4848/management/domain/resources/jdbc-resource/jdbc/__default"]} |
| curl -X OPTIONS -H "Accept: application/json" http://localhost:4848/management/domain/resources/jdbc-resource -v |
| { "Method":"POST", "Message Parameters":{ "id":{"Acceptable Values":"","Default Value":"","Type":"class java.lang.String","Optional":"false"}, "enabled":{"Acceptable Values":"","Default Value":"true","Type":"class java.lang.Boolean","Optional":"true"}, "description":{"Acceptable Values":"","Default Value":"","Type":"class java.lang.String","Optional":"true"}, "target":{"Acceptable Values":"","Default Value":"","Type":"class java.lang.String","Optional":"true"}, "property":{"Acceptable Values":"","Default Value":"","Type":"class java.util.Properties","Optional":"true"}, "connectionpoolid":{"Acceptable Values":"","Default Value":"","Type":"class java.lang.String","Optional":"false"} } "Method":"GET" |
| ~/tools/glassfish/v3/2023/glassfishv3 >curl -d
"id=jdbc/sample&connectionpoolid=DerbyPool"
http://localhost:4848/management/domain/resources/jdbc-resource -v * About to connect() to localhost port 4848 (#0) * Trying ::1... connected * Connected to localhost (::1) port 4848 (#0) > POST /management/domain/resources/jdbc-resource HTTP/1.1 > User-Agent: curl/7.16.3 (powerpc-apple-darwin9.0) libcurl/7.16.3 OpenSSL/0.9.7l zlib/1.2.3 > Host: localhost:4848 > Accept: */* > Content-Length: 42 > Content-Type: application/x-www-form-urlencoded > < HTTP/1.1 201 Created < Content-Type: text/html < Transfer-Encoding: chunked < Date: Wed, 19 Aug 2009 20:45:51 GMT < * Connection #0 to host localhost left intact * Closing connection #0 "http://localhost:4848/management/domain/resources/jdbc-resource/jdbc/sample" created successfully. |
| curl -H "Accept: application/json" http://localhost:4848/management/domain/resources/jdbc-resource -v |
| {JdbcResource:{},"child-resources":["http://localhost:4848/management/domain/resources/jdbc-resource/jdbc/__TimerPool", "http://localhost:4848/management/domain/resources/jdbc-resource/jdbc/__default", "http://localhost:4848/management/domain/resources/jdbc-resource/jdbc/sample"]} |
| ~/tools/glassfish/v3/2023/glassfishv3 >curl -H "Accept: application/xml"
http://localhost:4848/management/domain -v * About to connect() to localhost port 4848 (#0) * Trying ::1... connected * Connected to localhost (::1) port 4848 (#0) > GET /management/domain HTTP/1.1 > User-Agent: curl/7.16.3 (powerpc-apple-darwin9.0) libcurl/7.16.3 OpenSSL/0.9.7l zlib/1.2.3 > Host: localhost:4848 > Accept: application/xml > < HTTP/1.1 200 OK < Content-Type: application/xml < Transfer-Encoding: chunked < Date: Wed, 19 Aug 2009 18:17:07 GMT < <Domain log-root="${com.sun.aas.instanceRoot}/logs" application-root="${com.sun.aas.instanceRoot}/applications" locale="" version="re-continuous"> <child-resource>http://localhost:4848/management/domain/configs</child-resource> <child-resource>http://localhost:4848/management/domain/resources</child-resource> <child-resource>http://localhost:4848/management/domain/servers</child-resource> <child-resource>http://localhost:4848/management/domain/property</child-resource> <child-resource>http://localhost:4848/management/domain/applications</child-resource> <child-resource>http://localhost:4848/management/domain/system-applications</child-resource> <child-resource>http://localhost:4848/management/domain/stop</child-resource> <child-resource>http://localhost:4848/management/domain/restart</child-resource> <child-resource>http://localhost:4848/management/domain/uptime</child-resource> <child-resource>http://localhost:4848/management/domain/version</child-resource> <child-resource>http://localhost:4848/management/domain/rotate-log</child-resource> <child-resource>http://localhost:4848/management/domain/host-port</child-resource> * Connection #0 to host localhost left intact * Closing connection #0 |

Posted by Arun Gupta in General | Comments[8]
|
|
|
|
|
Thursday December 04, 2008
JavaFX 1.0 launched - access services hosted on embedded GlassFish
Today Sun announces the availability of Java
FX 1.0.
JavaFX 1.0 is a rich client platform for creating and delivering Rich
Internet Applications across all screens (desktop, browser,
and mobile) of your life. It consists of the following key components:
![]() |
|
![]() |
This blog shows how to create a simple JavaFX application using NetBeans IDE. The application plays a movie, allows the viewer to cast a vote if they liked it, and see aggregate response from other viewers. The application is developed using NetBeans 6.5, JavaFX 1.0 plugin, and coded using JavaFX Script. The voting engine is deployed as a RESTful Web service using Jersey on GlassFish. |



| Stage { title: "GlassFish Media Player" width: 625 height: 360 resizable: false scene: myScene } |
| var myScene: Scene = Scene { content: MediaView { fitWidth: 625 fitHeight: 360 mediaPlayer: bind myPlayer onMouseEntered: function( e: MouseEvent ):Void { println("mouse entered"); if (voted == false) { insert Vote{} into myScene.content; } else { insert Result{} into myScene.content; } } onMouseExited: function( e: MouseEvent ):Void { delete myScene.content[1] } } } |
| var myPlayer: MediaPlayer = MediaPlayer{ autoPlay: true media: bind myMedia }; |
| var myMedia: Media = Media { source: "http://sun.edgeboss.net/download/sun/media/1460825906/1460825906_2957290001_DayEarth-Bluray.flv" }; |
| class Vote extends CustomNode { override function create():Node { return Group { content: [ Rectangle { fill: Color.GREEN x: 185 y: 145 width: 243 height: 38 arcWidth: 20 arcHeight: 20 }, Text { x: 195 y: 170 fill: Color.WHITE font: Font { size: 18 } content: "I love it" }, Rectangle{ x: 191 y: 148 smooth: false width: 73 height: 32 fill: Color.TRANSPARENT onMouseClicked: function( e: MouseEvent ):Void { println("clicked I love it"); voted = true; wsClient.voteLoveIt(); delete myScene.content[1] } }, Text{ x: 305 y: 170 fill: Color.WHITE font: Font { size: 18 } content: "Not so great" }, Rectangle { x: 301 y: 148 smooth: false width: 118 height: 32 fill: Color.TRANSPARENT onMouseClicked: function( e: MouseEvent ):Void { voted = true; println("clicked Not so great"); wsClient.voteNotSoGreat(); delete myScene.content[1] } } ] } } }; |
| class Result extends CustomNode { override function create():Node { var resultPercent = wsClient.showResults(); var resultString = "{resultPercent} voters liked this clip"; return Group { content: [ Rectangle { fill: Color.BLUE x: 187 y: 145 width: 244 height: 38 arcWidth: 20 arcHeight: 20 onMouseClicked: function( e: MouseEvent ):Void { delete myScene.content[1] } }, Text { x: 199 y: 170 fill: Color.WHITE font: Font { size: 18 } content: resultString } ] } } }; |
| var voted = false; var wsClient = new WebserviceClient; |
| import javafx.scene.*; import javafx.scene.input.MouseEvent; import javafx.scene.media.Media; import javafx.scene.media.MediaPlayer; import javafx.scene.media.MediaView; import javafx.scene.paint.Color; import javafx.scene.shape.Rectangle; import javafx.scene.text.Font; import javafx.scene.text.Text; import javafx.stage.Stage; |
| @javax.xml.bind.annotation.XmlRootElement public class VoteBean { public static enum VOTE { LOVE_IT, NOT_SO_GREAT }; public VOTE vote; public VoteBean() { vote = VOTE.LOVE_IT; } public VoteBean(VOTE vote) { this.vote = vote; } } |

| public
class WebserviceClient { private static com.sun.jersey.api.client.WebResource createWebResource() { return com.sun.jersey.api.client.Client.create(). resource("http://localhost:8080/movie-feedback-webapp/webresources/myresource"); } public static void voteLoveIt() { createWebResource().type("application/json"). post(new VoteBean(VoteBean.VOTE.LOVE_IT)); } public static void voteNotSoGreat() { createWebResource().type("application/json"). post(new VoteBean(VoteBean.VOTE.NOT_SO_GREAT)); } public static String showResults() { return createWebResource().get(String.class); } } |
| @javax.xml.bind.annotation.XmlRootElement public class VoteBean { public static enum VOTE { LOVE_IT, NOT_SO_GREAT }; public VOTE vote; public VoteBean() { vote = VOTE.LOVE_IT; } public VoteBean(VOTE vote) { this.vote = vote; } } |
| int loveIt; int noSoGreat; |
| @POST public void postOneVote(VoteBean bean) { if (bean.vote == VoteBean.VOTE.LOVE_IT) { loveIt++; } else { noSoGreat++; } System.out.println("In POST: " + bean.vote); } |
| @GET @Produces("text/plain") public String getOpinion() { if (loveIt == 0 && noSoGreat == 0) return "No votes cast yet!"; return (loveIt * 100) / (loveIt + noSoGreat) + "%"; } |
Posted by Arun Gupta in webservices | Comments[13]
|
|
|
|
|
Monday December 01, 2008
TOTD #58: Jersey and GlassFish - how to process POST requests ?
Lets extend the Jersey endpoint (TOTD#
56) and client (TOTD#
57) such that it can accept a POST request and then invoke it.
| @POST @Consumes("application/json") @Produces("application/json") public Greeting postIt(Greeting greeting) { System.out.println("In POST: " + greeting.greeting); return greeting; } |
| public void
testPost() { Greeting result = createResource(). type("application/json"). post(Greeting.class, new Greeting("yo!")); assertTrue(result.greeting.equals("yo!")); } |
| Running org.glassfish.samples.AppTest 1 * Out-bound request 1 > GET http://localhost:8080/helloworld-webapp/webresources/myresource 1 > 1 < 200 1 < X-Powered-By: Servlet/2.5 1 < Transfer-Encoding: chunked 1 < Content-Type: text/plain 1 < Server: GlassFish/v3 1 < Date: Tue, 25 Nov 2008 20:19:34 GMT 1 < <?xml version="1.0" encoding="UTF-8" standalone="yes"?><greeting><greeting>Hi there!</greeting></greeting> 1 * In-bound response 1 * Out-bound request 1 > POST http://localhost:8080/helloworld-webapp/webresources/myresource 1 > Content-Type: application/json 1 > {"greeting":"yo!"} 1 < 200 1 < X-Powered-By: Servlet/2.5 1 < Transfer-Encoding: chunked 1 < Content-Type: application/json 1 < Server: GlassFish/v3 1 < Date: Tue, 25 Nov 2008 20:19:34 GMT 1 < {"greeting":"yo!"} 1 * In-bound response Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 1.191 sec |
Posted by Arun Gupta in webservices | Comments[6]
|
|
|
|
|
Wednesday November 26, 2008
TOTD #57: Jersey Client API - simple and easy to use
TOTD
#56 explains how to create a RESTful Web service endpoint
using Jersey
and publish the resource using JSON representation. The blog entry
showed how the endpoint can be accessed from a Web browser. This Tip Of The Day explains how to
use Jersey
Client APIs to invoke the published endpoint.
Lets get started!
| package org.glassfish.samples; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; /** * Unit test for simple App. */ public class AppTest extends TestCase { /** * Create the test case * * @param testName name of the test case */ public AppTest( String testName ) { super( testName ); } /** * @return the suite of tests being tested */ public static Test suite() { return new TestSuite( AppTest.class ); } /** * Rigourous Test :-) */ public void testApp() { assertTrue(true); } } |
| private
WebResource createResource() { Client client = Client.create(); WebResource resource = client.resource("http://localhost:8080/helloworld-webapp/webresources/myresource"); return resource; } |
|
Greeting result = createResource().get(Greeting.class); assertTrue(result.greeting.equals("Hi there!")); |
| import com.sun.jersey.api.client.Client; import com.sun.jersey.api.client.WebResource; |
| ~/samples/jersey/helloworld-webapp >mvn test [INFO] Scanning for projects... [INFO] ------------------------------------------------------------------------ [INFO] Building helloworld-webapp Jersey Webapp [INFO] task-segment: [test] [INFO] ------------------------------------------------------------------------ [INFO] [resources:resources] [INFO] Using default encoding to copy filtered resources. [INFO] [compiler:compile] [INFO] Nothing to compile - all classes are up to date [INFO] [resources:testResources] [INFO] Using default encoding to copy filtered resources. [INFO] [compiler:testCompile] [INFO] Compiling 1 source file to /Users/arungupta/samples/jersey/helloworld-webapp/target/test-classes [INFO] [surefire:test] [INFO] Surefire report directory: /Users/arungupta/samples/jersey/helloworld-webapp/target/surefire-reports ------------------------------------------------------- T E S T S ------------------------------------------------------- Running org.glassfish.samples.AppTest Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.587 sec Results : Tests run: 1, Failures: 0, Errors: 0, Skipped: 0 [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESSFUL [INFO] ------------------------------------------------------------------------ [INFO] Total time: 4 seconds [INFO] Finished at: Mon Nov 24 16:50:17 PST 2008 [INFO] Final Memory: 18M/43M [INFO] ------------------------------------------------------------------------ |
|
Client client = Client.create(); WebResource resource = client.resource("http://localhost:8080/helloworld-webapp/webresources/myresource"); resource.addFilter(new LoggingFilter()); return resource; |
| Running org.glassfish.samples.AppTest 1 * Out-bound request 1 > GET http://localhost:8080/helloworld-webapp/webresources/myresource 1 > 1 < 200 1 < X-Powered-By: Servlet/2.5 1 < Transfer-Encoding: chunked 1 < Content-Type: application/json 1 < Server: GlassFish/v3 1 < Date: Tue, 25 Nov 2008 07:07:51 GMT 1 < {"greeting":"Hi there!"} 1 * In-bound response Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 1.074 sec |
Posted by Arun Gupta in Finance | Comments[9]
|
|
|
|
|
Tuesday November 25, 2008
TOTD #56: Simple RESTful Web service using Jersey and Embeddable GlassFish - Text and JSON output
![]() |
Jersey is the open source, production quality, JAX-RS (JSR 311) Reference Implementation for building RESTful Web services in the GlassFish community. It also provides an API that allows developers to extend Jersey to suite their requirements. |
| ~/samples/jersey >mvn archetype:generate
-DarchetypeCatalog=http://download.java.net/maven/2 [INFO] Scanning for projects... [INFO] Searching repository for plugin with prefix: 'archetype'. [INFO] ------------------------------------------------------------------------ [INFO] Building Maven Default Project [INFO] task-segment: [archetype:generate] (aggregator-style) [INFO] ------------------------------------------------------------------------ [INFO] Preparing archetype:generate [INFO] No goals needed for project - skipping [INFO] Setting property: classpath.resource.loader.class => 'org.codehaus.plexus.velocity.ContextClassLoaderResourceLoader'. [INFO] Setting property: velocimacro.messages.on => 'false'. [INFO] Setting property: resource.loader => 'classpath'. [INFO] Setting property: resource.manager.logwhenfound => 'false'. [INFO] [archetype:generate] [INFO] Generating project in Interactive mode [INFO] No archetype defined. Using maven-archetype-quickstart (org.apache.maven.archetypes:maven-archetype-quickstart:1.0) Choose archetype: 1: remote -> jersey-quickstart-grizzly (Archetype for creating a RESTful web application with Jersey and Grizzly) 2: remote -> jersey-quickstart-webapp (Archetype for creating a Jersey based RESTful web application WAR packaging) Choose a number: (1/2): 2 [INFO] snapshot com.sun.jersey.archetypes:jersey-quickstart-webapp:1.0.1-SNAPSHOT: checking for updates from jersey-quickstart-webapp-repo Define value for groupId: : org.glassfish.samples Define value for artifactId: : helloworld-webapp Define value for version: 1.0-SNAPSHOT: : Define value for package: : org.glassfish.samples Confirm properties configuration: groupId: org.glassfish.samples artifactId: helloworld-webapp version: 1.0-SNAPSHOT package: org.glassfish.samples Y: : [INFO] ---------------------------------------------------------------------------- [INFO] Using following parameters for creating OldArchetype: jersey-quickstart-webapp:1.0.1-SNAPSHOT [INFO] ---------------------------------------------------------------------------- [INFO] Parameter: groupId, Value: org.glassfish.samples [INFO] Parameter: packageName, Value: org.glassfish.samples [INFO] Parameter: package, Value: org.glassfish.samples [INFO] Parameter: artifactId, Value: helloworld-webapp [INFO] Parameter: basedir, Value: /Users/arungupta/samples/jersey [INFO] Parameter: version, Value: 1.0-SNAPSHOT [INFO] ********************* End of debug info from resources from generated POM *********************** [INFO] OldArchetype created in dir: /Users/arungupta/samples/jersey/helloworld-webapp [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESSFUL [INFO] ------------------------------------------------------------------------ [INFO] Total time: 21 seconds [INFO] Finished at: Mon Nov 24 14:09:27 PST 2008 [INFO] Final Memory: 12M/30M [INFO] ------------------------------------------------------------------------ |
|
<plugin> <groupId>org.glassfish</groupId> <artifactId>maven-glassfish-plugin</artifactId> </plugin> |
|
<pluginRepositories> <pluginRepository> <id>maven2-repository.dev.java.net</id> <name>Java.net Repository for Maven</name> <url>http://download.java.net/maven/2/</url> <layout>default</layout> </pluginRepository> <pluginRepository> <id>maven-repository.dev.java.net</id> <name>Java.net Maven 1 Repository (legacy)</name> <url>http://download.java.net/maven/1</url> <layout>legacy</layout> </pluginRepository> </pluginRepositories> |
|
<dependency> <groupId>org.glassfish.distributions</groupId> <artifactId>web-all</artifactId> <version>10.0-build-20080430</version> <scope>test</scope> </dependency> <dependency> <groupId>org.glassfish.embedded</groupId> <artifactId>gf-embedded-api</artifactId> <version>1.0-alpha-4</version> <scope>test</scope> </dependency> |
|
<dependency> <groupId>org.glassfish.distributions</groupId> <artifactId>web-all</artifactId> <version>10.0-SNAPSHOT</version> <scope>test</scope> </dependency> <dependency> <groupId>org.glassfish.embedded</groupId> <artifactId>glassfish-embedded-all</artifactId> <version>3.0-Prelude-SNAPSHOT</version> </dependency> |
|
<properties> <jersey-version>1.0</jersey-version> </properties> |
| package org.glassfish.samples; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.Produces; // The Java class will be hosted at the URI path "/helloworld" @Path("/myresource") public class MyResource { // The Java method will process HTTP GET requests @GET // The Java method will produce content identified by the MIME Media // type "text/plain" @Produces("text/plain") public String getIt() { return "Hi there!"; } } |
| ~/samples/jersey/helloworld-webapp >mvn glassfish:run [INFO] Scanning for projects... [INFO] Searching repository for plugin with prefix: 'glassfish'. [INFO] ------------------------------------------------------------------------ [INFO] Building helloworld-webapp Jersey Webapp [INFO] task-segment: [glassfish:run] [INFO] ------------------------------------------------------------------------ [INFO] Preparing glassfish:run [INFO] [resources:resources] [INFO] Using default encoding to copy filtered resources. [INFO] [compiler:compile] [INFO] Compiling 1 source file to /Users/arungupta/samples/jersey/helloworld-webapp/target/classes [INFO] [glassfish:run] Nov 24, 2008 2:36:05 PM com.sun.enterprise.v3.server.AppServerStartup run INFO: HK2 initialized in 229 ms Nov 24, 2008 2:36:05 PM com.sun.enterprise.v3.server.AppServerStartup run INFO: com.sun.enterprise.naming.impl.ServicesHookup@2470b02c Init done in 237 ms Nov 24, 2008 2:36:05 PM com.sun.enterprise.v3.server.AppServerStartup run INFO: com.sun.enterprise.v3.server.Globals@13b3d787 Init done in 239 ms Nov 24, 2008 2:36:05 PM com.sun.enterprise.v3.server.AppServerStartup run INFO: com.sun.enterprise.v3.server.SystemTasks@61bedd7d Init done in 244 ms Nov 24, 2008 2:36:05 PM com.sun.enterprise.v3.server.AppServerStartup run INFO: com.sun.enterprise.v3.services.impl.HouseKeeper@2b9f7952 Init done in 245 ms Nov 24, 2008 2:36:05 PM com.sun.enterprise.v3.server.AppServerStartup run INFO: com.sun.enterprise.v3.services.impl.CmdLineParamProcessor@5249d560 Init done in 248 ms JMXMP connector server URL = service:jmx:jmxmp://localhost:8888 Nov 24, 2008 2:36:05 PM com.sun.enterprise.v3.services.impl.GrizzlyProxy start INFO: Listening on port 8080 Nov 24, 2008 2:36:06 PM com.sun.enterprise.v3.server.AppServerStartup run INFO: com.sun.enterprise.v3.services.impl.GrizzlyService@1baa56a2 startup done in 551 ms Nov 24, 2008 2:36:06 PM com.sun.enterprise.v3.services.impl.ApplicationLoaderService postConstruct INFO: loader service postConstruct started at 1227566166208 Nov 24, 2008 2:36:06 PM com.sun.enterprise.v3.server.AppServerStartup run INFO: Application Loader startup done in 740 ms Nov 24, 2008 2:36:06 PM com.sun.enterprise.v3.server.AppServerStartup run INFO: Glassfish v3 started in 740 ms Nov 24, 2008 2:36:07 PM com.sun.enterprise.web.WebModuleContextConfig authenticatorConfig SEVERE: webModuleContextConfig.missingRealm Nov 24, 2008 2:36:07 PM com.sun.jersey.api.core.PackagesResourceConfig init INFO: Scanning for root resource and provider classes in the packages: org.glassfish.samples Nov 24, 2008 2:36:07 PM com.sun.jersey.api.core.PackagesResourceConfig init INFO: Root resource classes found: class org.glassfish.samples.MyResource Nov 24, 2008 2:36:07 PM com.sun.jersey.api.core.PackagesResourceConfig init INFO: Provider classes found: Hit ENTER for redeploy |


| package org.glassfish.samples; import javax.xml.bind.annotation.XmlRootElement; /** * @author arungupta */ @XmlRootElement public class Greeting { public String greeting; public Greeting() { } public Greeting(String greeting) { this.greeting = greeting; } } |
| //
@Produces("text/plain") @Produces("application/json") public Greeting getIt() { return new Greeting("Hi there!"); } |

| mvn clean package |
Posted by Arun Gupta in webservices | Comments[16]
|
|
|
|
|
Monday January 28, 2008
GlassFish at WebGuild Web 2.0 Conference & Expo 2008 - Jan 29

Sun Microsystems is a sponsor of WebGuild's Web 2.0 Conference & Expo and you can meet me at Sun booth in the exhibitor hall. Register for a FREE exhibitor pass here.
Ask me about:
Technorati: conf jmaki jruby netbeans glassfish rubyonrails jruby jersey
Posted by Arun Gupta in web2.0 | Comments[2]
|
|
|
|
|
Thursday January 24, 2008
RESTful representation of "sakila" using GlassFish and NetBeans IDE
"sakila" is the sample database shipped with MySQL (pronounced as my ess-kew-ell). In the context of Sun Microsystems announcing the agreement to acquire MySQL, I'd like to dedicate this entry to show how this sample database can be exposed as a RESTful Web service endpoint and deployed on GlassFish using Jersey Tooling Plugin (0.4.1 with Jersey 0.4) in NetBeans IDE.
Lets get started!
sakila".mysqld-nt --user root
--console' in bin directory on Windows or './bin/mysqld_safe'
from MySQL directory on Unix flavors.sakila".
Choose "GlassFish v2" as the "Server:".Services" tab of NetBeans IDE, expand "Drivers" and add
MySQL
Connector/J driver if it does not exist already.
New", "Entity Classes from
Database...". In "Data Source", select "New Data Source..." and specify the
values as shown below:
film" in "Available Tables" and click on "Add >" as shown
below:
Next >".Create Persistence Unit..." and take all the defaults as shown
below:
Create".sakila" as shown below:
Finish".Configuration Files"
and open "persistence.xml". Specify the username and password
by replacing <properties/> with the following fragment:<properties>
<property name="toplink.jdbc.user" value="root"/>
<property name="toplink.jdbc.password" value=""/>
</properties>Tools", "Plugins", "Available Plugins", "RESTful
Web Services" and then click on "Install". This installs the
Jersey Tooling
Plugin in the IDE.New", "RESTful Web Services from
Entity Classes...".Add >>", take all other defaults as shown
below:
Next >", take all defaults and then "Finish".Test RESTful Web Services".
The following web page is presented in the browser:
films" and then on "Test" as shown
below:
Test" button or the URL "http://localhost:8080/sakila/resources/films/"
shows the RESTful representation of the "Film" table. The
default representation shows 10 records from the table where each entry
returns the "id" of the film and a reference to the detailed
entry.http://localhost:8080/sakila/resources/films/?max=40".
Additional fields from the table can be displayed by adding getter methods
to "converter.FilmRefConverter" class such as:@XmlElement
public String getTitle() {
return entity.getTitle();
}

Here are few more ideas for you to explore:
A JRuby-on-Rails application using MySQL is explained here. TOTD #9 explains how JDBC connection pooling in GlassFish can be used for a JRuby-on-Rails application using MySQL.
The key message here is MySQL can be very easily used with GlassFish and NetBeans IDE makes it possible! Once MySQL becomes part of Sun, this integration is going to be much more seamless for the betterment of community.
All the entries on this blog using MySQL can be found here. And last but not the least, Welcome aboard MySQL!
A NetBeans project with all the source code can be downloaded from here. You will still need to setup the database connection and need to make sure the correct version of Jersey plug-in as well :)
Technorati: glassfish netbeans jersey mysql sakila jpa jmaki rubyonrails
Posted by Arun Gupta in webservices | Comments[28]
|
|
|
|
|
Monday December 31, 2007
Screencast #Web11: Travel Map - Another Real-life app using jMaki & Jersey
In my role of Technology Evangelist, I get the opportunity to meet a lot of community (folks like you :) all around the world. In the year 2007, I represented GlassFish (and related technologies - Metro, jMaki and Jersey) at multiple conferences. This blog introduces a new real-life application that plots all the places I visited this year on a jMaki-wrapped Google Map widget. Clicking on the marker shows more information about the event such as dates and the blog entry covering the event.
Play the video below to see how the application looks like.
Here is the architecture of this application:

It consists of a server-side and a client-side applications - developed as NetBeans projects.
Both the server-side and client-side are deployed on GlassFish.
This is only a sample application so optimizations are certainly possible and corner cases (such as no blog entry for a particular visit) are not accounted for. But the application still demonstrates the concept. The fully built application looks like as shown below:

My first presentation in this role was Sun Tech Days Atlanta (highlighted in the image). This application generates an interactive Google Map so feel free to zoom in/out and click
And one last thing before we build the application. Here is
the list of technologies and associated concepts used to build this
application:
And finally, lets build this application. Lets build the
RESTful Web service endpoint project first.
jdbc:derby://localhost:1527/sample
[app on APP]" (right-click and select "Connect...").Execute
Command..." and create a table by giving the following
command:create table EVENTS (id int GENERATED ALWAYS AS
IDENTITY,
event_name varchar(255),
dates varchar(20),
venue varchar(255),
blogs varchar(2056),
PRIMARY KEY (id))Execute
Command..." to add data to the table by giving the
following command:
INSERT INTO EVENTS (event_name, dates, venue,
blogs) VALUES('SunTech Days - Atlanta', 'Jan 16 - Jan 17',
'Cobb Galleria Center, Two
Galleria Parkway, Atlanta, Georgia, 30339',
'http://blogs.sun.com/arungupta/entry/wsit_and_web_2_0');
INSERT
INTO EVENTS (event_name, dates, venue, blogs) VALUES('jMaki Day', '
Feb 23', '4150
Network Circle Santa Clara, CA 95054',
'http://blogs.sun.com/arungupta/entry/sun_internal_jmaki_day_review');
INSERT
INTO EVENTS (event_name, dates, venue, blogs) VALUES('Ajax World - New
York', 'Mar 19 - Mar 21', 'The
Roosevelt Hotel, 45 E 45th St, New York, NY 10017',
'http://blogs.sun.com/arungupta/entry/sun_ajax_world');
INSERT
INTO
EVENTS (event_name, dates, venue, blogs) VALUES('The Server Side Java
Symposium - Las Vegas', 'Mar 22', '3355 Las Vegas Blvd. South
Las
Vegas, NV 89109',
'http://blogs.sun.com/arungupta/entry/sun_the_server_side_java,
http://blogs.sun.com/arungupta/entry/tango_at_venetian_las_vegas');
INSERT
INTO EVENTS (event_name, dates, venue, blogs) VALUES('JavaOne - San
Francisco', 'May 7 - May 11', 'Moscone
Center, 747 Howard Street, San Francisco, CA 94103',
'http://blogs.sun.com/arungupta/entry/slides_for_ts_4865,
http://blogs.sun.com/arungupta/entry/javaone_2007_day_1_finished,
http://blogs.sun.com/arungupta/entry/javaone_2007_day_1,
http://blogs.sun.com/arungupta/entry/javascript_everywhere_javaone_2007_demo,
http://blogs.sun.com/arungupta/entry/excel_using_wsit_javaone_2007,
http://blogs.sun.com/arungupta/entry/ts_4865_takes_two_to,
http://blogs.sun.com/arungupta/entry/communityone_glassfish_day_report,
http://blogs.sun.com/arungupta/entry/javaone_2007_backstage,
http://blogs.sun.com/arungupta/entry/javaone_2007_is_almost_here,
http://blogs.sun.com/arungupta/entry/my_javaone_2007_picks');
INSERT
INTO EVENTS (event_name, dates, venue, blogs) VALUES('Rails Conf -
Portland', 'May 17 - May 20', '777 NE MLK, Jr. Blvd. Portland,
OR
97232',
'http://blogs.sun.com/arungupta/entry/tim_bray_s_keynote_session,
http://blogs.sun.com/arungupta/entry/sun_rails_conf_2007_keep,
http://blogs.sun.com/arungupta/entry/getting_started_with_jruby_tutorial,
http://blogs.sun.com/arungupta/entry/jmaki_netbeans_and_glassfish_in');
INSERT
INTO EVENTS (event_name, dates, venue, blogs) VALUES('Google Developer
Day - San Jose', 'May 31', '150 W San Carlos St San Jose, CA 95113',
'http://blogs.sun.com/arungupta/entry/google_developer_day_report');
INSERT
INTO EVENTS (event_name, dates, venue, blogs) VALUES('Mashup Camp -
Mountain View', 'Jul 18 - Jul 19', 'Computer History Museum, 1401 N
Shoreline Blvd., Mountain View, CA 94043',
'http://blogs.sun.com/arungupta/entry/jmaki_at_mashup_camp_report,
http://blogs.sun.com/arungupta/entry/jmaki_mashup_camp');
INSERT INTO EVENTS (event_name, dates, venue, blogs) VALUES('OSCON -
Portland',
'Jul 23 - Jul 27', '777 NE MLK, Jr. Blvd. Portland, OR 97232',
'http://blogs.sun.com/arungupta/entry/jmaki_oscon');
INSERT
INTO EVENTS (event_name, dates, venue, blogs) VALUES('JRuby Hack Day -
San Francisco', 'Aug 8', '1201 8th St, San Francisco, CA 94107',
'http://blogs.sun.com/arungupta/entry/jruby_on_rails_hackday_report,
http://blogs.sun.com/arungupta/entry/learn_jruby_on_rails_free');
INSERT
INTO EVENTS (event_name, dates, venue, blogs) VALUES('Rich Web
Experience - San Jose', 'Sep 6 - Sep 8', '170 S Market St, San
Jose,
CA 95113',
'http://blogs.sun.com/arungupta/entry/the_rich_web_experience_2007,
http://blogs.sun.com/arungupta/entry/jmaki_javafx_the_rich_web');
INSERT
INTO EVENTS (event_name, dates, venue, blogs) VALUES('Rails Conf Europe
- Berlin', 'Sep 17 - Sep 19', 'Maritim Pro Arte,
Friedrichstrasse 151,
10117 Berlin',
'http://blogs.sun.com/arungupta/entry/rails_conf_europe_2007_day2,
http://blogs.sun.com/arungupta/entry/rails_conf_europe_2007_day1,
http://blogs.sun.com/arungupta/entry/rails_conf_europe_2007_day,
http://blogs.sun.com/arungupta/entry/jmaki_netbeans_and_glassfish_in1');
INSERT
INTO EVENTS (event_name, dates, venue, blogs) VALUES('Sun Tech Days -
Rome', 'Sep 24 - Sep 25', 'Meliá Roma Aurelia Antica, Vía
Aldobrandeschi, 223
Rome ITALY 00163',
'http://blogs.sun.com/arungupta/entry/netbeans_day_rome_2007,
http://blogs.sun.com/arungupta/entry/travel_tips_to_rome,
http://blogs.sun.com/arungupta/entry/glassfish_metro_jersey_and_jmaki');
INSERT
INTO EVENTS (event_name, dates, venue, blogs) VALUES('Sun Tech Days -
Milan', 'Sep 26 - Sep 28', 'ATA Hotel Quark - Via Lampedusa 11/a 20141
Milano, Italia',
'http://blogs.sun.com/arungupta/entry/glassfish_day_milan_2007');
INSERT
INTO EVENTS (event_name, dates, venue, blogs) VALUES('Mid West Java
Tech Days - Minneapolis', 'Oct 16', 'University of St Thomas,
MPL 201,
1000 LaSalle Avenue,
Minneapolis, MN 55403-2005',
'http://blogs.sun.com/arungupta/entry/mid_west_java_tech_days,
http://blogs.sun.com/arungupta/entry/metro_and_jmaki_in_minneapolis');
INSERT
INTO EVENTS (event_name, dates, venue, blogs) VALUES('Mid West Java
Tech Days
- Chicago', 'Oct 18', 'Donald E Stephens Convention Center, 9301, W
Bryn Mawr Ave,
Rosemont IL 60018',
'http://blogs.sun.com/arungupta/entry/mid_west_java_tech_days1,
http://blogs.sun.com/arungupta/entry/crowne_plaza_chicago_o_hare,
http://blogs.sun.com/arungupta/entry/metro_and_jmaki_in_minneapolis');
INSERT
INTO EVENTS (event_name, dates, venue, blogs) VALUES('Silicon Valley
Code Camp
- Los Altos', 'Oct 27', 'Foothill College, Los Altos, CA',
'http://blogs.sun.com/arungupta/entry/silicon_valley_code_camp_trip,
http://blogs.sun.com/arungupta/entry/metro_jmaki_silicon_valley_code');
INSERT
INTO EVENTS (event_name, dates, venue, blogs) VALUES('Sun Tech Days -
Beijing', 'Nov 1 - Nov 3', 'Beijing International Convention
Center,
No.8
Beichendong Road Chaoyang District, Beijing',
'http://blogs.sun.com/arungupta/entry/glassfish_day_beijing_2007_by,
http://blogs.sun.com/arungupta/entry/wangfujing_street_authentic_china_in,
http://blogs.sun.com/arungupta/entry/sun_tech_days_beijing_talent,
http://blogs.sun.com/arungupta/entry/sun_tech_days_beijing_day,
http://blogs.sun.com/arungupta/entry/travel_tips_to_beijing,
http://blogs.sun.com/arungupta/entry/glassfish_day_beijing');
INSERT INTO EVENTS (event_name, dates, venue, blogs) VALUES('Partner
Preso
- Toronto', 'Nov 21', 'Toronto City Center',
'http://blogs.sun.com/arungupta/entry/metro_jmaki_jruby_glassfish_q');
INSERT INTO EVENTS (event_name, dates, venue, blogs) VALUES('Partner
Preso
- Montreal', 'Nov 21', 'Montreal City Center',
'http://blogs.sun.com/arungupta/entry/metro_jmaki_jruby_glassfish_q');
INSERT INTO EVENTS (event_name, dates, venue, blogs) VALUES('GlassFish
- Delhi University',
'Dec 3', 'New Delhi',
'http://blogs.sun.com/arungupta/entry/glassfish_delhi_university');
INSERT
INTO EVENTS (event_name, dates, venue, blogs) VALUES('FOSS.IN -
Bangalore', 'Dec 4', 'India Institute of Science, Bangalore',
'http://blogs.sun.com/arungupta/entry/packaging_java_apps_for_ubuntu,
http://blogs.sun.com/arungupta/entry/foss_in_schedules_now_available,
http://blogs.sun.com/arungupta/entry/glassfish_foss_in_2007');
INSERT INTO EVENTS (event_name, dates, venue, blogs) VALUES('Partner
Preso
- Bangalore', 'Dec 4', 'Bangalore',
'http://blogs.sun.com/arungupta/entry/glassfish_bangalore_chennai_and_pune');
INSERT INTO EVENTS (event_name, dates, venue, blogs) VALUES('Partner
Preso
- Chennai', 'Dec 5', 'Chennai',
'http://blogs.sun.com/arungupta/entry/glassfish_bangalore_chennai_and_pune');
INSERT INTO EVENTS (event_name, dates, venue, blogs) VALUES('Partner
Preso
- Pune', 'Dec 6', 'Pune',
'http://blogs.sun.com/arungupta/entry/glassfish_bangalore_chennai_and_pune');
INSERT INTO EVENTS (event_name, dates,
venue, blogs) VALUES('Partner
Preso
- San Francisco', 'Dec 17', 'San Francisco',
'http://blogs.sun.com/arungupta/');VALUES
clause to match accordingly.WebApplication3", package name is "events" and the table name to
generate Entity classes is EVENTS. Take everything else as the defaults.events
package as:
@javax.xml.bind.annotation.XmlRootElement
public class EventsList {
@javax.xml.bind.annotation.XmlElement
protected java.util.List<Events> events;
public EventsList() {
if (events == null)
events = new
java.util.ArrayList<Events>();
}
public void add(Events name) {
events.add(name);
}
public java.util.List<Events> getValue() {
return events;
}
}service.EventsResource,
change the method associated with GET to:public EventsList get() {
EventsList eventsList = new EventsList();
List<Events> list =
PersistenceService.getInstance().createQuery("SELECT e FROM Events
e").getResultList();
for (Events e : list) {
eventsList.add(e);
}
return eventsList;
}
http://localhost:8080/WebApplication3/resources/events"
now return a complete RESTful representation of all the rows from the
database table EVENTS. Ajax
Framework" and choose the "Standard"
layout for "index.jsp". Lets say the
project name is "WebApplication4".id="mymap" attribute to the
Google Map widget. The updated widget looks like as shown below:<a:widget name="google.map" id="mymap"
args="{ centerLat : 37.4041960114344,
centerLon : -122.008194923401 }" />
id="mymap" will allow the Map widget to be accessed by
name later.args="{label:'Plot Events'}"
attribute to thes Yahoo button widget. The updated widget looks like as
shown below:<a:widget name="yahoo.button" args="{label:'Plot Events'}"/>glue,js, add the following
code to *onClick subscribe method:var url = jmaki.xhp + "?id=events";
var _map = jmaki.getWidget("mymap").map;
_map.setZoom(2);
_map.clearOverlays();
_map.enableInfoWindow();
jmaki.doAjax({method: "GET",
url: url,
callback: function(_req)
{
var xmlobject = (new DOMParser()).parseFromString(_req.responseText,
"text/xml");
var root = xmlobject.getElementsByTagName('eventsList')[0];
var events = root.getElementsByTagName('events');
for (var i = 0 ; i < events.length ; i++) {
var event = events[i];
var eventName =
event.getElementsByTagName('eventName')[0].firstChild.nodeValue;
var venue = event.getElementsByTagName('venue')[0].firstChild.nodeValue;
var blogs = event.getElementsByTagName('blogs')[0].firstChild.nodeValue;
var dates = event.getElementsByTagName('dates')[0].firstChild.nodeValue;
var
id = event.getElementsByTagName('id')[0].firstChild.nodeValue;
var encodedLocation = encodeURIComponent("location=" + venue);
var url = jmaki.xhp + "?id=yahoogeocoder&urlparams=" +
encodedLocation;
jmaki.myHandler(url, eventName, blogs, dates, id, _map);
}
}
});*onClick
subscribe method:// "Function closure" used from
http://econym.googlepages.com/basic1.htm
// Creates local copy of "marker" and "html" variables to be preserved
for later use
function createMarker(point,html) {
var marker = new GMarker(point);
GEvent.addListener(marker, "click",
function() {
marker.openInfoWindowHtml(html);
});
return marker;
};
// Function closure that preserves "eventName", "blogs", "dates and "id"
// Gets the latitude/longitude from Yahoo Geocoding service and plots
them on the map
// Also creates meaningful markers
jmaki.myHandler = function(_url, eventName, blogs, dates, id, _map) {
jmaki.doAjax({url: _url,
callback : function(req) {
if (req.responseText.length > 0) {
jmaki.log("name: " + eventName);
var response = eval("(" + req.responseText + ")");
var coordinates = response.coordinates;
jmaki.publish("/jmaki/plotmap", coordinates);
jmaki.log("plotting " + eventName);
var latlng = new GLatLng(coordinates[0].latitude,
coordinates[0].longitude);
var blogHtml = "";
b = blogs.split(', ');
for (i=0; i<b.length; i++) {
blogHtml += '<a href="' + b[i] + '">' + (i+1) +
'</a>';
if (i<b.length-1)
blogHtml += ", ";
}
var txt = '<table>' +
'<tr><td>#' + id + ": " + eventName +
'</td></tr>' +
'<tr>Dates: ' + dates + ',
2007</td></tr>' +
'<tr><td>Blogs: ' + blogHtml +
'</td></tr>' +
'</table>';
var marker = createMarker(latlng, txt);
_map.addOverlay(marker);
marker.openInfoWindowHtml(txt);
} else {
jmaki.log("Failed to get coordinates for " + location );
}
}
});
};,
{"id": "events",
"url":"http://localhost:8080/WebApplication3/resources/events/"
}WebApplication3 is the project where RESTful Web service endpoint is hosted.<script type="text/javascript">
in index.jsp can be generated as <script
type="text/javascript;
e4x=1">.Technorati: screencast conf jmaki jersey netbeans glassfish jpa javascript googlemaps restful web2.0 jmakimashups
Posted by Arun Gupta in web2.0 | Comments[9]
|
|
|
|
|
Tuesday October 02, 2007
A jMaki widget expects data in JSON format as defined by the standard data models. There are three possible ways to generate the JSON data from a Jersey endpoint that can be consumed by a jMaki widget:
xhp.json) to convert the
received data into the JSON format as expected by the jMaki widget. This
keeps the server code simple but requires a stylesheet to convert from one
JSON format (defined by BadgerFish convention) to another JSON format (as
expected by the jMaki widget).This TOTD explains 2nd and 3rd bullet. The first bullet can be applied following the solution proposed in 2nd bullet.
examples/HelloWorld" project in
NetBeans 6 IDE.jdbc:derby://localhost:1527/sample [app on APP]"
and select Connect. Enter the password as "app" and select "OK".Execute Command..."
and issue the command:create table BOOKS (title varchar(255),
author varchar(255),
isbn varchar(255),
description varchar(255),
PRIMARY KEY (isbn))INSERT INTO BOOKS VALUES('Marathon', 'Jeff Galloway', 'ABCDEF', 'The best book
on running');
INSERT INTO BOOKS VALUES('Run a Marathon', 'Duke', '123456', 'How to train for a
marathon ?');New",
"Entity Classes from Database...".Available Tables", select "BOOKS"
and click on "Add >". Click on "Next >".Create Persistence Unit...", take all the
defaults and click on "Create" and then click on "Finish".@NamedQuery(name = "Books.findAll",
query = "SELECT b FROM Books b")" to the generated Books class.@javax.xml.bind.annotation.XmlRootElement"
to the generated Books class.com.sun.ws.rest.samples.helloworld"
package, select "New", "Java Class..." and
enter the Class Name as "BookList".package com.sun.ws.rest.samples.helloworld;
/**
* @author Arun Gupta
*/
@javax.xml.bind.annotation.XmlRootElement
public class BookList {
@javax.xml.bind.annotation.XmlElement
protected java.util.List<Books> book;
public BookList() {
if (book == null)
book = new java.util.ArrayList<Books>();
}
public void add(Books name) {
book.add(name);
}
public java.util.List<Books> getValue() {
return book;
}
}com.sun.ws.rest.samples.helloworld.resources",
select "New", "Java Class..." and enter the
Class Name as "TableResource".package com.sun.ws.rest.samples.helloworld.resources;
import com.sun.ws.rest.samples.helloworld.BookList;
import com.sun.ws.rest.samples.helloworld.Books;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.ws.rs.HttpMethod;
import javax.ws.rs.ProduceMime;
import javax.ws.rs.UriTemplate;
import javax.xml.bind.JAXBException;
import org.codehaus.jettison.json.JSONArray;
import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject;
/**
* @author Arun Gupta
*/
@UriTemplate("/table")
public class TableResource {
@HttpMethod
@ProduceMime("application/xml")
@UriTemplate("/xml")
public BookList getXML() throws JAXBException {
BookList booklist = new BookList();
for (Books b : getBooks()) {
booklist.add(b);
}
return booklist;
}
@HttpMethod
@ProduceMime("application/json")
@UriTemplate("/json")
public JSONObject getJSON() throws JSONException {
JSONObject tableDataModel = new JSONObject();
String[] labels = { "Title", "Author", "ISBN",
"Description"};
JSONArray columns = new JSONArray();
for (String l : labels) {
JSONObject item = new JSONObject();
item.put("label", l).put("id", l);
columns.put(item);
}
tableDataModel.put("columns", columns);
JSONArray rows = new JSONArray();
for (Books b : getBooks()) {
JSONObject item = new JSONObject();
item.put(labels[0], b.getTitle());
item.put(labels[1], b.getAuthor());
item.put(labels[2], b.getIsbn());
item.put(labels[3], b.getDescription());
rows.put(item);
}
tableDataModel.put("rows", rows);
return tableDataModel;
}
private List<Books> getBooks() {
EntityManagerFactory emf =
Persistence.createEntityManagerFactory("HelloWorldPU");
EntityManager em = emf.createEntityManager();
List<Books> list =
em.createNamedQuery("Books.findAll").getResultList();
return list;
}
}getXML() method returns only the table rows data in an
XML format. This XML representation of the resource is then processed by
a stylesheet (specified later in the jMaki application) and converted
into the JSON format as expected by the jMaki widget. The stylesheet
adds the column information as well. The getJSON() method
uses low-level JSON APIs to return the data exactly as expected by the
jMaki widget (including the column information).com.sun.ws.rest.samples.helloworld", edit "Main.java"
and change line 42 to use "TableResource" class instead of "HelloWorldResource".
The updated code looks like:HttpHandler handler = ContainerFactory.createContainer(
HttpHandler.class,
TableResource.class);Properties", choose "Libraries"
and add the following JARs by clicking on "Add JAR/Folder"
button:GLASSFISH_HOME/javadb/lib/derbyclient.jar"GLASSFISH_HOME/lib/toplink-essentials.jar"GLASSFISH_HOME/lib/toplink-essentials-agent.jar"Run".This concludes developing/configuring/running the Jersey endpoint. Now let's create a new web application and add a jMaki widget that consumes the resource representation exposed by this endpoint:
jMaki Ajax Framework"
for the project.Web pages", "resources", and edit "xhp.json"
to add the following entries at the end:,
{"id": "jersey-json",
"url":"http://localhost:9998/table/json"
},
{"id": "jersey-xml",
"url":"http://localhost:9998/table/xml",
"xslStyleSheet": "table.xsl"
}Web pages", "resources", "xsl"
and add a new stylesheet (table.xsl). The content of the stylesheet are given below:<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" encoding="utf-8"/>
<xsl:template match="/">
<xsl:apply-templates select="bookList"/>
</xsl:template>
<xsl:template match="bookList">
{"columns":
[{"label":"Title","id":"Title"},
{"label":"Author","id":"Author"},
{"label":"ISBN","id":"ISBN"},
{"label":"Description","id":"Description"}],
"rows": [
<xsl:apply-templates select="book" />
]
}
</xsl:template>
<xsl:template match="book">
{
"Title" : "<xsl:value-of select="title" />",
"Author" : "<xsl:value-of select="author" />",
"ISBN" : "<xsl:value-of select="isbn" />",
"Description" : "<xsl:value-of
select="description" />"
}
<xsl:if test="(position()!=last())">,</xsl:if>
</xsl:template>
</xsl:stylesheet><a:widget name="yahoo.dataTable"
service="/xhp?id=jersey-json" />
<a:widget name="yahoo.dataTable"
service="/xhp?id=jersey-xml" />

Please leave suggestions on other TOTD that you'd like to see. A complete archive is available here.
Technorati: totd jersey jmaki json netbeans glassfish
Posted by Arun Gupta in web2.0 | Comments[5]
|
|
|
|
|
Monday October 01, 2007
Europe Summer 2007 Trip Report
Here is a summary of my Europe Summer 2007 Trip Report:
GlassFish is the common theme between all these events, sessions and cities - that's what I was talking/preaching/demonstrating in all of them :) Here are all the detailed blogs covering each event:
During my travel, I posted several tips that are available at:
All my travel tips to Europe are aggregated here.
Technorati: conf glassfish netbeans jmaki metro jersey jruby suntechdays railsconfeurope
Posted by Arun Gupta in webservices | Comments[3]
|
|
|
|
|
Wednesday September 26, 2007
Sun Tech Days Rome 2007 was kick started by Maria Grazia Filippini (Director General, Sun Microsystems Italy) to a room full of approx 300 audience. She was followed by Corrado Sterpetti (Software Practice Manager, Sun Microsystems Italy). Both of them addressed the attendees in the local language. I could not understand any part of the talk (except bongiorno) but the passion was quite visible in their tone. And this is what brings Sun Tech Days back to Italy.
Reggie explained that this is 4th Sun Tech Days in Italy which is exactly the number of times Italy has won FIFA World Cup so far. It was fun when he divided the room in two halves and made them say "World" and "Cup" as he was waving his hand from left to right and wishing for Italy to win the 5th World cup in 2010.
The two main goals of the day set early in the day were:
Learn and Immerse in the different technologies presented.
Talk to one of the presenters and share with them how they can help you.
If you have attended any of the JavaOne, this is how John Gage sets the tone as well. And truly, this is one of the main objectives of taking Sun Tech Days all over the world. It's all about community and participation.
The first event of the day was a demo shoot out where 5 engineers demonstrated cool technology demonstrations. Here are the technologies that were demonstrated:
| Arun Gupta (me) | jMaki - Sun Tech Days Event Map |
| Sang Shin | NetBeans Profiler |
| Leonid Lenyashin | DTracelet in Sun Studio 12 |
| Sridhar Reddy | SunSPOT |
| Inyoung Cho | Java ME Technologies |
Then the day were split into three different tracks - Java, Solaris and Hands-on-Labs.
| The first talk in Java Track was presented by Sridhar on "Java EE 5, GlassFish and Their Future". GlassFish is an open-source, production-quality and JavaEE 5 compatible Application Server. GlassFish V2 is now available and has lots of cool features. This one slide captures all of them and Sridhar gave details on all of them. He also gave a preview of what's coming in GlassFish V3. GlassFish V2 Final can be downloaded from here. You can try a Technology Preview build of GlassFish V3 here. If you have any questions about GlassFish, please post them at users@glassfish or GlassFish Forum. |
|
Sridhar's talk was followed by my talk on "Metro and REST" where I explained how Metro is one-stop shop for all Web services needs - from simple Hello World to Secure, Reliable, Transactional and .NET 3.0 Interoperable Web services. The talk built upon Sridhar's demo where he showed how a simple Web service can be built and invoked using NetBeans 6. This talk demonstrated how Reliability and other enterprise features can be simply added by a click of button. It also demonstrated how an Excel 2007 client can invoke a Secure and Reliable endpoint deployed on GlassFish. This talk also provided a brief introduction to Jersey (Reference Implementation for JSR 311) and showed code samples on how it enables to easily and intuitively publishing RESTful endpoints. The slides for my talk are available here.
I had to leave right after my talk to catch the flight to Milan and so that's my summary of Tech Days Rome. I hope you guys had fun and we empowered you to be more productive. Feel free to leave comments if you attended and enjoyed.
GlassFish Day and NetBeans Day starts in Milan at 1pm local time today. The complete agenda is here. Looking forward to see you there.
Here is the album for Tech Days Rome 2007:
Technorati: suntechdays rome glassfish metro webservices jersey netbeans jmaki glassfish
Posted by Arun Gupta in webservices | Comments[3]
|
|
|
|
|
Monday September 10, 2007
TOTD #8: Generating JSON using JAXB annotations in Jersey
Jersey provides a pluggable type system for the encoding/decoding of a Java type to/from an entity of an HTTP response/request. JSON support was added in Jersey using the BadgerFish convention for encoding/decoding JAXB beans to/from JSON. A new sample was also added in the recently released 0.2.1 that demonstrates this concept.
This TOTD provides provides a trivial sample (using the snippets shown on
BadgerFish) that will allow you to
experiment with this feature in Jersey. This sample consists of a Resource,
Server and "build.xml" to build, deploy, run the server and invoke
the endpoint.
Here is the code for the REST resource:
import javax.ws.rs.HttpMethod;
import javax.ws.rs.ProduceMime;
import javax.ws.rs.UriTemplate;
@UriTemplate("/helloworld")
public class HelloWorldResource {
@HttpMethod
@ProduceMime("application/xml")
@UriTemplate("/xml")
public States getXML() {
return new alice();
}
@HttpMethod
@ProduceMime("application/json")
@UriTemplate("/json")
public States getJSON() {
return new alice();
}
}
This resource is published on two URIs - one using XML (/xml)
and the other using JSON (/json) representation. Here is the code
to start the server:
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;
import com.sun.ws.rest.api.container.ContainerFactory;
import java.io.IOException;
import java.net.InetSocketAddress;
public class HelloWorld {
public static void main(String[] args) throws IOException {
HttpHandler handler = ContainerFactory.createContainer(
HttpHandler.class,
HelloWorldResource.class);
HttpServer server = HttpServer.create(new
InetSocketAddress(9998), 0);
server.createContext("/", handler);
server.setExecutor(null);
server.start();
System.out.println("Server running");
System.out.println("Visit: http://localhost:9998/helloworld");
System.out.println("Hit return to stop...");
System.in.read();
System.out.println("Stopping server");
server.stop(0);
System.out.println("Server stopped");
}
}
This is a very standard code that is available in all the bundled samples.
And here is the "build.xml":
<project name="json" default="default" basedir=".">
<property name="jersey.home" value="c:\jersey-0.2.1-ea"/>
<path id="jersey.classpath">
<fileset dir="${jersey.home}\lib" includes="*.jar"/>
</path>
<property name="build.dir" value="build"/>
<property name="src.dir" value="src"/>
<target name="init">
<mkdir dir="${build.dir}"/>
</target>
<target name="build" depends="init">
<javac srcdir="${src.dir}" destdir="${build.dir}"
includes="**/*.java">
<classpath refid="jersey.classpath"/>
</javac>
</target>
<target name="run" depends="build">
<java classname="samples.HelloWorld" fork="true">
<classpath>
<path refid="jersey.classpath"/>
<pathelement location="${build.dir}"/>
</classpath>
</java>
</target>
<target name="get-json">
<get src="http://localhost:9998/helloworld/json" dest="out.json"/>
</target>
<target name="get-xml">
<get src="http://localhost:9998/helloworld/xml" dest="out.xml"/>
</target>
<target name="clean">
<delete quiet="true" dir="${build.dir}"/>
</target>
</project>
Make sure to set the value of "jersey.home" property correctly
in this file. And now the JAXB bean and corresponding XML and JSON
representation:
| JAXB Bean | XML representation | JSON representation |
@javax.xml.bind.annotation.XmlRootElement |
|
{"alice":{"$":"bob"}} |
@javax.xml.bind.annotation.XmlRootElement |
<alice> |
{"alice":{"bob":{"$":"charlie"},"david":{"$":"edgar"}}} |
@javax.xml.bind.annotation.XmlRootElement |
<alice charlie="david"> |
{"alice":{"@charlie":"david","$":"bob"}} |
@javax.xml.bind.annotation.XmlRootElement(namespace="http://some-namespace") |
<alice xmlns="http://some |
{"alice":{"@xmlns":{"$":"http:\/\/some-namespace"},"$":"bob"}} |
@javax.xml.bind.annotation.XmlRootElement |
<alice> |
{"alice":{"bob":[{"$":"charlie"},{"$":"david"}]}} |
JSON representation can always be constructed using the JSON APIs as shown
below and by adding the method to "HelloWorldResource":
import org.codehaus.jettison.json.*;
@HttpMethod("GET")
@ProduceMime("application/json")
@UriTemplate("/json2")
public JSONObject getJSONMessage() throws JSONException {
JSONObject object = new JSONObject();
JSONObject content = new JSONObject();
content.put("$", "bob");
object.put("alice", content);
return object;
}
JAX-WS also supports JSON as a pluggable encoding.
Please leave suggestions on other TOTD that you'd like to see. A complete archive is available here.
Technorati: totd jersey json jax-ws REST pluggableencoding restful
Posted by Arun Gupta in web2.0 | Comments[6]
|
|
|
|
|
Thursday September 06, 2007
Jersey is the open source JAX-RS (JSR 311) Reference Implementation for building RESTful Web services. Paul announced the availability of 0.2.1. This blog entry describe the steps to get started with Jersey and provide useful pointers for further exploration.
Download a stable build from
here or the latest binary from
here. jersey-xxx-ea.zip is the binary distribution and
jersey-snapshot-xxx-ea.zip is a snapshot of the SVN repository.
The bundle comes with all the required binaries (JAR dependencies) and a good set of samples for 0.2.1. Here is a consolidated list:
| HelloWorld | This is how everybody starts! |
| GlassFishDB | Demonstrates how to use JPA to expose the contents of a database table as a RESTful resource. |
| JsonFromJaxb | Demonstrates how to use JSON representation of JAXB-based resources. |
| EntityProvider | Demonstrates pluggable entity providers. |
| Bookmark | Demonstrates how to use JPA in the backend. |
| Bookstore | Demonstrates how to use ploymorphism with resources and views that are JSP pages. |
| OptimisticConcurrency | Demonstrates the application of optimistic concurrency to a web resource. |
| SimpleAtomServer | Simple Atom server that partially conforms to the Atom Publishing Format and Protocol |
| SimpleConsole | Demonstrates how to use the Lightweight HTTP Server included in Sun's Java SE 6.0 release. |
| SimpleJAXWSEndpoint | Demonstrates how to use a JAX-WS Endpoint. |
| SimpleServlet | Demonstrates how to use a Servlet container. |
| StorageService | Demonstrates a basic in-memory web storage service |
Pick a sample, most likely "Hello World", and then follow the instructions in the main "examples" directory to run the sample.
Getting Started - "Hello World" sample explained
As Alexis pointed, GlassFish is the preferred platform for deploying Jersey endpoints and NetBeans 6 will soon support Jersey.
Paul explained Why the name Jersey ? - Jersey is a restful place to spend a couple of days vacation. The Yellow jersey or Maillot jaune (the project logo) is worn by the overall leader in Le Tour. With modesty I would like this to be the leading open source project for developing RESTful Web services using plain old Java objects.
And then it could also be Java basEd RESTful Services for You as coined by Sridatta :)
Technorati: jersey jsr311 REST restful glassfish netbeans
Posted by Arun Gupta in web2.0 | Comments[10]
|
|
|
|
|
Today's Page Hits: 1003
Total # blog entries: 1002