Saturday Jan 26, 2013

Java EE 7 Maven Application (TOTD #197)

Did you know that Java EE 7 APIs are now published in maven ?

The complete set of coordinates are described here. So how do you build a simple Java EE 7 maven application ?

  1. Generate the ususal Java EE 6 maven application as:

    mvn -DarchetypeGroupId=org.codehaus.mojo.archetypes -DarchetypeArtifactId=webapp-javaee6 -DarchetypeVersion=1.5 -DarchetypeRepository=http://repo.maven.apache.org/maven2 -DgroupId=org.glassfish -DartifactId=hello-javaee7 -Dversion=1.0-SNAPSHOT -Dpackage=org.glassfish.hellojavaee7 -Darchetype.interactive=false --batch-mode archetype:generate
  2. In the generated pom.xml, replace
    <dependencies>
    <dependency>
    <groupId>javax</groupId>
    <artifactId>javaee-web-api</artifactId>
    <version>6.0</version>
    <scope>provided</scope>
    </dependency>
    </dependencies>

    with

    <repositories>
    <repository>
    <id>Java EE 7</id>
    <url>https://maven.java.net/content/groups/promoted/</url>
    </repository>
    </repositories>

    <dependencies>
    <dependency>
    <groupId>javax</groupId>
    <artifactId>javaee-api</artifactId>
    <version>7.0-b72</version>
    </dependency>
    </dependencies>

    Notice, there is a new <version> of dependency for each GlassFish 4 promoted build. This may be simplified in the coming builds.

    The <artifactId> can be changed to javaee-web-api if your application requires Java EE 7 Web Profile API only.

And now all Java EE 7 APIs so far integrated in GlassFish are available in your application.

You can also include specific API JAR files explicitly in your project directly. The latest APIs are available in the format:

In general, you can replace "b72" in the URL with the latest promoted build number to get the latest artifacts. A simplified URL for the latest set of these artifacts is in the works!

What next ? Maven archetype and support in NetBeans coming soon!

Thursday Jul 05, 2012

Jersey 2 in GlassFish 4 - First Java EE 7 Implementation Now Integrated (TOTD #182)


The JAX-RS 2.0 specification released their Early Draft 3 recently. One of my earlier blogs explained as the features were first introduced in the very first draft of the JAX-RS 2.0 specification. Last week was another milestone when the first Java EE 7 specification implementation was added to GlassFish 4 builds.

Jakub blogged about Jersey 2 integration in GlassFish 4 builds. Most of the basic functionality is working but EJB, CDI, and Validation are still a TBD. Here is a simple Tip Of The Day (TOTD) sample to get you started with using that functionality.
  1. Create a Java EE 6-style Maven project

    mvn archetype:generate
    -DarchetypeGroupId=org.codehaus.mojo.archetypes
    -DarchetypeArtifactId=webapp-javaee6 -DgroupId=example
    -DartifactId=jersey2-helloworld -DarchetypeVersion=1.5
    -DinteractiveMode=false

    Note, this is still a Java EE 6 archetype, at least for now.
  2. Open the project in NetBeans IDE as it makes it much easier to edit/add the files. Add the following <repositories>

    <repositories>
    <repository>
    <id>snapshot-repository.java.net</id>
    <name>Java.net Snapshot Repository for Maven</name>
    <url>https://maven.java.net/content/repositories/snapshots/</url>
    <layout>default</layout>
    </repository>
    </repositories>

  3. Add the following <dependency>s

    <dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.10</version>
    <scope>test</scope>
    </dependency>
    <dependency>
    <groupId>javax.ws.rs</groupId>
    <artifactId>javax.ws.rs-api</artifactId>
    <version>2.0-m09</version>
    <scope>test</scope>
    </dependency>
    <dependency>
    <groupId>org.glassfish.jersey.core</groupId>
    <artifactId>jersey-client</artifactId>
    <version>2.0-m05</version>
    <scope>test</scope>
    </dependency>
    The complete list of Maven coordinates for Jersey2 are available here. An up-to-date status of Jersey 2 can always be obtained from here.
  4. Here is a simple resource class:

    @Path("movies")
    public class MoviesResource {

    @GET
    @Path("list")
    public List<Movie> getMovies() {
    List<Movie> movies = new ArrayList<Movie>();

    movies.add(new Movie("Million Dollar Baby", "Hillary Swank"));
    movies.add(new Movie("Toy Story", "Buzz Light Year"));
    movies.add(new Movie("Hunger Games", "Jennifer Lawrence"));

    return movies;
    }
    }
    This resource publishes a list of movies and is accessible at "movies/list" path with HTTP GET. The project is using the standard JAX-RS APIs.

    Of course, you need the trivial "Movie" and the "Application" class as well. They are available in the downloadable project anyway.
  5. Build the project

    mvn package

    And deploy to GlassFish 4.0 promoted build 43 (download, unzip, and start as "bin/asadmin start-domain") as

    asadmin deploy --force=true target/jersey2-helloworld.war

  6. Add a simple test case by right-clicking on the MoviesResource class, select "Tools", "Create Tests", and take defaults. Replace the function "testGetMovies" to
    @Test
    public void testGetMovies() {
    System.out.println("getMovies");
    Client client = ClientFactory.newClient();
    List<Movie> movieList = client.target("http://localhost:8080/jersey2-helloworld/webresources/movies/list")
    .request()
    .get(new GenericType<List<Movie>>() {});
    assertEquals(3, movieList.size());
    }

    This test uses the newly defined JAX-RS 2 client APIs to access the RESTful resource.
  7. Run the test by giving the command "mvn test" and see the output as

    -------------------------------------------------------
    T E S T S
    -------------------------------------------------------
    Running example.MoviesResourceTest
    getMovies
    Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.561 sec

    Results :

    Tests run: 1, Failures: 0, Errors: 0, Skipped: 0

GlassFish 4 contains Jersey 2 as the JAX-RS implementation. If you want to use Jersey 1.1 functionality, then Martin's blog provide more details on that. All JAX-RS 1.x functionality will be supported using standard APIs anyway. This workaround is only required if Jersey 1.x functionality needs to be accessed.

The complete source code explained in this project can be downloaded from here.

Here are some pointers to follow

Provide feedback on Jersey 2 to users@jersey.java.net and JAX-RS specification to users@jax-rs-spec.java.net.

Friday May 11, 2012

wls-maven-plugin: WebLogic 12c Maven Plugin Usage (TOTD #177)


Oracle WebLogic Server 12c provides full Java EE 6 platform support. The screencast #39 shows how to build a complete application using NetBeans. The self-paced hands-on lab provides detailed instructions on the same as well. The Maven support in WebLogic 12c is much more improved. Steve Button and Markus Eisele wrote detailed blogs on how/what/why of Maven support in WebLogic. This Tip Of The Day (TOTD) will provide a quick overview of how to get started with using the maven plugin for deploying a Java EE 6 web application.

  1. Download and install WebLogic 12c using the zip installer as explained in TOTD #174.
  2. The Maven plugin can be installed using "$MW_HOME/wlserver/server/lib/wls-maven-plugin.jar". Change the directory to "$MW_HOME/wlserver/server/lib" and give the following commands:
    mvn install
    mvn install:install-file –Dfile=wls-maven-plugin.jar -DpomFile=pom.xml
  3. The maven plugin usage can be seen by giving the following command:
    mvn com.oracle.weblogic:wls-maven-plugin:help
    Or add the following to "~/.m2/settings.xml":
    <pluginGroups>     
    <pluginGroup>com.oracle.weblogic</pluginGroup>
    </pluginGroups>
    And then give the following command:
    mvn wls:help
    to see the output as:
    [INFO] Scanning for projects...
    [INFO]
    [INFO] ------------------------------------------------------------------------
    [INFO] Building wls-maven-sample 1.0-SNAPSHOT
    [INFO] ------------------------------------------------------------------------
    [INFO]
    [INFO] --- wls-maven-plugin:12.1.1.0:help (default-cli) @ wls-maven-sample ---
    [INFO]
    WebLogic Server Maven Plugin
    The following goals are supported by wls-maven-plugin:

    appc:
    The appc compiler generates and compiles the classes needed to deploy
    EJBs and JSPs to WebLogic Server. It also validates the deployment
    descriptors for compliance with the current specifications at both the
    individual module level and the application level.

    deploy:
    To deploy a weblogic server application (supports all formats WAR,JAR
    etc..)

    create-domain:
    Create a domain for WebLogic Server using the default domain template.
    For more complex domain creation use the WLST goal.

    help:
    Provides a list of all the goals supported by the wls-maven-plugin

    install:
    Install WebLogic Server

    list-apps:
    Lists the deployment names for applications and stand-alone modules
    deployed distributed, or installed to the domain

    redeploy:
    Redeploys a running application or part of a running application

    start-app:
    Starts an application deployed on weblogic server.

    start-server:
    Start WebLogic Server

    stop-app:
    Stops an application

    stop-server:
    Stop Weblogic Server

    undeploy:
    Undeploys the application from weblogic server. Stops the deployment unit
    and removes staged files from target servers

    update-app:
    Updates an application's deployment plan by redistributing the plan files
    and reconfiguring the application based on the new plan contents.

    wlst:
    WLST wrapper for Maven


    For detailed help on a goal, use -Dgoal=<goal-name> -Ddetail=true options.
    [INFO] ------------------------------------------------------------------------
    [INFO] BUILD SUCCESS
    [INFO] ------------------------------------------------------------------------
    [INFO] Total time: 0.794s
    [INFO] Finished at: Thu May 03 06:38:23 IST 2012
    [INFO] Final Memory: 8M/125M
    [INFO] ------------------------------------------------------------------------
    More details about each goal can be found using the following command:
    mvn wls:help -Dgoal=<GOAL> -Ddetail=true
    For example:
    mvn wls:help -Dgoal=install -Ddetail=true
    [INFO] Scanning for projects...
    [INFO]
    [INFO] ------------------------------------------------------------------------
    [INFO] Building Maven Stub Project (No POM) 1
    [INFO] ------------------------------------------------------------------------
    [INFO]
    [INFO] --- wls-maven-plugin:12.1.1.0:help (default-cli) @ standalone-pom ---
    [INFO]
    WebLogic Server Maven Plugin
    The following goals are supported by wls-maven-plugin:

    install:
    Install WebLogic Server

    Available Parameters:

    installCommand:
    The command to use to install the product when using an
    'executable' installer. The following macros are supported -
    @INSTALLER_FILE@ - the path to the installer file, @JAVA_HOME@ -
    path to the java home. eg: @JAVA_HOME@ -Xms512m -Xmx1024m -jar
    @INSTALLER_FILE@ one two

    artifactLocation:
    The address of the artifact. This can be one of the following -
    1) A ':' separated maven coordinates of the form (groupId:artifac-
    tId:packaging:classifier:version) 2) A file on the local system
    (/home/prash/myapps/helloworld.war)3) A remote http url
    (http://foo/a/b.zip)

    middlewareHome:
    The home directory for Oracle WebLogic Server or Fusion
    Middleware installation. Required unless WLS was installed in the
    default location selected by the WLS Maven Plugin's install goal.

    domainHome:
    Location of WLS domain

    localRepository:
    The absolute path of a local maven repository.

    artifactFactory:
    The artifactFactory is used to locate an artifact with a
    groupId:artifactId:artifactName:version in the remote Repository
    as provided by the remoteRepsitories parameter.

    artifactResolver:
    Artifactresolver resolves the artifact from the remote
    repository. Downloads an updated version of the artifact if
    present in the remote repo.



    [INFO] ------------------------------------------------------------------------
    [INFO] BUILD SUCCESS
    [INFO] ------------------------------------------------------------------------
    [INFO] Total time: 0.889s
    [INFO] Finished at: Wed May 02 17:35:46 PDT 2012
    [INFO] Final Memory: 6M/89M
    [INFO] ------------------------------------------------------------------------

  4. Build a Java EE 6 application
    1. Create a Java EE 6 Maven web application as:
      mvn archetype:generate
      -DarchetypeGroupId=org.codehaus.mojo.archetypes
      -DarchetypeArtifactId=webapp-javaee6 -DgroupId=example
      -DartifactId=wls-maven-sample -DarchetypeVersion=1.5
      -DinteractiveMode=false
    2. Add a trivial servlet to the sample project by following the screencast #39. The complete source code for the project can be downloaded here.
  5. Add the following code fragment to the generated "pom.xml":
    <plugin>                
    <groupId>com.oracle.weblogic</groupId>
    <artifactId>wls-maven-plugin</artifactId>
    <version>12.1.1.0</version>
    </plugin>
  6. Try some Maven commands in the "wls-maven-sample" directory
    1. The server can be started as:

      mvn wls:start-server
      -DmiddlewareHome=/Users/arungup/tools/weblogic/12c
      -DdomainHome=/Users/arungup/tools/weblogic/mydomain

      [INFO] Scanning for projects...
      [INFO]
      [INFO] ------------------------------------------------------------------------
      [INFO] Building wls-maven-sample 1.0-SNAPSHOT
      [INFO] ------------------------------------------------------------------------
      [INFO]
      [INFO] --- wls-maven-plugin:12.1.1.0:start-server (default-cli) @ wls-maven-sample ---
      [INFO] ++====================================================================++
      [INFO] ++ wls-maven-plugin: start-server ++
      [INFO] ++====================================================================++
      .[INFO] Starting server in domain: /Users/arungup/tools/weblogic/mydomain
      [INFO] Check stdout file for details: /Users/arungup/tools/weblogic/mydomain/server-922019421247284651.out
      [INFO] Process being executed, waiting for completion.
      ................
      [INFO] Server started successful
      [INFO] ------------------------------------------------------------------------
      [INFO] BUILD SUCCESS
      [INFO] ------------------------------------------------------------------------
      [INFO] Total time: 16.919s
      [INFO] Finished at: Wed May 02 18:06:22 PDT 2012
      [INFO] Final Memory: 5M/88M
      [INFO] ------------------------------------------------------------------------
    2. Build and deploy the application as:

      mvn wls:deploy
      -DmiddlewareHome=/Users/arungup/tools/weblogic/12c
      -DdomainHome=/Users/arungup/tools/weblogic/mydomain
      -Duser=admin
      -Dpassword=admin007
      -Dsource=/Users/arungup/code/samples/weblogic/wls-maven-sample/target/wls-maven-sample-1.0-SNAPSHOT.war

      [INFO] Scanning for projects...
      [INFO]
      [INFO] ------------------------------------------------------------------------
      [INFO] Building wls-maven-sample 1.0-SNAPSHOT
      [INFO] ------------------------------------------------------------------------
      [INFO]
      [INFO] --- wls-maven-plugin:12.1.1.0:deploy (default-cli) @ wls-maven-sample ---
      [INFO] ++====================================================================++
      [INFO] ++ wls-maven-plugin: deploy ++
      [INFO] ++====================================================================++
      weblogic.Deployer invoked with options: -noexit -user admin -deploy -source /Users/arungup/code/samples/weblogic/wls-maven-sample/target/wls-maven-sample-1.0-SNAPSHOT.war
      <May 3, 2012 8:24:17 AM IST> <Info> <J2EE Deployment SPI> <BEA-260121> <Initiating deploy operation for application, wls-maven-sample-1.0-SNAPSHOT [archive: /Users/arungup/code/samples/weblogic/wls-maven-sample/target/wls-maven-sample-1.0-SNAPSHOT.war], to configured targets.>
      Task 0 initiated: [Deployer:149026]deploy application wls-maven-sample-1.0-SNAPSHOT on myserver.
      Task 0 completed: [Deployer:149026]deploy application wls-maven-sample-1.0-SNAPSHOT on myserver.
      Target state: deploy completed on Server myserver

      [INFO] ------------------------------------------------------------------------
      [INFO] BUILD SUCCESS
      [INFO] ------------------------------------------------------------------------
      [INFO] Total time: 7.745s
      [INFO] Finished at: Thu May 03 08:24:18 IST 2012
      [INFO] Final Memory: 11M/130M
      [INFO] ------------------------------------------------------------------------
    3. The application is accessible at localhost:7001/wls-maven-sample-1.0-SNAPSHOT/TestServlet.
    4. Stop the server as:

      mvn wls:stop-server
      -DmiddlewareHome=/Users/arungup/tools/weblogic/12c
      -DdomainHome=/Users/arungup/tools/weblogic/mydomain
      -Duser=admin
      -Dpassword=admin007

      [INFO] Scanning for projects...
      [INFO]
      [INFO] ------------------------------------------------------------------------
      [INFO] Building wls-maven-sample 1.0-SNAPSHOT
      [INFO] ------------------------------------------------------------------------
      [INFO]
      [INFO] --- wls-maven-plugin:12.1.1.0:stop-server (default-cli) @ wls-maven-sample ---
      [INFO] ++====================================================================++
      [INFO] ++ wls-maven-plugin: stop-server ++
      [INFO] ++====================================================================++
      [INFO] Stop server in domain: /Users/arungup/tools/weblogic/mydomain
      [INFO] Process being executed, waiting for completion.
      [INFO] [exec] Stopping Weblogic Server...
      [INFO] [exec]
      [INFO] [exec] Initializing WebLogic Scripting Tool (WLST) ...
      [INFO] [exec]
      [INFO] [exec] Welcome to WebLogic Server Administration Scripting Shell
      [INFO] [exec]
      [INFO] [exec] Type help() for help on available commands
      [INFO] [exec]
      [INFO] [exec] Connecting to t3://localhost:7001 with userid admin ...
      [INFO] [exec] Successfully connected to Admin Server 'myserver' that belongs to domain 'mydomain'.
      [INFO] [exec]
      [INFO] [exec] Warning: An insecure protocol was used to connect to the
      [INFO] [exec] server. To ensure on-the-wire security, the SSL port or
      [INFO] [exec] Admin port should be used instead.
      [INFO] [exec]
      [INFO] [exec] Shutting down the server myserver with force=false while connected to myserver ...
      [INFO] [exec] WLST lost connection to the WebLogic Server that you were
      [INFO] [exec] connected to, this may happen if the server was shutdown or
      [INFO] [exec] partitioned. You will have to re-connect to the server once the
      [INFO] [exec] server is available.
      [INFO] [exec] Disconnected from weblogic server: myserver
      [INFO] [exec] Disconnected from weblogic server:
      [INFO] [exec]
      [INFO] [exec]
      [INFO] [exec] Exiting WebLogic Scripting Tool.
      [INFO] [exec]
      [INFO] [exec] Done
      [INFO] [exec] Stopping Derby Server...
      [INFO] ------------------------------------------------------------------------
      [INFO] BUILD SUCCESS
      [INFO] ------------------------------------------------------------------------
      [INFO] Total time: 10.847s
      [INFO] Finished at: Thu May 03 06:37:48 IST 2012
      [INFO] Final Memory: 9M/125M
      [INFO] ------------------------------------------------------------------------

Simple, quick, and easy!

Are you building Java EE 6 applications on WebLogic ? With Maven ? Now you can fully integrate the WebLogic lifecycle with your "pom.xml".

The WebLogic Application Development Guide provide detailed documentation on the maven plugin.


Sunday Sep 18, 2011

How to checkout and build GlassFish trunk ? (TOTD #171)

The complete instructions to check out and build GlassFish trunk are explained here. But if you want just quick instructions then follow the steps below:

svn checkout https://svn.java.net/svn/glassfish~svn/trunk/main glassfish
cd glassfish
mvn

Make sure you are using JDK 1.6 U4+ (not JDK 7 yet) and Maven 2.2.1 (not 3.0 yet).

UPDATE: Builds fine with JDK 7 and Maven 3.0.3 after this commit. Follow GLASSFISH-17285 for more on building with JDK 7.

The default target builds the entire workspace and runs the tests. You can skip the tests by additionally specifying

-Dmaven.test.skip=true
on the CLI.

A CI build of GlassFish trunk is always available at hudson.glassfish.org.

A fresh check of the workspace took about 19 minutes on my laptop and a build took about: 14 minutes. The final successful message was:

-------------------------------------------
BUILD SUCCESSFUL
-------------------------------------------
Total time: 14 minutes 23 seconds
Finished at: Fri Sep 16 13:54:49 PDT 2011
Final Memory: 189M/459M
-------------------------------------------

How often do you build GlassFish ?

How much time does it take on your laptop ?

Friday Sep 09, 2011

Scala and Maven - Getting Started Guide using maven-scala-plugin (TOTD #170)

Here is a quick Tip Of The Day (TOTD) that shows a "pom.xml" to get you started with building and running your Scala applications using Maven.

  1. Generate the Maven project
    D:\code\samples>mvn archetype:generate \
          -DarchetypeGroupId=org.scala-tools.archetypes \
          -DarchetypeArtifactId=scala-archetype-simple  \
          -DremoteRepositories=http://scala-tools.org/repo-releases \
          -DgroupId=org.glassfish.samples \
          -DartifactId=scala-helloworld \
          -Dversion=1.0-SNAPSHOT
    [INFO] Scanning for projects...
    [INFO]
    [INFO] ------------------------------------------------------------------------
    [INFO] Building Maven Stub Project (No POM) 1
    [INFO] ------------------------------------------------------------------------
    [INFO]
    [INFO] >>> maven-archetype-plugin:2.0:generate (default-cli) @ standalone-pom >>>
    [INFO]
    [INFO] <<< maven-archetype-plugin:2.0:generate (default-cli) @ standalone-pom <<<
    [INFO]
    [INFO] --- maven-archetype-plugin:2.0:generate (default-cli) @ standalone-pom ---
    [INFO] Generating project in Interactive mode
    [INFO] Archetype [org.scala-tools.archetypes:scala-archetype-simple:1.3] found in catalog remote
    [INFO] Using property: groupId = org.glassfish.samples
    [INFO] Using property: artifactId = scala-helloworld
    [INFO] Using property: version = 1.0-SNAPSHOT
    [INFO] Using property: package = org.glassfish.samples
    Confirm properties configuration:
    groupId: org.glassfish.samples
    artifactId: scala-helloworld
    version: 1.0-SNAPSHOT
    package: org.glassfish.samples
    Y: : Y
    [INFO] ------------------------------------------------------------------------
    [INFO] BUILD SUCCESS
    [INFO] ------------------------------------------------------------------------
    [INFO] Total time: 6.452s
    [INFO] Finished at: Fri Sep 09 09:59:53 PDT 2011
    [INFO] Final Memory: 12M/153M
    [INFO] ------------------------------------------------------------------------
    
    
    This command gets into an interactive mode confirming the entered details. After confirming, the generated directory structure looks like:

    .
    ./.gitignore
    ./pom.xml
    ./src
    ./src/main
    ./src/main/scala
    ./src/main/scala/org
    ./src/main/scala/org/glassfish
    ./src/main/scala/org/glassfish/samples
    ./src/main/scala/org/glassfish/samples/App.scala
    ./src/test
    ./src/test/scala
    ./src/test/scala/samples
    ./src/test/scala/samples/junit.scala
    ./src/test/scala/samples/scalatest.scala
    ./src/test/scala/samples/specs.scala
    And the generated "pom.xml" looks like:
    
    <project xmlns="http://maven.apache.org/POM/4.0.0" 
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
      xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
      <modelVersion>4.0.0</modelVersion>
      <groupId>org.glassfish.samples</groupId>
      <artifactId>scala-helloworld</artifactId>
      <version>1.0-SNAPSHOT</version>
      <name>${project.artifactId}</name>
      <description>My wonderfull scala app</description>
      <inceptionYear>2010</inceptionYear>
      <licenses>
        <license>
          <name>My License</name>
          <url>http://....</url>
          <distribution>repo</distribution>
        </license>
      </licenses>
    
      <properties>
        <maven.compiler.source>1.5</maven.compiler.source>
        <maven.compiler.target>1.5</maven.compiler.target>
        <encoding>UTF-8</encoding>
        <scala.version>2.8.0</scala.version>
      </properties>
    
      <!--
      <repositories>
        <repository>
          <id>scala-tools.org</id>
          <name>Scala-Tools Maven2 Repository</name>
          <url>http://scala-tools.org/repo-releases</url>
        </repository>
      </repositories>
    
      <pluginRepositories>
        <pluginRepository>
          <id>scala-tools.org</id>
          <name>Scala-Tools Maven2 Repository</name>
          <url>http://scala-tools.org/repo-releases</url>
        </pluginRepository>
      </pluginRepositories>
      -->
      <dependencies>
        <dependency>
          <groupId>org.scala-lang</groupId>
          <artifactId>scala-library</artifactId>
          <version>${scala.version}</version>
        </dependency>
    
        <!-- Test -->
        <dependency>
          <groupId>junit</groupId>
          <artifactId>junit</artifactId>
          <version>4.8.1</version>
          <scope>test</scope>
        </dependency>
        <dependency>
          <groupId>org.scala-tools.testing</groupId>
          <artifactId>specs_${scala.version}</artifactId>
          <version>1.6.5</version>
          <scope>test</scope>
        </dependency>
        <dependency>
          <groupId>org.scalatest</groupId>
          <artifactId>scalatest</artifactId>
          <version>1.2</version>
          <scope>test</scope>
        </dependency>
      </dependencies>
    
      <build>
        <sourceDirectory>src/main/scala</sourceDirectory>
        <testSourceDirectory>src/test/scala</testSourceDirectory>
        <plugins>
          <plugin>
            <groupId>org.scala-tools</groupId>
            <artifactId>maven-scala-plugin</artifactId>
            <version>2.15.0</version>
            <executions>
              <execution>
                <goals>
                  <goal>compile</goal>
                  <goal>testCompile</goal>
                </goals>
                <configuration>
                  <args>
                    <arg>-make:transitive</arg>
                    <arg>-dependencyfile</arg>
                    <arg>${project.build.directory}/.scala_dependencies</arg>
                  </args>
                </configuration>
              </execution>
            </executions>
          </plugin>
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <version>2.6</version>
            <configuration>
              <useFile>false</useFile>
              <disableXmlReport>true</disableXmlReport>
              <!-- If you have classpath issue like NoDefClassError,... -->
              <!-- useManifestOnlyJar>false</useManifestOnlyJar -->
              <includes>
                <include>**/*Test.*</include>
                <include>**/*Suite.*</include>
              </includes>
            </configuration>
          </plugin>
        </plugins>
      </build>
    </project>
    
  2. Edit the "pom.xml" to specify a script to be launched. Add the following code fragment after </executions> for "maven-scala-plugin":
    <configuration>
      <launchers>
        <launcher>
          <id>sample</id>
          <mainClass>org.glassfish.samples.App</mainClass>
          <args>
            <arg>${basedir}</arg>
          </args>
        </launcher>
      </launchers>
    </configuration>
    
  3. Build and run the project as:

    D:\code\samples\scala-helloworld>mvn scala:run
    [INFO] Scanning for projects...
    [INFO]
    [INFO] ------------------------------------------------------------------------
    [INFO] Building scala-helloworld 1.0-SNAPSHOT
    [INFO] ------------------------------------------------------------------------
    [INFO]
    [INFO] >>> maven-scala-plugin:2.15.0:run (default-cli) @ scala-helloworld >>>
    [INFO]
    [INFO] --- maven-resources-plugin:2.4.3:resources (default-resources) @ scala-helloworld ---
    [INFO] Using 'UTF-8' encoding to copy filtered resources.
    [INFO] skip non existing resourceDirectory D:\code\samples\scala-helloworld\src\main\resources
    [INFO]
    [INFO] --- maven-compiler-plugin:2.3.2:compile (default-compile) @ scala-helloworld ---
    [INFO] Nothing to compile - all classes are up to date
    [INFO]
    [INFO] --- maven-scala-plugin:2.15.0:compile (default) @ scala-helloworld ---
    [INFO] Checking for multiple versions of scala
    [INFO] includes = [**/*.scala,**/*.java,]
    [INFO] excludes = []
    [INFO] D:\code\samples\scala-helloworld\src\main\scala:-1: info: compiling
    [INFO] Compiling 1 source files to D:\code\samples\scala-helloworld\target\classes at 1315588676077
    [INFO] No known dependencies. Compiling everything
    [INFO] prepare-compile in 0 s
    [INFO] compile in 5 s
    [INFO]
    [INFO] --- maven-resources-plugin:2.4.3:testResources (default-testResources) @ scala-helloworld ---
    
    [INFO] Using 'UTF-8' encoding to copy filtered resources.
    [INFO] skip non existing resourceDirectory D:\code\samples\scala-helloworld\src\test\resources
    [INFO]
    [INFO] --- maven-compiler-plugin:2.3.2:testCompile (default-testCompile) @ scala-helloworld ---
    [INFO] Nothing to compile - all classes are up to date
    [INFO]
    [INFO] --- maven-scala-plugin:2.15.0:testCompile (default) @ scala-helloworld ---
    [INFO] Checking for multiple versions of scala
    [INFO] includes = [**/*.scala,**/*.java,]
    [INFO] excludes = []
    [INFO] D:\code\samples\scala-helloworld\src\test\scala:-1: info: compiling
    [INFO] Compiling 3 source files to D:\code\samples\scala-helloworld\target\test-classes at 131558868
    1986
    [INFO] No known dependencies. Compiling everything
    [INFO] prepare-compile in 0 s
    [INFO] compile in 10 s
    [INFO]
    [INFO] <<< maven-scala-plugin:2.15.0:run (default-cli) @ scala-helloworld <<<
    [INFO]
    [INFO] --- maven-scala-plugin:2.15.0:run (default-cli) @ scala-helloworld ---
    [INFO] Checking for multiple versions of scala
    [INFO] launcher 'sample' selected => org.glassfish.samples.App
    Hello World!
    concat arguments = D:\code\samples\scala-helloworld
    [INFO] ------------------------------------------------------------------------
    [INFO] BUILD SUCCESS
    [INFO] ------------------------------------------------------------------------
    [INFO] Total time: 18.970s
    [INFO] Finished at: Fri Sep 09 10:18:13 PDT 2011
    [INFO] Final Memory: 10M/153M
    [INFO] ------------------------------------------------------------------------

    Look for the output "Hello World!" towards the bottom.

Fire away to add more classes and build your application. A subsequent blog will show how to perform database connectivity from a Scala application.

The generated project can be downloaded from totd170-scala-helloworld.zip.

More details at:

Sunday Mar 14, 2010

TOTD #124: OSGi Declarative Services in GlassFish - Accessed from a Java EE client

The OSGi R4 compendium specification enables declaration of "Declarative Services" in configuration files. The specification says:

The service component model uses a declarative model for publishing, finding and binding to OSGi services. This model simplifies the task of authoring OSGi services by performing the work of registering the service and handling service dependencies.

There are several advantages of OSGi declarative services and they are well defined in the specification.

Neil Bartlett provided history and introduction to Declarative Services. Jerome blogged about OSGi Declarative Services in GlassFish v3 a while back. As mentioned in his post, this "curious reader" decided to experiment with adding more than one service implementation.

This Tip Of The Day shows how to use Maven Bundle Plugin and Maven SCR Plugin to create an OSGi bundle with two declarative services. Then it shows how to create a Java EE client, inject the declared services, and invoke them.

Lets get started!

For those who want want to see the results first:

  • Download service project and build as "mvn clean install". Install the service as "cp target/helloservice-1.0-SNAPSHOT.jar" to "domains/domain1/autodeploy/bundles".
  • Download client project and build as "mvn clean package"
  • Deploy the client to GlassFish v3 as "asadmin deploy target/helloclient-1.0-SNAPSHOT.war"
  • Invoke the client as "curl http://localhost:8080/helloclient-1.0-SNAPSHOT/HelloClient"

Now lets try to understand and create the projects from scratch.

First, create the service project as:

mvn archetype:create -DarchetypeGroupId=org.apache.maven.archetypes 
     -DgroupId=org.glassfish.samples.osgi.helloservice -DartifactId=helloservice

Lets first look at the completed project structure:

pom.xml
src
src/main
src/main/java
src/main/java/org
src/main/java/org/glassfish
src/main/java/org/glassfish/samples
src/main/java/org/glassfish/samples/osgi
src/main/java/org/glassfish/samples/osgi/helloservice
src/main/java/org/glassfish/samples/osgi/helloservice/api
src/main/java/org/glassfish/samples/osgi/helloservice/api/HelloService.java
src/main/java/org/glassfish/samples/osgi/helloservice/impl
src/main/java/org/glassfish/samples/osgi/helloservice/impl/HelloImpl.java
src/main/java/org/glassfish/samples/osgi/helloservice/impl/HowdyImpl.java

The three source files are one service API and two implementations.

HelloService.java

package org.glassfish.samples.osgi.helloservice.api;

/\*\*
 \* @author arungupta
 \*/
public interface HelloService {
  public String sayHello(String name);
}

A very simple interface with one method that takes a String parameter and returns a String response.

HelloImpl.java

package org.glassfish.samples.osgi.helloservice.impl;

import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Service;
import org.glassfish.samples.osgi.helloservice.api.HelloService;

/\*\*
 \* @author arungupta
 \*/
@Component(name="hello-service")
@Service
public class HelloImpl implements HelloService {

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

This class is an implementation of the service interface. Notice this class is in "impl" package, different from the "api" package where interface was defined.

The business method implementation appends the greeting "Hello " to name parameter and generates the response message. The @Component and @Service annotations help in generation of the component descriptors as defined by the Maven SCR Plugin. This plugin provides many other annotations to customize the generation of metadata in "OSGI-INF/servicesComponent.xml". The "name" attribute will be used later by the Java EE client to access this service.

HowdyImpl.java

package org.glassfish.samples.osgi.helloservice.impl;

import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Service;
import org.glassfish.samples.osgi.helloservice.api.HelloService;

/\*\*
 \* @author arungupta
 \*/
@Component(name="howdy-service")
@Service
public class HowdyImpl implements HelloService {

  public String sayHello(String name) {
    return "Howdy " + name;
  }
}

Another implementation of HelloService interface and uses "Howdy " for the greeting. Notice the name attribute has a different value.

Here is the complete pom.xml:

<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
                             http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>org.glassfish.samples.osgi.helloservice</groupId>
  <artifactId>helloservice</artifactId>
  <packaging>bundle</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>helloservice</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.apache.felix</groupId>
      <artifactId>org.apache.felix.scr.annotations</artifactId>
      <version>1.2.0</version>
      <scope>provided</scope>
    </dependency>
  </dependencies>
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <configuration>
          <source>1.5</source>
          <target>1.5</target>
        </configuration>
      </plugin>
      <plugin>
        <groupId>org.apache.felix</groupId>
        <artifactId>maven-bundle-plugin</artifactId>
        <version>2.0.1</version>
        <extensions>true</extensions>
        <configuration>
          <instructions>
            <Export-Package>${pom.groupId}.api</Export-Package>
            <Bundle-SymbolicName>${pom.artifactId}</Bundle-SymbolicName>
          </instructions>
        </configuration>
      </plugin>
    <plugin>
      <groupId>org.apache.felix</groupId>
      <artifactId>maven-scr-plugin</artifactId>
      <executions>
        <execution>
          <id>generate-scr-scrdescriptor</id>
          <goals>
            <goal>scr</goal>
          </goals>
        </execution>
      </executions>
    </plugin>
  </plugins>
 </build>
</project>

Maven SCR Plugin generates the descriptor file using the metadata specified by the @Component and @Service annotation in service implementations. If this plugin is used with Maven Bundle Plugin then it also adds the generated descriptor (OSGI-INF/serviceComponents.xml) to the bundle and set the required "Service-Component" manifest header.

Giving "mvn clean install" generates "target/helloservice-1.0-SNAPSHOT.jar" and installs the bundle in the local repository. This JAR is used later in the client project for importing the service API definition. The generated JAR has the following manifest:

Manifest-Version: 1.0
Export-Package: org.glassfish.samples.osgi.helloservice.api
Service-Component: OSGI-INF/serviceComponents.xml
Built-By: arungupta
Tool: Bnd-0.0.357
Bundle-Name: helloservice
Created-By: Apache Maven Bundle Plugin
Build-Jdk: 1.6.0_17
Bundle-Version: 1.0.0.SNAPSHOT
Bnd-LastModified: 1268374529666
Bundle-ManifestVersion: 2
Import-Package: org.glassfish.samples.osgi.helloservice.api
Bundle-SymbolicName: helloservice

The key thing to notice is that only "api" package is exported. The generated component descriptor in "OSGI-INF/serviceComponents.xml" looks like:

<?xml version="1.0" encoding="UTF-8"?>
<components xmlns:scr="http://www.osgi.org/xmlns/scr/v1.0.0">
  <scr:component enabled="true" name="hello-service">
    <implementation class="org.glassfish.samples.osgi.helloservice.impl.HelloImpl"/>
    <service servicefactory="false">
      <provide interface="org.glassfish.samples.osgi.helloservice.api.HelloService"/>
    </service>
    <property name="service.pid" value="hello-service"/>
  </scr:component>
  <scr:component enabled="true" name="howdy-service">
    <implementation class="org.glassfish.samples.osgi.helloservice.impl.HowdyImpl"/>
    <service servicefactory="false">
     <provide interface="org.glassfish.samples.osgi.helloservice.api.HelloService"/>
    </service>
    <property name="service.pid" value="howdy-service"/>
  </scr:component>
</components>

Notice that the "Service-Component" manifest header is pointing to this generated descriptor. And so the two declared services "hello-service" and "howdy-service" are available for consumption by other clients.

There are several ways to manage OSGi runtime bundle in GlassFish as described in TOTD #118. Simply copying the bundle to "glassfish/domains/domain1/autodeploy/bundles" is sufficient in this case, so lets do that.

The remote telnet shell (accessible using "telnet localhst 6666") shows status of the deployed bundle and associated service as:

-> find hello
START LEVEL 1
 ID State Level Name
[ 221] [Active ] [ 1] helloservice (1.0.0.SNAPSHOT)
-> scr list 221
 Id State Name
[ 2] [active ] hello-service
[ 3] [active ] howdy-service
-> scr info 2
ID: 2
Name: hello-service
Bundle: helloservice (221)
State: active
Default State: enabled
Activation: delayed
Services: org.glassfish.samples.osgi.helloservice.api.HelloService
Service Type: service
Properties:
 component.id = 2
 component.name = hello-service
 service.pid = hello-service
-> scr info 3
ID: 3
Name: howdy-service
Bundle: helloservice (221)
State: active
Default State: enabled
Activation: delayed
Services: org.glassfish.samples.osgi.helloservice.api.HelloService
Service Type: service
Properties:
 component.id = 3
 component.name = howdy-service
 service.pid = howdy-service

Maven SCR Plugin provides several other annotations to change the default value for each service.

Now create a Java EE client project to invoke the service as:

mvn archetype:create -DarchetypeGroupId=org.apache.maven.archetypes 
       -DgroupId=org.glassfish.samples.osgi -DartifactId=helloclient

Lets look at the completed project structure:

pom.xml
src
src/main
src/main/java
src/main/java/org
src/main/java/org/glassfish
src/main/java/org/glassfish/samples
src/main/java/org/glassfish/samples/osgi
src/main/java/org/glassfish/samples/osgi/HelloClient.java

There is only one source file which is the Servlet client and looks like:

package org.glassfish.samples.osgi;

import java.io.IOException;
import java.io.PrintWriter;
import javax.annotation.Resource;
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.samples.osgi.helloservice.api.HelloService;

/\*\*
 \* Hello world!
 \*/
@WebServlet(urlPatterns={"/HelloClient"})
public class HelloClient extends HttpServlet {

  @Resource(mappedName="hello-service")
  HelloService helloService;

  @Resource(mappedName="howdy-service")
  HelloService howdyService;

  @Override
  public void doGet(HttpServletRequest request, HttpServletResponse response)
    throws IOException, ServletException {
    PrintWriter out = response.getWriter();
    out.println(helloService.sayHello("Duke"));
    out.println(howdyService.sayHello("Duke"));
  }
}

This is a Java EE 6-style Servlet, using @WebServlet annotation, and will be accessible at "/HelloClient". The two OSGi services are injected using @Resource annotation and using the name specified in the "OSGI-INF/serviceComponents.xml" descriptor earlier.

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
         http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>org.glassfish.samples.osgi</groupId>
  <artifactId>helloclient</artifactId>
  <packaging>war</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>helloclient</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.glassfish.samples.osgi.helloservice</groupId>
      <artifactId>helloservice</artifactId>
      <version>1.0-SNAPSHOT</version>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>javax</groupId>
      <artifactId>javaee-api</artifactId>
      <version>6.0</version>
      <scope>provided</scope>
    </dependency>
  </dependencies>
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <configuration>
          <source>1.5</source>
          <target>1.5</target>
        </configuration>
      </plugin>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-war-plugin</artifactId>
        <version>2.1-beta-1</version>
        <configuration>
          <failOnMissingWebXml>false</failOnMissingWebXml>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>

Note that the previously generated service bundle is added as a dependency in the "provided" scope as its already deployed to GlassFish.

"mvn clean package" generates "target/helloclient-1.0-SNAPSHOT.war" Deploy this WAR file to GlassFish as:

asadmin deploy target/helloclient-1.0-SNAPSHOT.war

And finally invoke the client as:

curl http://localhost:8080/helloclient-1.0-SNAPSHOT/HelloClient

to see the output as:

Hello Duke
Howdy Duke

This is the expected output after invoking the two services.

So there you go, this blog demonstrated how to access a OSGi declarative service from a Java EE client - both deployed on GlassFish v3.

Are you using OSGi Declarative Services ? How ?

Technorati: totd osgi glassfish javaee declarative service maven bundle bnd scr component dependencyinjection

Friday Feb 05, 2010

TOTD #120: Deployment Descriptor-free Java EE 6 application using JSF 2.0 + EJB 3.1 + Servlets 3.0

Here is trivial Java EE 6 application that is keeping you away from any deployment descriptors. It uses Java Server Faces 2.0, Enterprise Java Beans 3.1, and Servlet 3.0. This application shows the following Java EE 6 features:

  1. No-interface view for EJB
  2. EJBs packaged in a WAR file
  3. Optional "faces-config.xml" for Java Server Faces
  4. FacesServlet registered using Servlet 3.0 programmatic registration APIs
  5. Java Server Faces navigation rules using convention-over-configuration
  6. Optional "web.xml" for Servlets 3.0

The WAR file structure is:

./index.jsp
./index.xhtml
./META-INF
./show.xhtml
./WEB-INF
./WEB-INF/classes
./WEB-INF/classes/org
./WEB-INF/classes/org/glassfish
./WEB-INF/classes/org/glassfish/samples
./WEB-INF/classes/org/glassfish/samples/SimpleBean.class
./WEB-INF/classes/org/glassfish/samples/SimpleEJB.class
./WEB-INF/classes/org/glassfish/samples/SimpleServlet.class

Look ma, no deployment descriptors!

So how do you create this application:

mvn archetype:create -DarchetypeGroupId=org.apache.maven.archetypes -DgroupId=org.glassfish.samples -DartifactId=simplewebapp

This application is purposely not generated as a web application (missing "-DarchetypeArtifactId=maven-archetype-webapp"). If you specify this property then it will generate "WEB-INF/web.xml" which we don't intend to use.

Change "pom.xml" to:

<project xmlns="http://maven.apache.org/POM/4.0.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
   <modelVersion>4.0.0</modelVersion>
   <groupId>org.glassfish.samples</groupId>
   <artifactId>simplewebapp</artifactId>
   <packaging>war</packaging>
   <version>1.0-SNAPSHOT</version>
   <name>simplewebapp</name>
   <url>http://maven.apache.org</url>
   <repositories>
     <repository>
       <id>glassfish-repository</id>
       <name>Java.net Repository for Glassfish</name>
       <url>http://download.java.net/maven/glassfish</url>
     </repository>
   </repositories>
   <build>
     <plugins>
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-compiler-plugin</artifactId>
         <version>2.0.2</version>
         <configuration>
           <source>1.5</source>
           <target>1.5</target>
         </configuration>
       </plugin>
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-war-plugin</artifactId>
         <version>2.1-beta-1</version>
         <configuration>
           <failOnMissingWebXml>false</failOnMissingWebXml>
         </configuration>
       </plugin>
     </plugins>
   </build>
   <dependencies>
     <dependency>
       <groupId>junit</groupId>
       <artifactId>junit</artifactId>
       <version>3.8.1</version>
       <scope>test</scope>
     </dependency>
    <dependency>
       <groupId>javax</groupId>
       <artifactId>javaee-api</artifactId>
       <version>6.0</version>
       <scope>provided</scope>
    </dependency>
   </dependencies>
</project>

In the above code:
  • "maven-compiler-plugin" needs to be specified as the default source level for Maven compile plugin is JDK 1.3. It's been over 9 years JDK 1.3 was released, not even listed on Java SE standard downloads page, EOLed many years ago. Vote/Comment for the issue MCOMPILER-80 if you'd like this bug to be fixed.
  • Adding "failOnMissingWebXml" ensures that Maven packages the WAR file even though no "web.xml" is present.
  • The complete list of Maven coordinates for GlassFish are available here.

Create the directory structure as:

./src/main
./src/main/java
./src/main/java/org
./src/main/java/org/glassfish
./src/main/java/org/glassfish/samples
./src/main/java/org/glassfish/samples/SimpleBean.java
./src/main/java/org/glassfish/samples/SimpleEJB.java
./src/main/java/org/glassfish/samples/SimpleServlet.java
./src/main/webapp
./src/main/webapp/index.jsp
./src/main/webapp/index.xhtml
./src/main/webapp/show.xhtml

Once again, there are no deployment descriptors, just plain Java files and XHTML/JSP pages.

Here are the different source files with explanation after each one of them:

SimpleBean.java
package org.glassfish.samples;

import javax.faces.bean.ManagedBean;

@ManagedBean(name="simplebean")
public class SimpleBean {
    private String name;
    private int age;

    public String getName() { return name; }
    public void setName(String name) { this.name = name; }

    public int getAge() { return age; }
    public void setAge(int age) { this.age = age; }
}

This is currently a simple JSF managed bean. TOTD #109 explains how to convert a JSF managed bean to use CDI. A future blog will show how to convert this sample to use CDI.

SimpleEJB.java

package org.glassfish.samples;

import javax.ejb.Stateless;

@Stateless
public class SimpleEJB {
    public String sayHello(String name) {
        return "Hello " + name + "!!!";
    }
}

The session bean has no interface, just the @Stateless annotation.

SimpleServlet.java

package org.glassfish.samples;

import javax.ejb.EJB;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.annotation.WebServlet;
import java.io.PrintWriter;
import java.io.IOException;

/\*\*
 \* Hello world!
 \*/
@WebServlet(urlPatterns={"/SimpleServlet"})
public class SimpleServlet extends HttpServlet {
    @EJB SimpleEJB bean;

    @Override
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
        PrintWriter out = response.getWriter();
        out.println("<html><body>");
        out.println("<h2>Serving at: " + request.getContextPath() + "</h2>");
        out.println("<h2>Invoking EJB: " + bean.sayHello("Duke") + "</h2>");
        out.println("</body></html>");
    }
}

The servlet injects the EJB in the application, display the servlet context and the result of invoking the business operation of the EJB.


index.jsp

<html>
<body>
<h2>Hello World!</h2>
Invoke the Servlet by clicking <a href="SimpleServlet">here</a>.
</body>
</html>

This is just a placeholder for invoking the servlet.

index.xhtml

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtm
l1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
 xmlns:ui="http://java.sun.com/jsf/facelets"
 xmlns:h="http://java.sun.com/jsf/html">
 <h:head>
 <title>Enter Name &amp; Age</title>
 </h:head>
 <h:body>
 <h1>Enter Name &amp; Age</h1>
<h:form>
 <h:panelGrid columns="2">
 <h:outputText value="Name:"/>
 <h:inputText value="#{simplebean.name}" title="name" id="name" required="true"/>
 <h:outputText value="Age:"/>
 <h:inputText value="#{simplebean.age}" title="age" id="age" required="true"/>
 </h:panelGrid>
 <h:commandButton action="show" value="submit"/>
 </h:form>
 </h:body>
</html>


JSF 2 uses Facelets as viewing technology and so an ".xhtml" file is used for all the JSF tags. This page is intentionally kept simple and not using any templating, composition, or any other features of Facelets. This page renders an HTML form with two text boxes and a command button, binds the value of text box to the managed bean, and displays the page "show.xhtml" when the command button is clicked. The default JSF 2 navigation handler try to match a view on the disk ("show.xhtml" in this case) based upon the "action" attribute.

show.xhtml

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtm
l1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
 xmlns:h="http://java.sun.com/jsf/html">
 <h:head>
 <title>Show Name &amp; Age</title>
 </h:head>
 <h:body>
 <h1>Show Name &amp; Age</h1>
<h:form action="show">
 <h:panelGrid columns="2">
 <h:outputText value="Name:"/>
 <h:outputText value="#{simplebean.name}" />
 <h:outputText value="Age:"/>
 <h:outputText value="#{simplebean.age}" />
 </h:panelGrid>
 </h:form>
 </h:body>
</html>

This page reads the bean properties (stored from previous page) and displays them on the page.

How do you build this entire application ?

mvn clean package

Lets deploy the application on a Java EE 6 compliant application server, GlassFish v3 (download here):

./bin/asadmin deploy --force=true ~/samples/javaee6/simplewebapp/target/simplewebapp-1.0-SNAPSHOT.war

And now your application is accessible at "http://localhost:8080/simplewebapp-1.0-SNAPSHOT/index.jsp" and looks like:

Clicking on "here" looks like:

The JSF page is accessible at "http://localhost:8080/simplewebapp-1.0-SNAPSHOT/index.jsf" and looks like (after entering the values):

Notice that even though the page is named "index.xhtml", it's accessed as "index.jsf". This is because the JSF specification provides recommended mapping for FacesServlet to "\*.faces" and "/faces/\*". In addition, Mojarra (Reference Implementation of JSF2 in GlassFish) also adds a mapping to "\*.jsf". Any views using these URL pattersn are routed through FacesServlet. So alternative URLs for our page are "http://localhost:8080/simplewebapp-1.0-SNAPSHOT/index.faces" and "http://localhost:8080/simplewebapp-1.0-SNAPSHOT/faces/index.xhtml".

Clicking on "Submit" shows the following page:



That's it!

Here are several other useful entries:

  • TOTD #109 : How to convert a JSF managed bean to JSR 299 bean (Web Beans) ?
  • TOTD #108 : Java EE 6 web application (JSF 2.0 + JPA 2.0 + EJB 3.1) using Oracle, NetBeans, and GlassFish
  • TOTD #102 : Java EE 6 (Servlet 3.0 and EJB 3.1) wizards in Eclipse
  • TOTD #99 : Creating a Java EE 6 application using MySQL, JPA 2.0 and Servlet 3.0 with GlassFish Tools Bundle for Eclipse
  • TOTD #98 : Create a Metro JAX-WS Web service using GlassFish Tools Bundle for Eclipse
  • TOTD #95 : EJB 3.1 + Java Server Faces 2.0 + JPA 2.0 web application - Getting Started with Java EE 6 using NetBeans 6.8 M1 & GlassFish v3
  • TOTD #94 : A simple Java Server Faces 2.0 + JPA 2.0 application - Getting Started with Java EE 6 using NetBeans 6.8 M1 & GlassFish v3
  • TOTD #93 : Getting Started with Java EE 6 using NetBeans 6.8 M1 & GlassFish v3 - A simple Servlet 3.0 + JPA 2.0 app

The next follow up blog will show "Hello World"s of Context & Dependency Injection, Bean Validation, Java API for Restful Web services, Java Persistence API, Interceptors, and other Java EE 6 specifications in this application.

Technorati: totd javaee glassfish v3 javaserverfaces servlet3 ejb maven

Wednesday Jan 20, 2010

TOTD #118: Managing OSGi bundles in GlassFish v3 - asadmin, filesystem, telnet console, web browser, REST, osgish

GlassFish v3 and OSGi integration is now known for almost two years. Several blogs have been published on this topic and googling on "glassfish osgi" shows 817,000 results. This blog has published four entries on the topic so far.

This Tip Of The Day (TOTD) will show the different ways you can manage OSGi bundles in GlassFish v3.

The first part is to create a trivial OSGi bundle as explained in TOTD #36.

  1. Create a simple Maven project using the command as shown below:
    ~/samples/v3/osgi >mvn archetype:create -DarchetypeGroupId=org.apache.maven.archetypes -DgroupId=org.glassfish.samples.osgi.helloworld -DartifactId=helloworld
    [INFO] Scanning for projects...
    [INFO] Searching repository for plugin with prefix: 'archetype'.
    [INFO] ------------------------------------------------------------------------
    [INFO] Building Maven Default Project
    [INFO]    task-segment: [archetype:create] (aggregator-style)
    [INFO] ------------------------------------------------------------------------
    [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:create]
    [WARNING] This goal is deprecated. Please use mvn archetype:generate instead
    [INFO] Defaulting package to group ID: org.glassfish.samples.osgi.helloworld
    [INFO] artifact org.apache.maven.archetypes:maven-archetype-quickstart: checking for updates from central
    [INFO] ----------------------------------------------------------------------------
    [INFO] Using following parameters for creating OldArchetype: maven-archetype-quickstart:RELEASE
    [INFO] ----------------------------------------------------------------------------
    [INFO] Parameter: groupId, Value: org.glassfish.samples.osgi.helloworld
    [INFO] Parameter: packageName, Value: org.glassfish.samples.osgi.helloworld
    [INFO] Parameter: package, Value: org.glassfish.samples.osgi.helloworld
    [INFO] Parameter: artifactId, Value: helloworld
    [INFO] Parameter: basedir, Value: /Users/arungupta/samples/v3/osgi
    [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/v3/osgi/helloworld
    [INFO] ------------------------------------------------------------------------
    [INFO] BUILD SUCCESSFUL
    [INFO] ------------------------------------------------------------------------
    [INFO] Total time: 11 seconds
    [INFO] Finished at: Wed Jan 20 14:12:41 PST 2010
    [INFO] Final Memory: 12M/80M
    [INFO] ------------------------------------------------------------------------
    
  2. Change the generated App class in "src/main/java/org/glassfish/samples/osgi/helloworld" folder so that it looks like:
    package org.glassfish.samples.osgi.helloworld;
    
    import org.osgi.framework.BundleActivator;
    import org.osgi.framework.BundleContext;
    
    /\*\*
     \* Hello world!
     \*
     \*/
    public class App implements BundleActivator {
        public void start(BundleContext context) throws Exception {
            System.out.println("Hey!");
        }
        public void stop(BundleContext context) throws Exception {
            System.out.println("Bye!");
        }
    }
    
    
    This is a trivial Activator class but sitll shows the key methods. The changes are highlighted in bold.
  3. Update "pom.xml" with the following changes:
    1. Change <packaging> to "bundle" from the default value of "jar".
    2. Add <dependency> on "org.osgi.core".
    3. Add the <plugin> maven-bundle-plugin and provide <instructions> to generate the appropriate MANIFEST.MF.
      <project xmlns="http://maven.apache.org/POM/4.0.0" 
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
                        http://maven.apache.org/maven-v4_0_0.xsd">
       <modelVersion>4.0.0</modelVersion>
       <groupId>org.glassfish.samples.osgi.helloworld</groupId>
       <artifactId>helloworld</artifactId>
       <packaging>bundle</packaging>
       <version>1.0-SNAPSHOT</version>
       <name>helloworld</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.apache.felix</groupId>
           <artifactId>org.osgi.core</artifactId>
           <version>1.0.0</version>
         </dependency>
       </dependencies>
       <build>
         <plugins>
           <plugin>
             <groupId>org.apache.felix</groupId>
             <artifactId>maven-bundle-plugin</artifactId>
             <extensions>true</extensions>
             <configuration>
               <instructions>
                 <Export-Package>${pom.groupId}</Export-Package>
                 <Bundle-SymbolicName>${pom.artifactId}</Bundle-SymbolicName>
                 <Bundle-Activator>${pom.groupId}.App</Bundle-Activator>
               </instructions>
             </configuration>
           </plugin>
         </plugins>
       </build>
      </project>
      

  4. Generate the OSGi bundle as shown below:
    ~/samples/v3/osgi/helloworld >mvn install
    [INFO] Scanning for projects...
    [INFO] ------------------------------------------------------------------------
    [INFO] Building helloworld
    [INFO]    task-segment: [install]
    [INFO] ------------------------------------------------------------------------
    [INFO] [resources:resources]
    [INFO] Using default encoding to copy filtered resources.
    [INFO] [compiler:compile]
    [INFO] Compiling 1 source file to /Users/arungupta/samples/v3/osgi/helloworld/target/classes
    [INFO] [resources:testResources]
    [INFO] Using default encoding to copy filtered resources.
    [INFO] [compiler:testCompile]
    [INFO] Compiling 1 source file to /Users/arungupta/samples/v3/osgi/helloworld/target/test-classes
    [INFO] [surefire:test]
    [INFO] Surefire report directory: /Users/arungupta/samples/v3/osgi/helloworld/target/surefire-reports
    
    -------------------------------------------------------
     T E S T S
    -------------------------------------------------------
    Running org.glassfish.samples.osgi.helloworld.AppTest
    Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.06 sec
    
    Results :
    
    Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
    
    [INFO] [bundle:bundle]
    [INFO] [install:install]
    [INFO] Installing /Users/arungupta/samples/v3/osgi/helloworld/target/helloworld-1.0-SNAPSHOT.jar to /Users/arungupta/.m2/repository/org/glassfish/samples/osgi/helloworld/helloworld/1.0-SNAPSHOT/helloworld-1.0-SNAPSHOT.jar
    [INFO] [bundle:install]
    [INFO] Parsing file:/Users/arungupta/.m2/repository/repository.xml
    [INFO] Installing org/glassfish/samples/osgi/helloworld/helloworld/1.0-SNAPSHOT/helloworld-1.0-SNAPSHOT.jar
    [INFO] Writing OBR metadata
    [INFO] ------------------------------------------------------------------------
    [INFO] BUILD SUCCESSFUL
    [INFO] ------------------------------------------------------------------------
    [INFO] Total time: 8 seconds
    [INFO] Finished at: Wed Jan 20 14:18:31 PST 2010
    [INFO] Final Memory: 20M/80M
    [INFO] ------------------------------------------------------------------------
    
    
    The generated "target/helloworld-1.0-SNAPSHOT.jar" has the following contents:

     META-INF/MANIFEST.MF
     META-INF/
     META-INF/maven/
     META-INF/maven/org.glassfish.samples.osgi.helloworld/
     META-INF/maven/org.glassfish.samples.osgi.helloworld/helloworld/
     META-INF/maven/org.glassfish.samples.osgi.helloworld/helloworld/pom.properties
     META-INF/maven/org.glassfish.samples.osgi.helloworld/helloworld/pom.xml
     org/
     org/glassfish/
     org/glassfish/samples/
     org/glassfish/samples/osgi/
     org/glassfish/samples/osgi/helloworld/
     org/glassfish/samples/osgi/helloworld/App.class
    

    And the generated "MANIFEST.MF" looks like:
    Manifest-Version: 1.0
    Export-Package: org.glassfish.samples.osgi.helloworld;uses:="org.osgi.
     framework"
    Built-By: arungupta
    Tool: Bnd-0.0.357
    Bundle-Name: helloworld
    Created-By: Apache Maven Bundle Plugin
    Bundle-Version: 1.0.0.SNAPSHOT
    Build-Jdk: 1.6.0_17
    Bnd-LastModified: 1264025910352
    Bundle-ManifestVersion: 2
    Bundle-Activator: org.glassfish.samples.osgi.helloworld.App
    Import-Package: org.glassfish.samples.osgi.helloworld,org.osgi.framewo
     rk;version="1.3"
    Bundle-SymbolicName: helloworld
    

Lets install this newly created OSGi bundle in GlassFish v3. First, fire up GlassFish as:

~/tools/glassfish/v3/74b/glassfishv3/glassfish >./bin/asadmin start-domain -v
Jan 20, 2010 2:30:39 PM com.sun.enterprise.admin.launcher.GFLauncherLogger info
INFO: JVM invocation command line:
/System/Library/Frameworks/JavaVM.framework/Versions/1.6/Home/bin/java
-cp
/Users/arungupta/tools/glassfish/v3/74b/glassfishv3/glassfish/modules/glassfish.jar
-XX:+UnlockDiagnosticVMOptions
-XX:MaxPermSize=192m
-XX:NewRatio=2
-XX:+LogVMOutput

. . .

Jan 20, 2010 2:30:40 PM com.sun.enterprise.admin.launcher.GFLauncherLogger info
INFO: Successfully launched in 52 msec.
Jan 20, 2010 2:30:40 PM com.sun.enterprise.glassfish.bootstrap.ASMain main
INFO: Launching GlassFish on Felix platform

Welcome to Felix
================

[#|2010-01-20T14:30:49.437-0800|INFO|glassfishv3.0|com.sun.grizzly.config.GrizzlyServiceListener|_ThreadID=11;_ThreadName=FelixStartLevel;|Perform lazy SSL initialization for the listener 'http-listener-2'|#]

[#|2010-01-20T14:30:49.527-0800|INFO|glassfishv3.0|com.sun.grizzly.config.GrizzlyServiceListener|_ThreadID=12;_ThreadName=Thread-11;|Starting Grizzly Framework 1.9.18-k - Wed Jan 20 14:30:49 PST 2010|#]

. . .

[#|2010-01-20T14:30:58.668-0800|INFO|glassfishv3.0|javax.enterprise.system.std.com.sun.enterprise.v3.services.impl|_ThreadID=21;_ThreadName={felix.fileinstall.poll=5000, felix.fileinstall.bundles.new.start=true, felix.fileinstall.dir=/Users/arungupta/tools/glassfish/v3/74b/glassfishv3/glassfish/modules/autostart/, felix.fileinstall.debug=1};|Started bundle: file:/Users/arungupta/tools/glassfish/v3/74b/glassfishv3/glassfish/modules/autostart/org.apache.felix.scr.jar|#]

[#|2010-01-20T14:30:58.786-0800|INFO|glassfishv3.0|javax.enterprise.system.std.com.sun.enterprise.v3.services.impl|_ThreadID=21;_ThreadName={felix.fileinstall.poll=5000, felix.fileinstall.bundles.new.start=true, felix.fileinstall.dir=/Users/arungupta/tools/glassfish/v3/74b/glassfishv3/glassfish/modules/autostart/, felix.fileinstall.debug=1};|Started bundle: file:/Users/arungupta/tools/glassfish/v3/74b/glassfishv3/glassfish/modules/autostart/osgi-web-container.jar|#]

[#|2010-01-20T14:31:00.436-0800|INFO|glassfishv3.0|null|_ThreadID=23;_ThreadName=ping;|Total number of available updates : 0|#]

There are several ways to manage the OSGi bundles in GlassFish v3:

  1. The "asadmin" command (explained here)
  2. Filesystem operations using the pre-installed Apache Felix File Install bundle (explained here)
  3. A Telnet shell using pre-installed Apache Felix Remote Shell (explained here and TOTD #103)
  4. A Web browser using the Apache Felix Web Console (needs to be installed separately and more details below)
  5. A RESTful client by installing the REST console (need to be installed separately and more details below)


Lets explore each option in detail now.

Option 1: Manage the OSGi bundle using the "asadmin" command

  1. Deploy the generated OSGi bundle using asadmin command:
    ~/samples/v3/osgi/helloworld/target >~/tools/glassfish/v3/74b/glassfishv3/glassfish/bin/asadmin deploy --type osgi helloworld-1.0-SNAPSHOT.jar 
    Application deployed successfully with name helloworld-1.0-SNAPSHOT.
    
    
    Command deploy executed successfully.
    
    The server log shows the following output:
    [#|2010-01-20T16:15:10.553-0800|INFO|glassfishv3.0|javax.enterprise.system.std.com.
    sun.enterprise.v3.services.impl|_ThreadID=36;_ThreadName=http-thread-pool-4848-(2);
    |Hey!|#]
    
    
    Notice "Hey!" message in the server log as the bundle gets started.
  2. Verify the installed bundle as:
    ~/samples/v3/osgi/helloworld/target >~/tools/glassfish/v3/74b/glassfishv3/glassfish/bin/asadmin list-applications
    helloworld-1.0-SNAPSHOT 
    
    Command list-applications executed successfully.
    

    Or if there are multiple applications deployed then only the OSGi bundles can be queried as:

    ~/samples/v3/osgi/helloworld/target >~/tools/glassfish/v3/74b/glassfishv3/glassfish/bin/asadmin list-applications --type osgi
    helloworld-1.0-SNAPSHOT 
    
    Command list-applications executed successfully.
    
  3. The bundle can be undeployed as:

    ~/samples/v3/osgi/helloworld/target >~/tools/glassfish/v3/74b/glassfishv3/glassfish/bin/asadmin undeploy helloworld-1.0-SNAPSHOT 
    
    Command undeploy executed successfully.
    
    
    And then the following message is shown on the console:
    [#|2010-01-20T16:22:19.554-0800|INFO|glassfishv3.0|javax.enterprise.system.std.com.
    sun.enterprise.v3.services.impl|_ThreadID=37;_ThreadName=http-thread-pool-4848-(1);
    |Bye!|#]
    
    
    Notice "Bye!" message in second line of the log output indicating the bundle is stopped.

Option 2: Manage the OSGi bundle using file system operations

  1. Copy the generated jar (target/helloworld-1.0-SNAPSHOT.jar) in "modules/autostart" directory as:
    ~/tools/glassfish/v3/74b/glassfishv3/glassfish >cp ~/samples/v3/osgi/helloworld/target/helloworld-1.0-SNAPSHOT.jar modules/autostart/
    
    
    and that shows the log output as:
    [#|2010-01-20T16:29:04.625-0800|INFO|glassfishv3.0|javax.enterprise.system.std.com.
    sun.enterprise.v3.services.impl|_ThreadID=21;_ThreadName={felix.fileinstall.poll=5000, felix.fileinstall.bundles.new.start=true, felix.fileinstall.dir=/Users/arungupta/tools/glassfish/v3/74b/glassfishv3/glassfish
    /modules/autostart/, felix.fileinstall.debug=1};|Installed /Users/arungupta/tools/glassfish/v3/74b/glassfishv3/glassfish/modules/autostart/
    helloworld-1.0-SNAPSHOT.jar|#]
    
    [#|2010-01-20T16:29:04.635-0800|INFO|glassfishv3.0|javax.enterprise.system.std.com.
    sun.enterprise.v3.services.impl|_ThreadID=21;_ThreadName={felix.fileinstall.poll=5000, felix.fileinstall.bundles.new.start=true, felix.fileinstall.dir=/Users/arungupta/tools/glassfish/v3/74b/glassfishv3/glassfish
    /modules/autostart/, felix.fileinstall.debug=1};|Hey!|#]
    
    [#|2010-01-20T16:29:04.636-0800|INFO|glassfishv3.0|javax.enterprise.system.std.com.
    sun.enterprise.v3.services.impl|_ThreadID=21;_ThreadName={felix.fileinstall.poll=5000, felix.fileinstall.bundles.new.start=true, felix.fileinstall.dir=/Users/arungupta/tools/glassfish/v3/74b/glassfishv3/glassfish
    /modules/autostart/, felix.fileinstall.debug=1};|Started bundle: file:/Users/arungupta/tools/glassfish/v3/74b/glassfishv3/glassfish/modules/autostart
    /helloworld-1.0-SNAPSHOT.jar|#]
    
    
    Notice "Hey!" message in the second line of log output as the bundle gets started.
  2. The bundle can be undeployed by removing the JAR file from "modules/autostart" directory as:

    ~/tools/glassfish/v3/74b/glassfishv3/glassfish >rm modules/autostart/helloworld-1.0-SNAPSHOT.jar
    
    
    that shows the following output:
    ~/tools/glassfish/v3/74b/glassfishv3/glassfish >[#|2010-01-20T16:32:04.677-0800|INFO|glassfishv3.0|javax.enterprise.system.std.com.
    sun.enterprise.v3.services.impl|_ThreadID=21;_ThreadName={felix.fileinstall.poll=5000, felix.fileinstall.bundles.new.start=true, felix.fileinstall.dir=/Users/arungupta/tools/glassfish/v3/74b/glassfishv3/glassfish
    /modules/autostart/, felix.fileinstall.debug=1};|Uninstalling bundle 224 (helloworld)|#]
    
    [#|2010-01-20T16:32:04.679-0800|INFO|glassfishv3.0|javax.enterprise.system.std.com.
    sun.enterprise.v3.services.impl|_ThreadID=21;_ThreadName={felix.fileinstall.poll=5000, felix.fileinstall.bundles.new.start=true, felix.fileinstall.dir=/Users/arungupta/tools/glassfish/v3/74b/glassfishv3/glassfish
    /modules/autostart/, felix.fileinstall.debug=1};|Bye!|#]
    
    [#|2010-01-20T16:32:04.682-0800|INFO|glassfishv3.0|javax.enterprise.system.std.com.
    sun.enterprise.v3.services.impl|_ThreadID=21;_ThreadName={felix.fileinstall.poll=5000, felix.fileinstall.bundles.new.start=true, felix.fileinstall.dir=/Users/arungupta/tools/glassfish/v3/74b/glassfishv3/glassfish
    /modules/autostart/, felix.fileinstall.debug=1};|Uninstalled /Users/arungupta/tools/glassfish/v3/74b/glassfishv3/glassfish/modules/autostart
    /helloworld-1.0-SNAPSHOT.jar|#]
    
    
    Notice "Bye!" message in second line of the log output indicating the bundle is stopped.

Option 3: Manage the OSGi bundle using a remote Telnet Shell

  1. Connecting to the Felix Remote Shell as:
    ~/tools/glassfish/v3/74b/glassfishv3/glassfish >telnet localhost 6666
    Trying ::1...
    telnet: connect to address ::1: Connection refused
    Trying fe80::1...
    telnet: connect to address fe80::1: Connection refused
    Trying 127.0.0.1...
    Connected to localhost.
    Escape character is '\^]'.
    
    Felix Remote Shell Console:
    ============================
    
    ->
    
  2. Install the bundle as:
    -> install file:///Users/arungupta/samples/v3/osgi/helloworld/target/helloworld-1.0-SNAPSHOT.jar
    Bundle ID: 225
    
    The command output shows "225" as the bundle id. This id is used to start / stop / uninstall the bundle.
  3. Check the bundle status as:
    -> find hello
    START LEVEL 1
       ID   State         Level  Name
    [ 225] [Installed  ] [    1] helloworld (1.0.0.SNAPSHOT)
    
    
    and then start, stop, and uninstall the bundle as:
    -> start 225
    -> stop 225
    -> uninstall 225
    -> find hello
    No matching bundles found
    
    
    which shows following output in the logs:
    [#|2010-01-20T16:43:45.399-0800|INFO|glassfishv3.0|javax.enterprise.system.std.com.
    sun.enterprise.v3.services.impl|_ThreadID=38;_ThreadName=telnetconsole.shell remote=/127.0.0.1:4894;|Hey!|#]
    
    [#|2010-01-20T16:43:58.516-0800|INFO|glassfishv3.0|javax.enterprise.system.std.com.
    sun.enterprise.v3.services.impl|_ThreadID=38;_ThreadName=telnetconsole.shell remote=/127.0.0.1:4894;|Bye!|#]
    

    Notice "Hey!" and "Bye!" messages in the log output as the bundle is started and stopped.


Option 4 - Manage the OSGi bundle using a Web browser

Lets see how the OSGi bundles in GlassFish can be managed using Apache Felix Web Console. This is originally explained in Sahoo's blog.

  1. Copy GlassFish OSGi HTTP Service bundle from here (latest) and save it in the "modules/autostart" directory.

  2. Copy Apache Felix Web Console bundle from here (latest) and save it in the "modules/autostart" directory.

  3. Ignore the "NoClassDefFoundError" in the server log. The key is to look for the following message in server log:

    Started bundle: file:/Users/arungupta/tools/glassfish/v3/74b/glassfishv3/glassfish/modules/autostart/org.apache.felix.webconsole-2.0.4.jar|#]
    
  4. Open the URL "http://localhost:8080/osgi/system/console/bundles" in a browser and use "admin" as the username and "admin" as the password as shown below:



    I had to enter the credentials couple of times for the login to work but finally the following window showed up:



    It shows a complete summary of all the OSGi bundles available/installed/active etc in GlassFish v3. A new OSGi bundle can be installed by clicking on "Choose File" button. Several administration commands such as Start/Stop, Update, Uninstall, Refresh Import Packages can be issued for each bundle by clicking on associated buttons.

  5. Install the OSGi bundle by clicking on "Choose File" and selecting "helloworld-1.0.-SNAPSHOT.jar" and then click on "Install or Update" button. The following message is shown in the server log:

    [#|2010-01-20T17:04:46.654-0800|INFO|glassfishv3.0|javax.enterprise.system.std.com.
    sun.enterprise.v3.services.impl|_ThreadID=39;_ThreadName=Background Install /var/folders/+E/+E6YtSvGGEKNwOA77I-9Fk+++TI/-Tmp-/install1657418488877506078.tmp;
    |Hey!|#]
    

    The bundle gets installed and started as identified by "Hey!" message.
    The recently installed "HelloWorld" bundle looks like:

    Clicking on "helloworld" shows the complete status about the bundle as shown below:

     

  6. The bundle can be stopped by clicking on the Stopped, Refreshed Package Imports, Updated, and Uninstalled by clicking on the respective buttons in the "Actions" column. Clicking on the Stop button shows the following message:

    [#|2010-01-20T17:10:56.359-0800|INFO|glassfishv3.0|javax.enterprise.system.std.com
    .sun.enterprise.v3.services.impl|_ThreadID=25;_ThreadName=http-thread-pool-8080-(2);
    |Bye!|#]
    
    
    Notice "Bye!" message indicating the bundle has stopped.

Option 5: Manage the OSGi bundle using a REST console

  1. If not done already, copy GlassFish OSGi HTTP Service bundle from here (latest) and save it in the "modules/autostart" directory.
  2. Download the REST console bundle (latest) in "modules/autostart" directory.
  3. The complete list of bundles is available in Text or XML format by accessing the URL "http://localhost:8080/osgi/restconsole/bundles/.txt" or "http://localhost:8080/osgi/restconsole/bundles" respectively. Here is how the text output looks like:
      % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                     Dload  Upload   Total   Spent    Left  Speed
    100 16198    0 16198    0     0  1173k      0 --:--:-- --:--:-- --:--:-- 1173kbundles 
         bundle 
              id 
                   0 
              symbolic-name 
                   org.apache.felix.framework 
    
    . . .
    
              description 
                   Generated using Pax-Construct 
              vendor 
              version 
                   1.0.0.SNAPSHOT 
              location 
                   file:/Users/arungupta/tools/glassfish/v3/74b/glassfishv3/glassfish/modules/autostart/
    com.knokode.osgi.restconsole.main-1.0-PREVIEW01.jar 
              state 
                   ACTIVE
    
  4. The OSGi bundle should be installed by issuing the following command:
    curl -X PUT file:///Users/arungupta/samples/v3/osgi/helloworld/target/helloworld-1.0-SNAPSHOT.jar http://localhost:8080/osgi/restconsole/bundles
    
    but it's giving a "Segmentation fault". Am following with @fdiotalevi.

    Anyway, the complete usage information of the REST console is described here.

So how do you manage OSGi bundles in GlassFish v3 - asadmin, file system operations, telnet console, web browser, or REST ?

UPDATE: Osgish is a command-line shell for OSGi and implemented in Perl. See the complete installation instructions and it can be used to manage OSGi runtime in GlassFish as well.

A complete archive of all the TOTDs is available here.

Technorati: totd glassfish v3 osgi apache felix bundles maven

Thursday Aug 06, 2009

TOTD #91: Retrieve JSON libraries using Maven dependency: json-lib


So you need to include JSON libraries in your Maven project. The only option that seems to be currently available is using json-lib with the following dependencies:

        <dependency>
            <groupId>net.sf.json-lib</groupId>
            <artifactId>json-lib</artifactId>
            <version>2.3</version>
            <classifier>jdk15</classifier>
        </dependency>

The APIs are based upon the original work done at json.org/java.

If you are using NetBeans for adding the Maven dependency then it nicely shows the different versions for the artifact as shown below:



The usage guide and samples at json-lib have lots of documentation to get you started. Don't forget the package names are changed so "org.json.JSONObject" is "net.sf.json.JSONObject" and similarly other classes.

Please leave suggestions on other TOTD (Tip Of The Day) that you'd like to see. A complete archive of all the tips is available here.

Technorati: json maven json-lib netbeans

Wednesday Jun 25, 2008

TOTD #36: Deploy OSGi bundles in GlassFish using maven-bundle-plugin


GlassFish v3 is a modular (OSGi compliant), embeddable (runs in-VM) and extensible (supports non-Java apps) Application Server.

The extensible part is demonstrated by deployment of Rails and Grails applications. An example of embeddability is an in-VM Servlet. This blog demonstrates how a simple OSGi bundle can be easily created using Maven Bundle Plugin and deployed on v3 trunk.
  1. Generate a simple Maven project using the command as shown below:

    ~/samples/v3 >mvn archetype:create -DarchetypeGroupId=org.apache.maven.archetypes -DgroupId=org.glassfish.samples.osgi.helloworld -DartifactId=helloworld
    [INFO] Scanning for projects...
    [INFO] Searching repository for plugin with prefix: 'archetype'.
    [INFO] Ignoring available plugin update: 2.0-alpha-3 as it requires Maven version 2.0.7
    [INFO] Ignoring available plugin update: 2.0-alpha-2 as it requires Maven version 2.0.7
    [INFO] Ignoring available plugin update: 2.0-alpha-1 as it requires Maven version 2.0.7
    [INFO] ----------------------------------------------------------------------------
    [INFO] Building Maven Default Project
    [INFO]    task-segment: [archetype:create] (aggregator-style)
    [INFO] ----------------------------------------------------------------------------
    [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] \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
    [INFO] Starting Jakarta Velocity v1.4
    [INFO] RuntimeInstance initializing.
    [INFO] Default Properties File: org/apache/velocity/runtime/defaults/velocity.properties
    [INFO] Default ResourceManager initializing. (class org.apache.velocity.runtime.resource.ResourceManagerImpl)
    [INFO] Resource Loader Instantiated: org.codehaus.plexus.velocity.ContextClassLoaderResourceLoader
    [INFO] ClasspathResourceLoader : initialization starting.
    [INFO] ClasspathResourceLoader : initialization complete.
    [INFO] ResourceCache : initialized. (class org.apache.velocity.runtime.resource.ResourceCacheImpl)
    [INFO] Default ResourceManager initialization complete.
    [INFO] Loaded System Directive: org.apache.velocity.runtime.directive.Literal
    [INFO] Loaded System Directive: org.apache.velocity.runtime.directive.Macro
    [INFO] Loaded System Directive: org.apache.velocity.runtime.directive.Parse
    [INFO] Loaded System Directive: org.apache.velocity.runtime.directive.Include
    [INFO] Loaded System Directive: org.apache.velocity.runtime.directive.Foreach
    [INFO] Created: 20 parsers.
    [INFO] Velocimacro : initialization starting.
    [INFO] Velocimacro : adding VMs from VM library template : VM_global_library.vm
    [ERROR] ResourceManager : unable to find resource 'VM_global_library.vm' in any resource loader.
    [INFO] Velocimacro : error using  VM library template VM_global_library.vm : org.apache.velocity.exception.ResourceNotFoundException: Unable to find resource 'VM_global_library.vm'
    [INFO] Velocimacro :  VM library template macro registration complete.
    [INFO] Velocimacro : allowInline = true : VMs can be defined inline in templates
    [INFO] Velocimacro : allowInlineToOverride = false : VMs defined inline may NOT replace previous VM definitions
    [INFO] Velocimacro : allowInlineLocal = false : VMs defined inline will be  global in scope if allowed.
    [INFO] Velocimacro : initialization complete.
    [INFO] Velocity successfully started.
    [INFO] [archetype:create]
    [INFO] Defaulting package to group ID: org.glassfish.samples.osgi.helloworld
    [INFO] ----------------------------------------------------------------------------
    [INFO] Using following parameters for creating Archetype: maven-archetype-quickstart:RELEASE
    [INFO] ----------------------------------------------------------------------------
    [INFO] Parameter: groupId, Value: org.glassfish.samples.osgi.helloworld
    [INFO] Parameter: packageName, Value: org.glassfish.samples.osgi.helloworld
    [INFO] Parameter: basedir, Value: /Users/arungupta/samples/v3
    [INFO] Parameter: package, Value: org.glassfish.samples.osgi.helloworld
    [INFO] Parameter: version, Value: 1.0-SNAPSHOT
    [INFO] Parameter: artifactId, Value: helloworld
    [INFO] \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* End of debug info from resources from generated POM \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
    [INFO] Archetype created in dir: /Users/arungupta/samples/v3/helloworld
    [INFO] ------------------------------------------------------------------------
    [INFO] BUILD SUCCESSFUL
    [INFO] ------------------------------------------------------------------------
    [INFO] Total time: 1 second
    [INFO] Finished at: Wed Jun 25 10:07:27 PDT 2008
    [INFO] Final Memory: 5M/10M
    [INFO] ------------------------------------------------------------------------
  2. Change the generated App class in "src/main/java/org/glassfish/samples/osgi/helloworld" folder so that it looks like:

    package org.glassfish.samples.osgi.helloworld;

    import org.osgi.framework.BundleActivator;
    import org.osgi.framework.BundleContext;

    /\*\*
     \* Hello world!
     \*
     \*/
    public class App implements BundleActivator {
        public void start(BundleContext context) throws Exception {
            System.out.println("Hey!");
        }
        public void stop(BundleContext context) throws Exception {
            System.out.println("Bye!");
        }
    }


    This is a trivial Activator class but sitll shows the key methods. The changes are highlighted in bold.
  3. Update "pom.xml" with the following changes:
    1. Change the <packaging> to "bundle" from the default value of "jar".
    2. Add the <dependency> on "org.osgi.core".
    3. Add the <plugin> maven-bundle-plugin and provide <instructions> to generate the appropriate MANIFEST.MF.

    The updated "pom.xml" with changes highlighted in bold are shown below:

    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
      <modelVersion>4.0.0</modelVersion>
      <groupId>org.glassfish.samples.osgi.helloworld</groupId>
      <artifactId>helloworld</artifactId>
      <packaging>bundle</packaging>
      <version>1.0-SNAPSHOT</version>
      <name>helloworld</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.apache.felix</groupId>
          <artifactId>org.osgi.core</artifactId>
          <version>1.0.0</version>
        </dependency>
      </dependencies>
      <build>
        <plugins>
          <plugin>
            <groupId>org.apache.felix</groupId>
            <artifactId>maven-bundle-plugin</artifactId>
            <extensions>true</extensions>
            <configuration>
              <instructions>
                <Export-Package>${pom.groupId}</Export-Package>
                <Bundle-SymbolicName>${pom.artifactId}</Bundle-SymbolicName>
                <Bundle-Activator>${pom.groupId}.App</Bundle-Activator>
              </instructions>
            </configuration>
          </plugin>
        </plugins>
      </build>
    </project>
  4. Generate the OSGi bundle as shown below:

    ~/samples/v3/helloworld >mvn install
    [INFO] Scanning for projects...
    [INFO] ----------------------------------------------------------------------------
    [INFO] Building helloworld
    [INFO]    task-segment: [install]
    [INFO] ----------------------------------------------------------------------------
    [INFO] [resources:resources]
    [INFO] Using default encoding to copy filtered resources.
    [INFO] [compiler:compile]
    [INFO] Compiling 1 source file to /Users/arungupta/samples/v3/helloworld/target/classes
    [INFO] [resources:testResources]
    [INFO] Using default encoding to copy filtered resources.
    [INFO] [compiler:testCompile]
    [INFO] Compiling 1 source file to /Users/arungupta/samples/v3/helloworld/target/test-classes
    [INFO] [surefire:test]
    [INFO] Surefire report directory: /Users/arungupta/samples/v3/helloworld/target/surefire-reports

    -------------------------------------------------------
     T E S T S
    -------------------------------------------------------
    Running org.glassfish.samples.osgi.helloworld.AppTest
    Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.022 sec

    Results :

    Tests run: 1, Failures: 0, Errors: 0, Skipped: 0

    [INFO] [bundle:bundle]
    [INFO] [install:install]
    [INFO] Installing /Users/arungupta/samples/v3/helloworld/target/helloworld-1.0-SNAPSHOT.jar to /Users/arungupta/.m2/repository/org/glassfish/samples/osgi/helloworld/helloworld/1.0-SNAPSHOT/helloworld-1.0-SNAPSHOT.jar
    [INFO] [bundle:install]
    [INFO] Parsing file:/Users/arungupta/.m2/repository/repository.xml
    [INFO] Installing org/glassfish/samples/osgi/helloworld/helloworld/1.0-SNAPSHOT/helloworld-1.0-SNAPSHOT.jar
    [INFO] Writing OBR metadata
    [INFO] ------------------------------------------------------------------------
    [INFO] BUILD SUCCESSFUL
    [INFO] ------------------------------------------------------------------------
    [INFO] Total time: 4 seconds
    [INFO] Finished at: Wed Jun 25 10:20:27 PDT 2008
    [INFO] Final Memory: 22M/54M
    [INFO] ------------------------------------------------------------------------

    The generated "target/helloworld-1.0-SNAPSHOT.jar" has the following contents:

    META-INF/MANIFEST.MF
    META-INF/
    META-INF/maven/
    META-INF/maven/org.glassfish.samples.osgi.helloworld/
    META-INF/maven/org.glassfish.samples.osgi.helloworld/helloworld/
    META-INF/maven/org.glassfish.samples.osgi.helloworld/helloworld/pom.properties
    META-INF/maven/org.glassfish.samples.osgi.helloworld/helloworld/pom.xml
    org/
    org/glassfish/
    org/glassfish/samples/
    org/glassfish/samples/osgi/
    org/glassfish/samples/osgi/helloworld/
    org/glassfish/samples/osgi/helloworld/App.class

    And the generated "MANIFEST.MF" looks like:

    Manifest-Version: 1.0
    Export-Package: org.glassfish.samples.osgi.helloworld;uses:="org.osgi.
     framework"
    Built-By: arungupta
    Tool: Bnd-0.0.255
    Bundle-Name: helloworld
    Created-By: Apache Maven Bundle Plugin
    Bundle-Version: 1.0.0.SNAPSHOT
    Build-Jdk: 1.6.0_05
    Bnd-LastModified: 1214414426851
    Bundle-ManifestVersion: 2
    Bundle-Activator: org.glassfish.samples.osgi.helloworld.App
    Import-Package: org.glassfish.samples.osgi.helloworld,org.osgi.framewo
     rk;version="1.3"
    Bundle-SymbolicName: helloworld
Now let's install this newly created bundle using Felix shell in GlassFish v3. Check out and build GlassFish v3 workspace as explained in TOTD #33. Unzip "~/workspaces/glassfish/v3/distributions/web/target/web.zip" and enable Felix TUI as explained in TOTD #34.
  1. Start GlassFish v3 as:

    ~/testbed/glassfish/v3/snapshot/glassfish >java -jar modules/glassfish-10.0-SNAPSHOT.jar
    Jun 25, 2008 4:09:19 PM com.sun.enterprise.glassfish.bootstrap.ASMain main
    INFO: Launching GlassFish on Apache Felix OSGi platform
    Jun 25, 2008 4:09:19 PM com.sun.enterprise.glassfish.bootstrap.ASMainOSGi getSharedRepos
    INFO: /Users/arungupta/testbed/glassfish/v3/snapshot/glassfish/domains/domain1/lib does not exist

    Welcome to Felix.
    =================

    Jun 25, 2008 4:09:20 PM HK2Main start
    INFO: contextRootDir = /Users/arungupta/testbed/glassfish/v3/snapshot/glassfish/modules
    Jun 25, 2008 4:09:20 PM OSGiFactoryImpl initialize
    INFO: Singleton already initialized as com.sun.enterprise.module.impl.HK2Factory@3d44d0c6
    Jun 25, 2008 4:09:20 PM OSGiModuleImpl loadClass
    INFO: Started bundle org.glassfish.common.glassfish-mbeanserver [19]
    Jun 25, 2008 4:09:20 PM OSGiModuleImpl loadClass
    INFO: Started bundle org.glassfish.core.kernel [51]
    Jun 25, 2008 4:09:21 PM OSGiModuleImpl loadClass
    INFO: Started bundle org.glassfish.common.glassfish-naming [8]
    Jun 25, 2008 4:09:21 PM OSGiModuleImpl loadClass
    INFO: Started bundle org.glassfish.admin.config-api [43]
    Jun 25, 2008 4:09:21 PM OSGiModuleImpl loadClass
    INFO: Started bundle org.glassfish.common.internal-api [33]
    Jun 25, 2008 4:09:21 PM OSGiModuleImpl loadClass
    INFO: Started bundle org.glassfish.deployment.deployment-common [10]
    Jun 25, 2008 4:09:21 PM 
    INFO: JMXMP connector server URL = service:jmx:jmxmp://localhost:8888
    Jun 25, 2008 4:09:21 PM com.sun.enterprise.v3.services.impl.GrizzlyProxy start
    INFO: Listening on port 8080
    Jun 25, 2008 4:09:21 PM com.sun.enterprise.v3.services.impl.GrizzlyProxy start
    INFO: Listening on port 8181
    Jun 25, 2008 4:09:21 PM com.sun.enterprise.v3.services.impl.GrizzlyProxy start
    INFO: Listening on port 4848
    Jun 25, 2008 4:09:21 PM OSGiModuleImpl loadClass
    INFO: Started bundle org.glassfish.common.container-common [21]
    Jun 25, 2008 4:09:22 PM com.sun.enterprise.v3.admin.adapter.AdminConsoleAdapter setContextRoot
    INFO: Admin Console Adapter: context root: /admin
    Jun 25, 2008 4:09:22 PM com.sun.enterprise.v3.server.AppServerStartup run
    INFO: Glassfish v3 started in 1789 ms
    Jun 25, 2008 4:09:22 PM 
    INFO: ->
    Jun 25, 2008 4:09:22 PM com.sun.enterprise.glassfish.bootstrap.ASMainFelix launchOSGiFW
    INFO: Framework successfully started
  2. Install the Hello World bundle as:

    install file:///Users/arungupta/samples/v3/helloworld/target/helloworld-1.0-SNAPSHOT.jar
    Jun 25, 2008 4:10:19 PM 
    INFO: Bundle ID: 75
    Jun 25, 2008 4:10:19 PM 
    INFO: ->

    The command output shows "75" as the process id. This id is used to start/stop/uninstall the bundle later.
  3. Check the bundle status

    ps     
    Jun 25, 2008 4:10:27 PM 
    INFO: START LEVEL 1
    Jun 25, 2008 4:10:27 PM 
    INFO:    ID   State         Level  Name
    Jun 25, 2008 4:10:27 PM 
    INFO: [   0] [Active     ] [    0] System Bundle (1.0.4)
    Jun 25, 2008 4:10:27 PM 
    INFO: [   1] [Active     ] [    1] org.jvnet.tiger-types repackaged as module (0.3.2)
    Jun 25, 2008 4:10:27 PM 

    . . .

    INFO: [  71] [Installed  ] [    1] Web module command line interface (10.0.0.SNAPSHOT)
    Jun 25, 2008 4:10:27 PM 
    INFO: [  72] [Installed  ] [    1] Admin GUI Web Container Plugin (10.0.0.SNAPSHOT)
    Jun 25, 2008 4:10:27 PM 
    INFO: [  75] [Installed  ] [    1] helloworld (1.0.0.SNAPSHOT)
    Jun 25, 2008 4:10:27 PM 
    INFO: ->

    The last log output shows the newly added process.
  4. Start the bundle as:

    start 75
    Jun 25, 2008 4:10:32 PM 
    INFO: Hey!
    Jun 25, 2008 4:10:32 PM 
    INFO: ->

    This fragment shows "Hey!" output printed from the start method of Activator.
  5. Stop the bundle as:

    stop 75
    Jun 25, 2008 4:10:35 PM 
    INFO: Bye!
    Jun 25, 2008 4:10:35 PM 
    INFO: ->

    This fragment shows "Bye!" output printed from the stop method of Activator.
  6. And finally uninstall the bundle as:

    uninstall 75
    Jun 25, 2008 4:10:42 PM 
    INFO: ->
So following this blog you can deploy any of your OSGi bundles in GlassFish v3.

Technorati: glassfish v3 osgi maven mavenbundleplugin
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
« March 2015
SunMonTueWedThuFriSat
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
    
       
Today