Monday Jan 31, 2011

Java EE 6 & GlassFish @ JavaGruppen, JFokus, and Vaadin Meetup

Java EE 6 and GlassFish are floating to Denmark, Sweden, and Finland next week.

First stop is ... Javagruppen! This annual conference is organized by Danish JUG and this year the theme is "Java - a cloudy affair".

I'll be speaking on "Running your Java EE applications in the cloud".

Second stop is .... JFokus! This annual conference is organized by Javaforum, Swedish JUG, and will be celebrating 5th anniversary this year.

Here is the list of sessions presented by Oracle speakers ...

One of my sessions at JFokus will have a special guest but still need to confirm the exact time slot. Based upon previous experience, this guest adds great humor to the otherwise extremely technical talk and so stay tuned on that :-)

Show your presence and track this conference at lanyrd.

And the third stop is ... Vaddin Developer Meetup.

I'll be speaking on "OSGi and Java EE Hybrid Applications using GlassFish" at an interesting time of 9:35pm :-)

This is my first time visit to each of these conferences and so certainly looking forward to meeting everybody!

Its going to be really cold, at least for a Californian, at all these places so Runners World tips on winter/snow running and winter gear will be helpful.

Technorati: conf jfokus vaadin meetup javagruppen javaee6 glassfish netbeans osgi

Monday Jan 10, 2011

TOTD #154: Dynamic OSGi services in GlassFish 3.1 - Using CDI and @OSGiService

TOTD #131 explained how dynamic OSGi services can be easily created and deployed in GlassFish. The dynamism comes from the fact that the client keeps a reference to the service which is automatically refreshed if the bundle providing the service is refreshed. That tip used ServiceTracker API for the dynamic discovery of service which still uses some boilerplate code. In Java EE 6 environment, this can be further simplified by using CDI to inject the service and delegate all the service discovery/bind code to a CDI Qualifier available using CDI extensions in GlassFish 3.1.

Siva provides more details in his blog. But basically GlassFish 3.1 comes with a a standard CDI portable extension (org.glassfish.osgi-cdi) that intercepts deployment of hybrid applications that has components who have expressed dependencies on OSGi services. This CDI extension then takes care of discover, bind, inject, and track the service.

With this new CDI extension, the boilerplate code of dynamically tracking the service changes from:

ServiceTracker tracker = new ServiceTracker(context, Hello.class.getName(), null);
tracker.open();
Hello hello = (Hello) tracker.getService();
System.out.println(hello.sayHello("Duke"));

to

@Inject @OSGiService(dynamic=true) Hello hello;
System.out.println(hello.sayHello("Duke"));

No String-based and completely typesafe resolution of an OSGi service in a web application, how neat!

This will work in a "hybrid application" only, and not in pure web application, as BundleContext is required for dynamically tracking the service. Notice that by default the application is not ready to handle the dynamicity of OSGi environment and so "dynamic=true" need to be set explicitly on @OSGiService.

The complete source code for this application is available here. This project consists of 4 Maven modules:

  • helloworld-api
  • helloworld-impl
  • helloworld-client
  • helloworld-cdiclient

The first three modules are explained in detail at TOTD #131. Lets create "helloworld-cdiclient" module!

  1. In the parent directory of TOTD #131 zip file, create a new Maven module as:
    mvn archetype:create -DarchetypeGroupId=org.apache.maven.archetypes -DgroupId=org.samples.osgi.helloworld -DartifactId=helloworld-webclient
    

    Make sure to change the all the references from "totd131" to "totd154".
  2. The updated directory structure looks like:
    osgi.properties
    pom.xml
    src
    src/main
    src/main/java
    src/main/java/org
    src/main/java/org/samples
    src/main/java/org/samples/osgi
    src/main/java/org/samples/osgi/helloworld
    src/main/java/org/samples/osgi/helloworld/App.java
    src/main/resources
    src/main/webapp
    src/main/webapp/index.jsp
    src/main/webapp/WEB-INF
    src/main/webapp/WEB-INF/beans.xml
    
    1. "index.jsp" is generated by the Maven archetype
    2. "beans.xml" is a newly added file to enable CDI injection
    3. "osgi.properties" is a newly added file and is used to read the metadata for OSGi hybrid application
    4. "App.java" is a Servlet that invokes the service
  3. The "osgi.properties" file looks like:
    Web-ContextPath:/helloworld-cdiclient
    
    This makes sure that the hybrid application is accessible at "/helloworld-cdiclient" context root.
  4. The updated "pom.xml" looks like:
    <?xml version="1.0" encoding="UTF-8"?>
    <project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
             http://maven.apache.org/xsd/maven-4.0.0.xsd" 
             xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
      <modelVersion>4.0.0</modelVersion>
        <parent>
          <artifactId>totd154</artifactId>
          <groupId>org.samples.osgi.helloworld</groupId>
          <version>1.0-SNAPSHOT</version>
        </parent>
        <packaging>war</packaging>
        <groupId>org.samples.osgi.helloworld</groupId>
        <artifactId>helloworld-cdiclient</artifactId>
        <version>1.0-SNAPSHOT</version>
        <name>helloworld-cdiclient</name>
        <url>http://maven.apache.org</url>
        <dependencies>
          <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>3.8.1</version>
            <scope>test</scope>
          </dependency>
          <dependency>
            <groupId>org.samples.osgi.helloworld</groupId>
            <artifactId>helloworld-api</artifactId>
          </dependency>
          <dependency>
            <groupId>javax</groupId>
            <artifactId>javaee-api</artifactId>
            <version>6.0</version>
            <scope>provided</scope>
          </dependency>
          <dependency>
            <groupId>org.glassfish</groupId>
            <artifactId>osgi-cdi-api</artifactId>
            <version>3.1-SNAPSHOT</version>
            <scope>provided</scope>
          </dependency>
        </dependencies>
        <build>
          <pluginManagement>
            <plugins>
              <plugin>
                <groupId>org.apache.felix</groupId>
                <artifactId>maven-bundle-plugin</artifactId>
                <version>2.1.0</version>
                <extensions>true</extensions>
                <configuration>
                  <supportedProjectTypes>
                    <supportedProjectType>ejb</supportedProjectType>
                    <supportedProjectType>war</supportedProjectType>
                    <supportedProjectType>bundle</supportedProjectType>
                    <supportedProjectType>jar</supportedProjectType>
                  </supportedProjectTypes>
                  <instructions>
                    <!-- Read all OSGi configuration info from this optional file -->
                    <_include>-osgi.properties</_include>
                    <!-- By default, we don't export anything -->
                    <Export-Package>!\*.impl.\*, \*</Export-Package>
                  </instructions>
                </configuration>
                <executions>
                  <execution>
                    <id>bundle-manifest</id>
                    <phase>process-classes</phase>
                    <goals>
                      <goal>manifest</goal>
                    </goals>
                  </execution>
                  <execution>
                    <id>bundle-install</id>
                    <phase>install</phase>
                    <goals>
                      <goal>install</goal>
                    </goals>
                  </execution>
                </executions>
              </plugin>
              <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                  <source>1.5</source>
                  <target>1.5</target>
                </configuration>
              </plugin>
              <plugin> <!-- Need to use this plugin to build war files -->
                <artifactId>maven-war-plugin</artifactId>
                <groupId>org.apache.maven.plugins</groupId>
                <!-- Use version 2.1-beta-1, as it supports the new property failOnMissingWebXml -->
                <version>2.1-beta-1</version>
                <configuration>
                  <archive>
                    <!-- add bundle plugin generated manifest to the war -->
                    <manifestFile>
                      ${project.build.outputDirectory}/META-INF/MANIFEST.MF
                    </manifestFile>
                    <!-- For some reason, adding Bundle-ClassPath in maven-bundle-plugin
                         confuses that plugin and it generates wrong Import-Package, etc.
                         So, we generate it here.
                    -->
                    <manifestEntries>
                      <Bundle-ClassPath>WEB-INF/classes/
                      </Bundle-ClassPath>
                    </manifestEntries>
                  </archive>
                  <!-- We don't have a web.xml -->
                  <failOnMissingWebXml>false</failOnMissingWebXml>
                </configuration>
              </plugin>
            </plugins>
          </pluginManagement>
          <plugins>
            <plugin>
              <groupId>org.apache.felix</groupId>
              <artifactId>maven-bundle-plugin</artifactId>
            </plugin>
          </plugins>
       </build>
    </project>
    

    Screencast #32 provide a detailed explanation of this "pom.xml". A basic introduction to "hybrid applications" is given here.
  5. The updated "App.java" looks like:
    package org.samples.osgi.helloworld;
    
    import java.io.IOException;
    import java.io.PrintWriter;
    import javax.inject.Inject;
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import org.glassfish.osgicdi.OSGiService;
    import org.samples.osgi.helloworld.api.Hello;
    
    /\*\*
     \* Hello world!
     \*/
    @WebServlet(urlPatterns = {"/HelloWebClient"})
    public class App extends HttpServlet {
        
        @Inject @OSGiService(dynamic=true) Hello hello;
    
        @Override
        public void doGet(HttpServletRequest request, HttpServletResponse response)
                throws IOException, ServletException {
            PrintWriter out = response.getWriter();
            out.println(hello.sayHello("Duke"));
        }
    }
    

    This is a "web.xml"-free servlet using @WebServlet. "@OSGiService" is used to dynamically discover, bind, inject, and track the service. So if the backend service changes then the service reference is automatically updated without any additional effort.
  6. Build and Deploy this project as:
    mvn clean install
    asadmin deploy --type=osgi  target/helloworld-cdiclient-1.0-SNAPSHOT.war
    
    Optionally you can also drop this generated WAR file to "glassfish/domains/domain1/autodeploy/bundles" directory as well.
  7. Run the app
    1. Make sure helloworld-api-\* and helloworld-impl-\* bundles are already deployed as explained in TOTD #131.
    2. Invoking "curl http://localhost:8080/helloworld-cdiclient/HelloWebClient" shows the result as "Hello Duke".
    3. Change "org.samples.osgi.helloworld.impl.HelloImpl" to use "Howdy" string instead of "Hello", build the bundle again (mvn clean install), and copy it to the "glassfish/domains/domain1/autodeploy/bundles" directory.
    4. Invoking "curl http://localhost:8080/helloworld-cdiclient/HelloWebClient" now shows the result as "Howdy Duke". This ensures that the service changes are dynamically tracked.

I tried this with GlassFish 3.1 build 35 Web Profile.

Read the latest about GlassFish and OSGi integration on this wiki.

Where are you deploying your OSGi applications ?

Technorati: totd osgi javaee6 glassfish dynamic discovery

Wednesday Nov 17, 2010

TOTD #150: Collection of GlassFish, NetBeans, JPA, JSF, JAX-WS, EJB, Jersey, MySQL, Rails, Eclipse, and OSGi tips

This is the 150th tip published on this blog so decided to make it a collection of all the previous ones. Here is a tag cloud (created from wordle.net/create) from title of all the tips:

As expected GlassFish is the most prominent topic. And then there are several entries on NetBeans, JRuby/Rails, several Java EE 6 technologies like JPA, JAX-WS, JAX-RS, EJB, and JSF, and more entries on Eclipse, OSGi and some other tecnhologies too. Here is a complete collection of all the tips published so far:

Just for fun, here is another tag cloud:

You can access all the tips here. And keep those suggestions coming!

Technorati: totd glassfish netbeans jpa jsf jaxws jersey mysql rails osgi eclipse

Friday Oct 15, 2010

Java EE 6 & GlassFish @ Silicon Valley Code Camp 2010 Trip Report - Slides Now Available

What's common between 350 Mountain Mike's Pizza, 920 Erik's Deli Sandwiches, 29 huge jugs of Peet's Coffee, and 194 geek sessions ?

It takes 1876 developers, hackers, architects, technology honchos etc to consume all of them over a weekend :-)

Yes, we are talking about Silicon Valley Code Camp 5.0!

This is a for the developer community, by the developer community, and to the developer community event focused on Agile, Cloud, HTML5, Google Developer Tools & Platforms, Java, Web services, and many other topics. The code camp website shows attendance records from the previous years as:

A slightly updated view of this data is:

As you can see, there is steady year/year growth in the number of sessions, registration, and attendance. This year specifically has seen about 60% growth on registrations and 80% on the actual attendance. The ratio between registered/attended was also steady for the first few years and has also gone higher this year. This event has truly grown organically over the past years and is the second biggest conference, with Java focus, in the USA after JavaOne! Oracle certainly was a platinum sponsor of this conference. Are there any other bigger conferences that I don't know of ? ;-)

It would be interesting to revisit this pattern if the event starts charging a nominal (may be optional) fees from all the attendees. However the main website highlights three points:

  • by/for the developer community
  • always free
  • never occur during work hours

GlassFish team presented several sessions at the Code Camp:

  1. Java EE 6: Doing More with Less
  2. Java EE 6 Tooling
  3. Introduction to JAX-RS
  4. Servlets 3.0: Asynchronous, Extensible, Easy-to-use
  5. OSGi and Java EE in GlassFish
  6. Running your Java EE 6 applications in the Cloud

I could not deliver #5 due to a conflict but slides from all the sessions are now available:

Here are some key pointers for you:

Check out the complete list of sessions by Oracle at the Code Camp. Please enter session evaluations at http://siliconvalley-codecamp.com/SessionsOverview.aspx (make sure you are logged in and then click the link at the end of the session you attended that says 'Evaluate').

The Android App was pretty useful, did not try the iPhone App. I wonder if there was a session on "How I created the Android/iPhone App" :-)

Personally, this was my fourth code camp (2009, 2008, 2007) and I enjoyed meeting the local geek community. I could barely spend Saturday morning at the code camp and delivered two of my sessions but its always fun to meet the usual suspects. Many thanks to Peter Kellner, Van Riper, Tammy Baker, Kevin Nilson, other organizers, and many other volunteers for running a great show!

Couple of suggestions for next year ...

  • Expose the RESTful API for the code camp registration/session/speaker/etc data and organize a competition on the best created app. May be a panel with different attendees who attempted to build this application ?
  • Make sure the speakers are not running across the campus between their back-to-back talks. 

Check out some of the pictures:


And the complete photo album:

Looking forward to Silicon Valley Code Camp 6.0 next year!

Technorati: conf svcc javaee6 glassfish netbeans eclipse intellij cloud osgi servlets restful

Sunday Oct 03, 2010

Screencast #32: OSGi-enabled Java EE Applications using NetBeans and GlassFish

OSGi provides the benefit of modularity, dependency management, service dynamism, and others. Java EE provides persistence, security, transaction management and other similar services. The Enterprise Expert Group in OSGi Alliance defines how to mix and match the Java EE APIs in OSGi. The Release 4 Version 4.2 of Enterprise Specification defines how several Java EE specifications such as JPA, JNDI, JMX, and WAR file specification can work with OSGi and levarage its benefits.

Sahoo & Siva gave a talk at JavaOne 2010 explaining the approach and advantages of writing such applications, their slides are available below:

This 6-part screencast shows how to develop OSGi-enabled Java EE applications using NetBeans and deploy them on GlassFish. The screencast creates a simple OSGi service which is invoked by OSGi client. The same OSGi service is then invoked by Web Application Bundle (WAB) client that is a Web Application + OSGi bundle, a.k.a hybrid application. The OSGi service is then replaced by an EJB-based service using Java Persistence API. This shows how OSGi client and service can seamlessly interoperate with Java EE counterparts.

Specifically, the different parts show:

1. How to create a parent POM project
2. API and Service OSGi Bundle
3. Client OSGi Bundle invoking an OSGi Service
4. Web Application Bundle (WAB) client invoking an OSGi service
5. Client OSGi bundle invoking EJB service
6. Conclusion and other possible extensions

This entire exercise was scheduled as S313522 hands-on lab at JavaOne 2010 but could not be conducted because of technical difficulties. We hope you are able to follow the steps mentioned below and benefit from it.

Please download and install NetBeans 6.9.1 and download the following zip files before attempting the exercise:

  1. GlassFish 3.1 b20 Web Profile
  2. GlassFish OSGi Feature Pack for 3.1 b20
  3. S313522 Detailed Docs + Solutions

If you are using a different build of GlassFish then the OSGi Feature Pack can be downloaded by executing the following script in "glassfish/modules/autostart" directory and giving the build number as the first parameter:

curl -C - -O http://download.java.net/maven/glassfish/org/glassfish/osgi-http/3.1-b$1/osgi-http-3.1-
b$1.jar
curl -C - -O http://download.java.net/maven/glassfish/org/glassfish/osgi-platforms/felix-webconsole-
extension/3.1-b$1/felix-webconsole-extension-3.1-b$1.jar
curl -C - -O http://download.java.net/maven/glassfish/org/glassfish/osgi-jpa/3.1-b$1/osgi-jpa-3.1-b$
1.jar
curl -C - -O http://download.java.net/maven/glassfish/org/glassfish/osgi-ejb-container/3.1-b$1/osgi-
ejb-container-3.1-b$1.jar
curl -C - -O http://download.java.net/maven/glassfish/org/glassfish/admingui/glassfish-osgi-console-
plugin/3.1-b$1/glassfish-osgi-console-plugin-3.1-b$1.jar
curl -C - -O http://www.reverse.net/pub/apache/felix/org.apache.felix.webconsole-3.1.2.jar

A typical execution of this script might look like:

./gf-osgi-fp.sh 20
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 27522  100 27522    0     0  74967      0 --:--:-- --:--:-- --:--:--  120k
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  6795  100  6795    0     0  17811      0 --:--:-- --:--:-- --:--:-- 24068
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 24342  100 24342    0     0  59168      0 --:--:-- --:--:-- --:--:--  108k
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 16145  100 16145    0     0  72180      0 --:--:-- --:--:-- --:--:--  186k
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 18724  100 18724    0     0  35921      0 --:--:-- --:--:-- --:--:-- 48785
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  602k  100  602k    0     0   636k      0 --:--:-- --:--:-- --:--:--  748k

Enjoy the video!


How are you using OSGi and Java EE together ? What other OSGi features would you like to see in GlassFish ?


Technorati: screencast javaone osgi javaee netbeans glassfish

Thursday Sep 30, 2010

Java EE 6 & GlassFish @ JAX London & London JUG Trip Report

JAX London had its second conference of the year and the venue was shared with DevCon and OSGi DevCon. The tri-partite conference gave the attendees an option to attend a variety of sessions from a good quality of speakers. There were about approximately 250 attendees and I think the number is commendable considering this is only the second conference. The good news is that there is only room to grow :-)

I gave a presentation on "Running your Java EE applications in the Cloud" and the slides are available below:

The talk explained

  • Oracle's definition of Cloud and talked about Exalogic Elastic Compute Cloud, a.k.a "Cloud in a box"
  • Light-weight ness, extensibility, and simplicity/ease-of-use of Java EE 6
  • How to run Java EE 6 on Amazon, RightScale, Elastra, and Joyent
  • What Java EE currently offers for the Cloud and what's coming in Java EE 7

Because of a last minute speaker cancellation for the JAX Community Night I also got a chance to show a live demo of how NetBeans provides extensive and powerful tooling around Java EE 6 & GlassFish. Check out screencast #30 to view the complete set of Java EE 6 Netbeans tooling. Java EE 6 tooling is also available in Eclipse and can be seen in the screencast #31.

I had a good conversation with Sebastien Meyen who is the organizer of JAX conferences and hopefully you'll see more presence of Java EE 6 & GlassFish in their upcoming events ;-) He recorded a video segment for JAX TV and the link will be shared when its live.

Barry Cranford, London JUG leader, graciously arranged for a talk at their local meeting. And of course I talked on the Java EE 6 & GlassFish 3: Light-weight, Extensible, and Powerful and the slides are available below:

The talk explained how Java EE 6 is an extreme makeover from its previous versions and provides a light-weight, extensible, and powerful platform to build your enterprise and Web applications. The talk explained how several new key specifications like Contexts & Dependency Injection, Bean Validation, and Java API for RESTful Web Services 1.1 in the platform are making it really powerful and rich. It also explained how the existing specifications like  Java Server Faces, Servlets, Java Persistence API, and Enterprise Java Beans have gone over an extreme makeover to make the platform easier and intuitive to use. And its always fun to talk about the latest set of features coming in GlassFish 3.1 like Clustering, High Availability, Application Versioning, SSH-based Administration and Provisioning, and Application-scoped Resources. The Java EE 6 code sample built during the meeting can be downloaded here.

Here is some feedback posted on the event page:

Great speaker and great talk, with a perfect pace and content!

It was great. I particularly like that it was presented with examples, and you could really see how it works, and not only someone explaining how it would work

This was a very insightful and engaging session with a good mix of technical detail and completely live demo. The presenter was very skilled and knowledgeable and had a great way of expressing concepts and details easily.

Great presentation and demos. Had underestimated the tooling in Netbeans IDE so the demos were great. Good opportunity to meet Arun Gupta, whose blog I spend time reading

Very good presentation. The key point that Glassfish restores session information over multiple restarts was very helpfull for me. Also learnt quite a few titbits throughout the presentation , which I am sure will come very handy.

An excellent presentation which covered a good subset of a very wide topic to an adequate depth. A great overview of some of the compelling new features in JEE6.

Now this is London and pub culture is very prominent here, yes even on weekdays :) So we got together at a nearby pub - The Slaughtered Lamb - and it was good discussing with JUG attendees and fellow beer drinkers on why Oracle will do the right thing for Java.

Most of the major European conferences like Devoxx, JFall, and JFokus are organized by a local JUG. I seeded that thought with Sebastien and Barry and hopefully the energies will synthesize and the conference will grow. Overall, a short visit for me but gave me an opportunity to meet with several other speakers and create more community connections for GlassFish, and in general for Oracle :-)

Let us know how are you using GlassFish by posting a comment on this blog.

Technorati: conf jax london devcon osgi javaee6 glassfish 

Tuesday Sep 21, 2010

S313522: Instructions for OSGi-enabled Java EE Applications Hands-on Lab at JavaOne 2010

This blog provides instructions on how to follow S313522 (Hands-on Lab on OSGi-enabled Java EE Applications) that was conducted at JavaOne 2010 earlier today.

  1. Download and Install NetBeans 6.9.1.
  2. Download and Unzip GlassFish 3.1 b20 Web Profile.
  3. Start GlassFish as "asadmin start-domain" and Database as "asadmin start-database" from "glassfishv3/glassfish/bin" directory.
  4. Go to "glassfishv3/glassfish/modules/autostart" directory and execute the following script:
    #!/bin/sh -x
    wget http://download.java.net/maven/glassfish/org/glassfish/osgi-http/3.1-b20/osgi-http-3.1-b20.jar
    wget http://download.java.net/maven/glassfish/org/glassfish/osgi-platforms/felix-webconsole-extensio
    n/3.1-b20/felix-webconsole-extension-3.1-b20.jar
    wget http://download.java.net/maven/glassfish/org/glassfish/osgi-jpa/3.1-b20/osgi-jpa-3.1-b20.jar
    wget http://download.java.net/maven/glassfish/org/glassfish/osgi-ejb-container/3.1-b20/osgi-ejb-cont
    ainer-3.1-b20.jar
    wget http://download.java.net/maven/glassfish/org/glassfish/admingui/glassfish-osgi-console-plugin/3
    .1-b20/glassfish-osgi-console-plugin-3.1-b20.jar
    wget http://www.reverse.net/pub/apache//felix/org.apache.felix.webconsole-3.1.2.jar
    This is going to download the required OSGi bundles.

Refer to detailed docs and completed solutions to get started. A detailed screencast highlighting the exact set of steps will be available next week.

Technorati: conf javaone handson osgi javaee glassfish netbeans

Monday Jun 21, 2010

Uber Conf 2010 - Day 4 Report - OSGi/Java EE in GlassFish and Getting Started with Clojure


Uber Conf Day 4 (Day 3, 2, and 1) started with yet another 10 miler with fellow attendees in 1 hr 18 mins and 7:49 pace. It was slightly slower than the day before - guess physical exhaustion was setting in ;-) Here are the mile splits:

Thanks to Andy for showing how to turn on the Auto-Lap feature in Garmin 305 ... really handy!

I gave a talk on how GlassFish provides a great execution environment for deploying OSGi, Java EE, and hybrid applications easily. The slides are given below:

The remainder of the day was spent in Clojure track by Stuart Halloway. Next are some basic notes for getting started with Clojure:

Why Clojure ?

  • Power (hosted on jvm)
  • Robustness (functional)
  • Concurrency (identity, state, time)
  • Abstraction (OO done right)
  • Focus (lisp)

Together, these features add up to simplicity. Simplicity means

  • absence of incidental complexity
  • sufficient to meet your design constraints

Simplicity does not mean

  • Familiarity has nothing to do with simplicity
  • its not superficial, goes to the bone (e.g. only simpler syntax is just a sugar wrapper, look for the supported idioms)
  • does not mean easy, its very hard to be simple

Lot of code in Clojure is not about "set" something, its about invoke a function on it.

How to get started ?

Download the latest stable release or cutting edge build. The Clojure REPL (Read-Evaluate-Print Loop) is the easiest way to run a Clojure program as shown below:

~/tools/clojure/clojure-1.1.0 >java -cp clojure.jar clojure.main
Clojure 1.1.0
user=> (print "Hello World")
Hello Worldnil
user=> \^D

OR

~/tools/clojure/jun7 >java -cp clojure.jar clojure.main
Clojure 1.2.0-master-SNAPSHOT
user=> (print "Hello World")
Hello Worldnil
user=> \^D

Notice, the first fragment shows how to run REPL using the latest stable release and the second fragment shows the same using the cutting edge build. "Ctrl+D" exits the REPL shell. Stuart mentioned that the Clojure community stays on the cutting edge build most of the times.

Alternatively, you can also clone "labrepl" from "http://github.com/relevance/labrepl" which is an environment for exploring the Clojure language. It also provides complete instructions for getting started with NetBeans/Enclojure, Eclipse/Counterclockwise, Maven, Max/Linux command line, Windows command line, IDEA/La Clojure, and Emacs.

Configuring Clojure in NetBeans using the Enclojure plugin with NetBeans 6.9 gives the following error:

but works easily with NetBeans 6.8. The IDE seem to support REPL, Java/Clojure integration, syntax highlighting, brace/paren/bracket matching, code navigation, debugger and lots of interesting features.

Here is a typical REPL getting started session with NetBeans and Enclojure:

Here are some equivalent syntax with Java:

Semantic Java Clojure
new new Widget("foo") (Widget. "foo")
Access static members Math.PI Math/PI
Access instance members rnd.nextInt() (.nextInt rnd)
Chaining access person.getAddress().getZipCode() (.. person getAddress getZipCode)
  • "defn" is a symbol so no new syntax for adding a method.
  • \^ introduces metadata for the next symbol, "greet" in this case. You can put metadata anywhere.
  • "clojure.core" is the core of Clojure's implementation
  • "javadoc" knows the default JDK javadocs, can make a local copy and/or extend it
  • "show" is Java reflection
  • "dir", "show", "source" are promoted from community version to the bleeding edge build.
  • Source is not always exposed
  • [1 2 3] Call the function 1 with arguments 2 & 3.
  • '(1 2 3) don't evaluate it and print as is, just tick it.
  • Idiomatically Clojure requires less parentheses than Java
  • Every single function in Clojure is Runnable and Callable

  • Java interop is simple, wrapper-free (raw), performant, complete

Compojure is a small, open source Web framework for Clojure based upon Ring (similar to Python's WSGI and Ruby's Rack). Otherwise Clojure apps are deployed as a JAR file.

A subsequent blog will show how to deploy a simple Clojure JAR file and a simple web app using Compojure on GlassFish.

And finally, here are my top-10 reasons (in no particular order) that I'd like to attend UberConf next year:

  1. Long 90 minute sessions
  2. Lots of hands-on workshops
  3. Fun Run as part of the formal agenda
  4. Beautiful location (Westin Westminster) with lots of running trails
  5. Great food (breakfast + lunch + dinner)
  6. Small attendance so intimate discussions with speakers
  7. Great set of speakers
  8. Rarely see session hopping
  9. Pure technology, no product pitching
  10. Swags are nice - bracelet-style USB stick with all the presos, 2 different tee-shirts, fancy folder and some additional goodies for speakers

See ya next year, hopefully!

Check out the complete set of pictures at:

Technorati: conf uberconf denver clojure compojure glassfish netbeans javaee osgi

Wednesday Jun 02, 2010

TOTD #140: Moving GlassFish Installation - Referenced file does not exist "osgi-main.jar"

This is a quick Tip Of The Day (TOTD) to show how to get GlassFish running again if the directory is moved to a new location after it has been started once. Note, of course, you are not moving the directory while the server is running. Its only after the server has been started once at least and stopped.

If you move your GlassFish installation to a different directory then you may see errors like:

ERROR: Error creating archive. (java.io.IOException: Referenced file does not exist: /Users/arungupta/tools/glassfish/v3/glassfishv3/glassfish/modules/osgi-main.jar)
java.io.IOException: Referenced file does not exist: /Users/arungupta/tools/glassfish/v3/glassfishv3/glassfish/modules/osgi-main.jar
        at org.apache.felix.framework.cache.BundleArchive.createRevisionFromLocation(BundleArchive.java:994)
        at org.apache.felix.framework.cache.BundleArchive.revise(BundleArchive.java:631)
        at org.apache.felix.framework.cache.BundleArchive.(BundleArchive.java:206)
        at org.apache.felix.framework.cache.BundleCache.getArchives(BundleCache.java:149)
        at org.apache.felix.framework.Felix.init(Felix.java:558)
        at org.apache.felix.main.Main.main(Main.java:292)
. . .
org.osgi.framework.BundleException: Bundle symbolic name and version are not unique: com.sun.grizzly.grizzly-config:1.9.18.k
 at org.apache.felix.framework.BundleImpl.createModule(BundleImpl.java:1145)
 at org.apache.felix.framework.BundleImpl.<init>(BundleImpl.java:79)
 at org.apache.felix.framework.Felix.installBundle(Felix.java:2372)
. . .
May 30, 2010 4:27:05 PM Main install
WARNING: Failed to install file:/Users/arungupta/tools/glassfish/v3/glassfishv3-2/glassfish/modules/grizzly-config.jar
org.osgi.framework.BundleException: Bundle symbolic name and version are not unique: com.sun.grizzly.grizzly-config:1.9.18.k
 at org.apache.felix.framework.BundleImpl.createModule(BundleImpl.java:1145)
 at org.apache.felix.framework.BundleImpl.<init>(BundleImpl.java:79)
 at org.apache.felix.framework.Felix.installBundle(Felix.java:2372)
. . .

Fortunately the fix is simple, just remove your "domains/domain1/osgi-cache" directory. The cache will be rebuilt during the next run of GlassFish.

Technorati: totd glassfish v3 osgi cache error

Wednesday Apr 28, 2010

TOTD #131: Dynamic OSGi services in GlassFish - Using ServiceTracker

OSGi is the dynamic module system for Java. Each module, or bundle as called in OSGi terminology, is packaged as a JAR file and the inbound and outbound dependencies are explicitly defined using the META-INF/MANIFEST.MF in the JAR file. A complex software system may be broken into multiple modules where each module may be exposing a set of services. These services are then consumed by some other "client" OSGi bundles. The beauty of dynamic nature of OSGi is that each bundle can be easily updated without restarting the framework and any reference to the service in the "client" bundles is also updated accordingly. However the client needs to ensure that they are watching out for changes in the lifecycle of "service" bundle.

GlassFish's modular architecture is based upon OSGi. The different capabilities such as Web container, EJB container, and RESTful Web services are provided as OSGi modules. The OSGi framework is available to developers as well so that they can construct their application as OSGi modules and leverage all the goodness.

This Tip Of The Day (TOTD) explains an OSGi design pattern that allows the client to track the dynamic discovery of an OSGi service. This means that client keeps a reference to the service which is automatically refreshed if the bundle providing the service is refreshed. And of course, it uses GlassFish to deploy the bundles :-)

For those, who prefer to see the results directly, download and unzip this zip file:

  1. Give the following command in the root directory:
    mvn clean install
    
  2. Copy the generated bundles to "domains/domain1/autodeploy/bundles" directory as:
    cp helloworld-api/target/helloworld-api-1.0-SNAPSHOT.jar \\
    helloworld-impl/target/helloworld-impl-1.0-SNAPSHOT.jar \\
    helloworld-client/target/helloworld-client-1.0-SNAPSHOT.jar \\
    ~/tools/glassfish/v3/final/glassfishv3/glassfish/domains/domain1/autodeploy/bundles
    

    The following log messages will be displayed in the console:
    [#|2010-04-28T17:03:55.090-0700|INFO|glassfishv3.0|javax.enterprise.system.std.com.sun.enterprise.v3.
    services.impl|_ThreadID=23;_ThreadName=Thread-23;|Getting a new service|#]
    
    [#|2010-04-28T17:03:55.091-0700|INFO|glassfishv3.0|javax.enterprise.system.std.com.sun.enterprise.v3.
    services.impl|_ThreadID=23;_ThreadName=Thread-23;|Hello Duke|#]
    
    [#|2010-04-28T17:03:57.091-0700|INFO|glassfishv3.0|javax.enterprise.system.std.com.sun.enterprise.v3.
    services.impl|_ThreadID=23;_ThreadName=Thread-23;|Getting a new service|#]
    
    [#|2010-04-28T17:03:57.092-0700|INFO|glassfishv3.0|javax.enterprise.system.std.com.sun.enterprise.v3.
    services.impl|_ThreadID=23;_ThreadName=Thread-23;|Hello Duke|#]
    
    

    The log messages from the client bundle invoking the service bundle are highlighted in bold.
  3. Update the service implementation
    1. Edit service implementation in "hello-impl/src/main/java/org/samples/osgi/helloworld/impl/HelloImpl.java" and change the "return" statement from:
      return "Hello " + name;
      
      to
      return "Howdy " + name;
      
    2. Create the service implementation bundle again by giving the command:
      mvn clean install
      

      in the "helloworld-impl" directory.
    3. Copy the updated bundle from "helloworld-impl/target/helloworld-impl-1.0-SNAPSHOT.jar" to "glassfishv3/glassfish/domains/domain1/autodeploy/bundles" directory. The following sequence of log messages will be seen:
      [#|2010-04-28T17:04:47.110-0700|INFO|glassfishv3.0|javax.enterprise.system.std.com.sun.enterprise.v3.
      services.impl|_ThreadID=23;_ThreadName=Thread-23;|Getting a new service|#]
      
      [#|2010-04-28T17:04:47.110-0700|INFO|glassfishv3.0|javax.enterprise.system.std.com.sun.enterprise.v3.
      services.impl|_ThreadID=23;_ThreadName=Thread-23;|Hello Duke|#]
      
      [#|2010-04-28T17:04:48.151-0700|INFO|glassfishv3.0|javax.enterprise.system.std.com.sun.enterprise.v3.
      services.impl|_ThreadID=22;_ThreadName={felix.fileinstall.poll=5000, 
      felix.fileinstall.bundles.new.start=true, service.pid=org.apache.felix.fileinstall.b0b03c1b-5a58-457d-bfde-116be31299f0,
      felix.fileinstall.dir=/Users/arungupta/tools/glassfish/v3/final/glassfishv3/glassfish/domains/domain1
      /autodeploy/bundles/, felix.fileinstall.filename=org.apache.felix.fileinstall-autodeploy-bundles.cfg, 
      service.factorypid=org.apache.felix.fileinstall, felix.fileinstall.debug=1};|Updated 
      /Users/arungupta/tools/glassfish/v3/final/glassfishv3/glassfish/domains/domain1/autodeploy/bundles/
      helloworld-impl-1.0-SNAPSHOT.jar|#]
      
      [#|2010-04-28T17:04:49.110-0700|INFO|glassfishv3.0|javax.enterprise.system.std.com.sun.enterprise.v3.
      services.impl|_ThreadID=23;_ThreadName=Thread-23;|Getting a new service|#]
      
      [#|2010-04-28T17:04:49.111-0700|INFO|glassfishv3.0|javax.enterprise.system.std.com.sun.enterprise.v3.
      services.impl|_ThreadID=23;_ThreadName=Thread-23;|Howdy Duke|#]
      

      As evident from the log messages, "Hello Duke" message is printed first, the service implementation bundle gets refreshed, and then the message from the updated service implementation, i.e. "Howdy Duke" is printed. Notice, only the service implementation got refreshed.

Now some explanation!

The application is split into 3 bundles - API, Impl, and Client. Splitting into 3 bundles allows cleaner separation and other implementations of the service  to show up relying purely upon the API bundle.

The "API" bundle (helloworld-api) has one class with the following interface:

package org.samples.osgi.helloworld.api;

public interface Hello {
    public String sayHello(String name);
}

This bundle has the following manifest entry:

<Export-Package>${pom.groupId}.api</Export-Package>

to ensure that the package with the service interface is exported and available for imports by service implementers. The "Impl" bundle (helloworld-impl) has the trivial implementation of this interface as:
package org.samples.osgi.helloworld.impl

import org.samples.osgi.helloworld.api.Hello;

public class HelloImpl implements Hello {
    public String sayHello(String name) {
        return "Hello " + name;
    }
}

And the bundle's activator registers the service as:

package org.samples.osgi.helloworld.impl;

import java.util.Properties;
import org.samples.osgi.helloworld.api.Hello;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;

public class App implements BundleActivator {

    public void start(BundleContext bc) throws Exception {
        bc.registerService(Hello.class.getName(), new HelloImpl(), new Properties());
    }

    public void stop(BundleContext bc) throws Exception {
        bc.ungetService(bc.getServiceReference(Hello.class.getName()));
    }
}

This bundle defines the dependency on the package exported earlier as:

<dependency>
 <groupId>${pom.groupId}</groupId>
 <artifactId>helloworld-api</artifactId>
 <version>1.0-SNAPSHOT</version>
 </dependency>

and also imports the appropriate packages as:

<Import-Package>${pom.groupId}.api, org.osgi.framework</Import-Package>

The "client" bundle's (helloworld-client) activator uses "org.osgi.util.tracker.ServiceTracker" for the dynamic discovery of service. The code looks like:

package org.samples.osgi.helloworld.client;

import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.osgi.util.tracker.ServiceTracker;
import org.samples.osgi.helloworld.api.Hello;

public class App implements BundleActivator {
    BundleContext ctx;
    ServiceTracker tracker;

    public void start(BundleContext context) {
        System.out.println("Starting client bundle");

        this.ctx = context;        

        // Create a service tracker to monitor Hello services.
        tracker = new ServiceTracker(context, Hello.class.getName(), null);
        tracker.open();

        new PingService(tracker).start();
    }

    public void stop(BundleContext context) {
        System.out.println("Stopping client bundle");
        tracker.close();
    }

    private class PingService extends Thread {
        ServiceTracker tracker;

        PingService(ServiceTracker tracker) {
            this.tracker = tracker;
        }

        public void run() {
            try {
                while (true) {
                    Thread.sleep(2000);
                    System.out.println("Getting a new service");
                    Hello hello = (Hello) tracker.getService();
                    if (hello == null)
                        System.out.println("No service found!"); 
                    else      
                        System.out.println(hello.sayHello("Duke"));
                }
            } catch (InterruptedException ex) {
                ex.printStackTrace();
            }
        }
    }
}

The ServiceTracker API allows customized service tracking and find services that meet search criteria defined by filters. Basically it listens to different service events and gets/ungets the service accordingly. In this case, a "ServiceTracker" is created to track the service by specifying the class name. The "tracker.open()" starts the service tracking. A new thread is started which pings the service every 2 seconds and prints the received response. Notice, a new service is retrieved from the service tracker as the service bundle might have been refreshed.

Please read through OSGi javadocs for more details on these APIs.

A future blog will show how a Java EE 6 MVC-based application can be split into multiple OSGi bundles using this design pattern.

How are you using dynamic discovery of services in OSGi ?

Technorati: totd osgi modules glassfish v3 felix dynamic discovery

About

profile image
Arun Gupta is a technology enthusiast, a passionate runner, author, and a community guy who works for Oracle Corp.


Java EE 7 Samples

Stay Connected

Search

Archives
« April 2014
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
   
       
Today