Wednesday May 05, 2010

TOTD #133: JPA2 (JPQL & Criteria), JavaDB, and embedded GlassFish - perfect recipe for testing

TOTD #132 explained how to use embedded GlassFish for deploying/testing a simple Servlet. As mentioned in that blog, this Tip Of The Day (TOTD) will extend that entry and show how to create a simple test that:

  • Creates a JDBC Connection Pool using GlassFish APIs
  • Creates a JDBC Resource using that Connection Pool, again programmatically
  • Persists and Queries an entity in that database using JPQL and the newly introduced Criteria APIs in JPA 2

This application uses a "Games" entity with two simple fields - "id" for the primary key and "name" for the name of a game. The test persists 3 entries in the database and then retrieves them by issuing a JPQL statement and Criteria API. There are four tests:

  • The first test consists of creating a JDBC Connection Pool & a JDBC Resource using that pool in the embedded GlassFish instance
  • The second test stores 3 entities in the database using the JDBC resource
  • The third test queries the database using JPQL
  • The fourth test queries the database using Criteria API

The entire source code is available here and "mvn test" is all you need to see the action. The updated directory structure from TOTD #132 is:

src
src/main
src/main/java
src/main/java/org
src/main/java/org/glassfish
src/main/java/org/glassfish/embedded
src/main/java/org/glassfish/embedded/samples
src/main/java/org/glassfish/embedded/samples/App.java
src/main/java/org/glassfish/embedded/samples/Games.java
src/main/resources
src/main/resources/META-INF
src/main/resources/META-INF/persistence.xml
src/test
src/test/java
src/test/java/org
src/test/java/org/glassfish
src/test/java/org/glassfish/embedded
src/test/java/org/glassfish/embedded/samples
src/test/java/org/glassfish/embedded/samples/AppTest.java

The newly added files are highlighted in the bold. "Games.java" is the new entity class and "persistence.xml" provides the definition of Persistence Unit.

Here is our simple entity class:

package org.glassfish.embedded.samples;

import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;

/\*\*
 \* @author arungupta
 \*/
@Entity
@Table
public class Games implements Serializable {
    @Id
    int id;

    @Column
    String name;

    public Games() { }

    public Games(int id, String name) {
        this.id = id;
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

Adding "@Entity" and "@Table" annotation on this POJO makes it an JPA Entity Bean. In addition, the primary key is defined using the "@Id" annotation on the field and an additional column is marked using "@Column"annotation.

In "AppTest.java", add a new method to create and test for JDBC connection pool and a JDBC resource using that pool as shown below:

public void testJDBCPoolAndResource() throws Throwable {
    Server.Builder builder = new Server.Builder("server");
    server = builder.build();
    server.createPort(8080);

    // add the required containers
    server.addContainer(ContainerBuilder.Type.web);
    server.addContainer(ContainerBuilder.Type.jpa);

    // Create a JDBC connection pool
    ParameterMap params = new ParameterMap();
    params.add("datasourceclassname", "org.apache.derby.jdbc.EmbeddedDataSource");
    params.add("property",
       "databaseName=games:connectionAttributes=\\\\;create\\\\=true");
    params.add("jdbc_connection_pool_id", JDBC_POOL);
    executeCommand("create-jdbc-connection-pool", server, params);
    System.out.println("JDBC Connection Pool successfully created.");

    // Assert the JDBC connection pool
    List<MessagePart> messageParts = 
        executeCommand("list-jdbc-connection-pools", server);
    assertInArray(messageParts, JDBC_POOL);

    // Create a JDBC resource
    System.out.println("Creating JDBC resource ...");
    ParameterMap params2 = new ParameterMap();
    params2.add("connectionpoolid", "MyPool");
    params2.add("jndi_name", JDBC_RESOURCE);
    executeCommand("create-jdbc-resource", server, params2);

    // Assert the JDBC resource
    messageParts = executeCommand("list-jdbc-resources", server);
    assertInArray(messageParts, JDBC_RESOURCE);
}

A disk representation of the database is created in the current directory by using "databaseName=games". Using in-memory JavaDB would've avoided the directory creation but facing issues with that (more on this at the end).

Here are convenience methods to execute an "asadmin"-equivalent command and used in the method above ...

private List executeCommand(String command, Server server) throws Throwable {
    return executeCommand(command, server, null);
}

private List executeCommand(String command, Server server, ParameterMap params) 
    throws Throwable {
    CommandRunner runner = server.getHabitat().getComponent(CommandRunner.class);
    ActionReport report = server.getHabitat().getComponent(ActionReport.class);
    if (params == null)
        runner.getCommandInvocation(command, report).execute();
    else
        runner.getCommandInvocation(command, report).parameters(params).execute();
    if (report.hasFailures()) {
        report.writeReport(System.out);
        throw report.getFailureCause();
    }

    return report.getTopMessagePart().getChildren();
}   

The error messages are shown on the console. Add another method for asserting on the created JDBC connection pool and resource as:

private void assertInArray(List messageParts, String resource) throws Throwable {
    boolean found = false;

    for (MessagePart part : messageParts) {
        if (part.getMessage().equals(resource)) {
            found = true;
            break;
        }
        System.out.println(part.getMessage());
    }

    if (!found)
        throw new Throwable("\\"" + resource + "\\" resource not found");
}

Here is a method to insert new values in the database using standard JPA calls:

public void testInsert() throws Throwable {
    EntityManagerFactory emf = 
        Persistence.createEntityManagerFactory("webtier2-PU");
    EntityManager em = emf.createEntityManager();

    // list of games to be added
    String[] games = {
               "Super Mario Galaxy",
               "Super Mario Brothers",
               "Mario Kart" };

    // create a transaction
    EntityTransaction utx = em.getTransaction();
    System.out.println("Persisting " + games.length + " games ...");
    utx.begin();
    for (int i=0; i<games.length; i++) {
        em.persist(new Games(i, games[i]));
        System.out.println("\\t " + games[i]);
    }
    utx.commit(); // and commit
    System.out.println("Committed.");
}

The method to query the database using JPQL ...

public void testJPQL() throws Throwable {
    EntityManagerFactory emf = 
        Persistence.createEntityManagerFactory("webtier2-PU");
    EntityManager em = emf.createEntityManager();

    // now query them
    List list = em.createQuery("select g from Games g").getResultList();
    assertEquals("Games retrieved", 3, list.size());
    System.out.println("Found " + list.size() + " games (using JPQL) ...");
    for (Object o : list) { // and dump
        System.out.println("\\t" + ((Games)o).getName());
    }
}

And finally a method to query the database using JPA 2 Critieria API ...

public void testCriteria() throws Throwable {
    EntityManagerFactory emf = 
        Persistence.createEntityManagerFactory("webtier2-PU");
    EntityManager em = emf.createEntityManager();

    CriteriaBuilder cb = emf.getCriteriaBuilder();
    CriteriaQuery<Games> criteria = cb.createQuery(Games.class);

    // FROM clause
    Root<Games> games = criteria.from(Games.class);

    // SELECT clause
    criteria.select(games);

    // No WHERE clause - pick all

    // FIRE
    List<Games> list = em.createQuery(criteria).getResultList();
    assertEquals("Games retrieved", 3, list.size());
    System.out.println("Found " + list.size() + " games (using Criteria) ...");
    for (Object o : list) { // and dump
       System.out.println("\\t" + ((Games)o).getName());
    }
 }

And here is the "persistence.xml"

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" 
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
       http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
   <persistence-unit name="webtier2-PU" transaction-type="JTA">
       <jta-data-source>jdbc/MyResource</jta-data-source>
       <properties>
           <property name="eclipselink.ddl-generation" value="drop-and-create-tables"/>
       </properties>
       <class>org.glassfish.embedded.samples.Games</class>
   </persistence-unit>
</persistence>

The Persistence Unit is referring to "jdbc/MyResource" JDBC Resource created earlier. The table creation strategy is "drop-and-create-tables" and this can be "create-tables" if in-memory JavaDB is used instead.

The version of "glassfish-embedded-all" dependency in "pom.xml" is changed from "3.0" to "3.1-SNAPSHOT" so that latest updates are picked. The updated dependency looks like:

<dependency>
   <groupId>org.glassfish.extras</groupId>
   <artifactId>glassfish-embedded-all</artifactId>
   <version>3.1-SNAPSHOT</version>
</dependency>

Change the source version of "maven-compiler-plugin" from "1.5" to "1.6", the updated entry looks like:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>2.0.2</version>
    <configuration>
       <source>1.6</source>
       <target>1.6</target>
    </configuration>
</plugin>


And now when you fire "mvn clean test", a test output is shown as ...

INFO: Instantiated an instance of org.hibernate.validator.engine.resolver.JPATraversableResolver.
[EL Info]: 2010-05-05 13:49:28.339--ServerSession(149074043)--file:/Users/arungupta/samples/v3/
embedded/webtier2/target/classes/_webtier2-PU login successful
Persisting 3 games ...
         Super Mario Galaxy
         Super Mario Brothers
         Mario Kart
Committed.
Found 3 games (using JPQL) ...
        Mario Kart
        Super Mario Galaxy
        Super Mario Brothers
Found 3 games (using Criteria) ...
        Mario Kart
        Super Mario Galaxy
        Super Mario Brothers

You may see the following exception during the test run:

May 5, 2010 1:49:24 PM com.sun.logging.LogDomains$1 log
SEVERE: loader.asurlclassloader_malformed_url
java.util.zip.ZipException: error in opening zip file
        at java.util.zip.ZipFile.open(Native Method)
        at java.util.zip.ZipFile.(ZipFile.java:114)
        at java.util.jar.JarFile.(JarFile.java:133)
        at java.util.jar.JarFile.(JarFile.java:97)

This occurs because no URL is specified in the connection properties. This error message can be ignored as sufficient information is available to resolve the database otherwise.

Using the in-memory JavaDB is causing some sort of race condition in the test path and throwing an exception at random runs. After trying the configuration on couple of Macs, Windows 7 and Ubuntu and still not able to detect the cause of randomness, no formal issue is logged yet but its still being followed with the required folks.

In the meanwhile, enjoy the power of embedded GlassFish with JPA and Java DB.

Technorati: totd glassfish v3 javaee embedded servlet jpa persistence javadb

Friday Apr 30, 2010

TOTD #132: Servlets 3.0 in Embedded GlassFish Reloaded - lightweight Java EE 6

This Tip Of The Day (TOTD) is a refresh of Embeddable GlassFish in Action - Servlet in a Maven Project.

GlassFish v3 runs easily in embedded mode - no download, installation, or configuration - every thing done programmatically within a JVM. This blog shows how to deploy a simple Servlet using these APIs and then write a simple test to invoke it - all within the same VM.

Lets get started!

  1. Lets create our Maven project:
    mvn archetype:create -DarchetypeGroupId=org.apache.maven.archetypes \\
    -DgroupId=org.glassfish.embedded.samples -DartifactId=webtier2
    
  2. Add the following <repository>, <dependency>, and <plugin> to the generated "pom.xml:
    <repositories>
      <repository>
        <id>glassfish-repository</id>
        <name>Java.net Repository for Glassfish</name>
        <url>http://download.java.net/maven/glassfish</url>
      </repository>
    </repositories>
    . . .
    <dependencies>
      . . .
      <dependency>
        <groupId>org.glassfish.extras</groupId>
        <artifactId>glassfish-embedded-all</artifactId>
        <version>3.0</version>
      </dependency>
    </dependencies>
    <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>
      </plugins>
    </build>
    

    Read Setting the Class Path for more discussions on the different JAR files that are available. The version may be changed form "3.0" to "3.1-SNAPSHOT" to pick the latest bug fixes and improvements.
  3. Change the generated "src/main/java/org/glassfish/embedded/samples/App.java" to:
    package org.glassfish.embedded.samples;
    
    import java.io.IOException;
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    /\*\*
     \* Hello world!
     \*/
    @WebServlet(name="app", urlPatterns={"/app"})
    public class App extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest request,
                HttpServletResponse response)
                throws ServletException, IOException {
            response.getWriter().println("Hello Duke");
        }
    }
    
    This is using "@WebServlet" annotation, a new feature in Servlets 3.0, to mark a POJO as a Servlet. Notice the servlet is hosted at "/app" URL. No "web.xml" will be required in this case.
  4. Edit the generated "src/test/java/org/glassfish/embedded/samples/AppTest.java" and add the following method:
    public void testServlet() throws IOException, LifecycleException {
        // Build a server
        Server.Builder builder = new Server.Builder("server");
        Server server = builder.build();
    
        // Specify the port
        server.createPort(8080);
    
        // Add the Web container
        server.addContainer(ContainerBuilder.Type.web);
    
        // Create the WAR file
        ScatteredArchive.Builder saBuilder = new ScatteredArchive.Builder("test",
                Collections.singleton(new File("target/classes").toURI().toURL()));
        ScatteredArchive archive = saBuilder.buildWar();
    
        // Deploy the WAR file
        EmbeddedDeployer deployer = server.getDeployer();
        deployer.deploy(archive, null);
    
        // Read the response from the servlet hosted at "/app"
        URL url = new URL("http://localhost:8080/test/app");
        BufferedReader br = new BufferedReader(
                new InputStreamReader(
                url.openConnection().getInputStream()));
    
        // ... and assert
        assertEquals("Hello Duke", br.readLine());
    }
    
    This method is well commented and where all the magic is happening.

    The updated import statements look like:
    import java.io.BufferedReader;
    import java.io.File;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.net.URL;
    import java.util.Collections;
    import junit.framework.Test;
    import junit.framework.TestCase;
    import junit.framework.TestSuite;
    import org.glassfish.api.deployment.DeployCommandParameters;
    import org.glassfish.api.embedded.ContainerBuilder;
    import org.glassfish.api.embedded.EmbeddedDeployer;
    import org.glassfish.api.embedded.LifecycleException;
    import org.glassfish.api.embedded.ScatteredArchive;
    import org.glassfish.api.embedded.Server;
    

  5. And now fire the following command:
    mvn test
    

    and see the output as:

    Running org.glassfish.embedded.samples.AppTest
    Apr 30, 2010 10:49:55 AM com.sun.enterprise.v3.server.AppServerStartup run
    INFO: GlassFish v3 (74.2) startup time : Embedded(498ms) startup services(433ms) total(931ms)
    Apr 30, 2010 10:49:55 AM com.sun.enterprise.transaction.JavaEETransactionManagerSimplified initDelegates
    INFO: Using com.sun.enterprise.transaction.jts.JavaEETransactionManagerJTSDelegate as the delegate
    Apr 30, 2010 10:49:55 AM org.glassfish.admin.mbeanserver.JMXStartupService$JMXConnectorsStarterThread run
    INFO: JMXStartupService: JMXConnector system is disabled, skipping.
    Apr 30, 2010 10:49:55 AM AppServerStartup run
    INFO: [Thread[GlassFish Kernel Main Thread,5,main]] started
    Apr 30, 2010 10:49:55 AM org.hibernate.validator.util.Version INFO: Hibernate Validator null
    Apr 30, 2010 10:49:55 AM org.hibernate.validator.engine.resolver.DefaultTraversableResolver detectJPA
    INFO: Instantiated an instance of org.hibernate.validator.engine.resolver.JPATraversableResolver.
    Apr 30, 2010 10:49:56 AM com.sun.enterprise.v3.services.impl.GrizzlyProxy$2$1 onReady
    INFO: Grizzly Framework 1.9.18-k started in: 154ms listening on port 8080
    Apr 30, 2010 10:50:00 AM com.sun.common.util.logging.LoggingConfigImpl openPropFile
    INFO: Cannot read logging.properties file. 
    Apr 30, 2010 10:50:00 AM com.sun.enterprise.web.WebContainer createHttpListener
    INFO: Created HTTP listener embedded-listener on port 8080
    Apr 30, 2010 10:50:00 AM com.sun.enterprise.web.WebContainer configureHttpServiceProperties
    WARNING: pewebcontainer.invalid_http_service_property
    Apr 30, 2010 10:50:00 AM com.sun.enterprise.web.WebContainer createHosts
    INFO: Created virtual server server
    Apr 30, 2010 10:50:00 AM com.sun.enterprise.web.WebContainer loadSystemDefaultWebModules
    INFO: Virtual server server loaded system default web module
    Apr 30, 2010 10:50:02 AM com.sun.enterprise.security.SecurityLifecycle INFO: security.secmgroff
    Apr 30, 2010 10:50:03 AM com.sun.enterprise.security.ssl.SSLUtils checkCertificateDates
    SEVERE: java_security.expired_certificate
    Apr 30, 2010 10:50:03 AM com.sun.enterprise.security.SecurityLifecycle onInitialization
    INFO: Security startup service called
    Apr 30, 2010 10:50:03 AM com.sun.enterprise.security.PolicyLoader loadPolicy
    INFO: policy.loading
    Apr 30, 2010 10:50:03 AM com.sun.enterprise.security.auth.realm.Realm doInstantiate
    INFO: Realm admin-realm of classtype com.sun.enterprise.security.auth.realm.file.FileRealm successfully created.
    Apr 30, 2010 10:50:03 AM com.sun.enterprise.security.auth.realm.Realm doInstantiate
    INFO: Realm file of classtype com.sun.enterprise.security.auth.realm.file.FileRealm successfully created.
    Apr 30, 2010 10:50:03 AM com.sun.enterprise.security.auth.realm.Realm doInstantiate
    INFO: Realm certificate of classtype com.sun.enterprise.security.auth.realm.certificate.CertificateRealm successfully created.
    Apr 30, 2010 10:50:03 AM com.sun.enterprise.security.SecurityLifecycle onInitialization
    INFO: Security service(s) started successfully....
    classLoader = WebappClassLoader (delegate=true; repositories=WEB-INF/classes/)
    SharedSecrets.getJavaNetAccess()=java.net.URLClassLoader$7@71e13a2c
    Apr 30, 2010 10:50:03 AM com.sun.enterprise.web.WebApplication start
    INFO: Loading application test at /test
    Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 9.845 sec
    
    Results :
    
    Tests run: 2, Failures: 0, Errors: 0, Skipped: 0
    

    The key messages in the log are highlighted in bold.

    As you can see embedded GlassFish started in less than a second ... neat! It also shows a message that HTTP listener is starting on port 8080. And finally the 2 tests passed - one is the default one generated by Maven and other is the new one that we added!

A future blog will show how to create JDBC resource using these APIs and use the JPA 2 APIs to query an in-memory database.

Alternatively, you can also use the Maven plug-in or EJB 3.1 Embeddable API. Always refer to the GlassFish v3 Embedded Server Guide for the definitive documentation. The latest javadocs are available here.

How are you using embeddable GlassFish ?

Technorati: totd glassfish v3 javaee embedded servlet

Tuesday Apr 13, 2010

TOTD #128: EJBContainer.createEJBContainer: Embedded EJB using GlassFish v3

This blog has been in my Drafts folder for quite some time now, needed some final tweaks, and finally pushing it out.

Chapter 22 of Enterprise JavaBeans 3.1 specification (released as part of Java EE 6) describes "Embeddable Usage" as:

Unlike traditional Java EE server-based execution, embeddable usage allows client code and its corresponding enterprise beans to run within the same JVM and class loader. This provides better support for testing, offline processing (e.g. batch), and the use of the EJB programming model in desktop applications.

Earlier blogs already described the steps in detail but I had to try this stuff myself :-) And moreover this Tip Of The Day (TOTD) shows, as always, complete detailed steps to get you going from scratch.

Lets see how such an embeddable EJB application can be easily created.

  1. Create a Maven project as:
    mvn archetype:create -DarchetypeGroupId=org.apache.maven.archetypes -DgroupId=org.glassfish.embedded.samples -DartifactId=ejb31
    
    
  2. Add the following fragments to "pom.xml" to ensure right set of JARs are pulled in:
    <repositories>
      <repository>
      <id>download.java.net</id>
      <name>Java.net Maven Repository</name>
      <url>http://download.java.net/maven/2</url>
      </repository>
    </repositories>
    . . .
    
    <dependency>
      <groupId>org.glassfish.extras</groupId>
      <artifactId>glassfish-embedded-all</artifactId>
      <version>3.0</version>
      <scope>compile</scope>
    </dependency>
    . . .
    
    <build>
      <defaultGoal>install</defaultGoal>
      <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>
      </plugins>
    </build>
    

  3. Change the generated "src/main/java/org/glassfish/embedded/samples/App.java" to:
    package org.glassfish.embedded.samples;
    
    import javax.ejb.Stateless;
    
    /\*\*
     \* Hello world!
     \*/
    @Stateless
    public class App {
        public static String sayHello(String name) {
            return "Hello " + name;
        }
    }
    

    This creates our trivial Enterprise JavaBean.
  4. Change the generated "src/test/java/org/glassfish/embedded/samples/AppTest.java" to (taking the code snippet from Adam's blog and slightly altering it):
    public void testEJB() throws NamingException {
            EJBContainer ejbC = EJBContainer.createEJBContainer();
    
            Context ctx = ejbC.getContext();
    
            App app = (App) ctx.lookup("java:global/classes/App");
    
            assertNotNull(app);
    
            String NAME = "Duke";
    
            String greeting = app.sayHello(NAME);
    
            assertNotNull(greeting);
    
            assertTrue(greeting.equals("Hello " + NAME));
    
            ejbC.close();
        }
    

    This is a simple test that looks up the bean using portable JNDI name, more explanation on JNDI name below.
  5. Run the tests by giving the following standard command in the Maven project:
    ~/samples/v3/embedded/ejb31 >mvn clean test
    [INFO] Scanning for projects...
    [INFO] ------------------------------------------------------------------------
    [INFO] Building ejb31
    [INFO]    task-segment: [clean, test]
    [INFO] ------------------------------------------------------------------------
    [INFO] [clean:clean {execution: default-clean}]
    [INFO] Deleting directory /Users/arungupta/samples/v3/embedded/ejb31/target
    
    . . .
    
    -------------------------------------------------------
     T E S T S
    -------------------------------------------------------
    Running org.glassfish.embedded.samples.AppTest
    Apr 9, 2010 3:48:16 PM org.glassfish.ejb.embedded.EJBContainerProviderImpl getValidFile
    SEVERE: ejb.embedded.location_not_exists
    Apr 9, 2010 3:48:19 PM com.sun.enterprise.v3.server.AppServerStartup run
    INFO: GlassFish v3 (74.2) startup time : Embedded(1180ms) startup services(1523ms) total(2703ms)
    Apr 9, 2010 3:48:20 PM com.sun.enterprise.transaction.JavaEETransactionManagerSimplified initDelegates
    INFO: Using com.sun.enterprise.transaction.jts.JavaEETransactionManagerJTSDelegate as the delegate
    Apr 9, 2010 3:48:21 PM org.glassfish.admin.mbeanserver.JMXStartupService$JMXConnectorsStarterThread run
    INFO: JMXStartupService: JMXConnector system is disabled, skipping.
    Apr 9, 2010 3:48:21 PM AppServerStartup run
    INFO: [Thread[GlassFish Kernel Main Thread,5,main]] started
    Apr 9, 2010 3:48:30 PM com.sun.enterprise.security.SecurityLifecycle INFO: security.secmgroff
    Apr 9, 2010 3:48:31 PM com.sun.enterprise.security.ssl.SSLUtils checkCertificateDates
    SEVERE: java_security.expired_certificate
    Apr 9, 2010 3:48:31 PM com.sun.enterprise.security.SecurityLifecycle onInitialization
    INFO: Security startup service called
    Apr 9, 2010 3:48:31 PM com.sun.enterprise.security.PolicyLoader loadPolicy
    INFO: policy.loading
    Apr 9, 2010 3:48:32 PM com.sun.enterprise.security.auth.realm.Realm doInstantiate
    INFO: Realm admin-realm of classtype com.sun.enterprise.security.auth.realm.file.FileRealm successfully created.
    Apr 9, 2010 3:48:32 PM com.sun.enterprise.security.auth.realm.Realm doInstantiate
    INFO: Realm file of classtype com.sun.enterprise.security.auth.realm.file.FileRealm successfully created.
    Apr 9, 2010 3:48:32 PM com.sun.enterprise.security.auth.realm.Realm doInstantiate
    INFO: Realm certificate of classtype com.sun.enterprise.security.auth.realm.certificate.CertificateRealm successfully created.
    Apr 9, 2010 3:48:32 PM com.sun.enterprise.security.SecurityLifecycle onInitialization
    INFO: Security service(s) started successfully....
    Apr 9, 2010 3:48:33 PM com.sun.ejb.containers.BaseContainer initializeHome
    INFO: Portable JNDI names for EJB App : [java:global/classes/App!org.glassfish.embedded.samples.App, java:global/classes/App]
    Apr 9, 2010 3:48:34 PM org.glassfish.admin.mbeanserver.JMXStartupService shutdown
    INFO: JMXStartupService and JMXConnectors have been shut down.
    Apr 9, 2010 3:48:34 PM com.sun.enterprise.v3.server.AppServerStartup stop
    INFO: Shutdown procedure finished
    Apr 9, 2010 3:48:34 PM AppServerStartup run
    INFO: [Thread[GlassFish Kernel Main Thread,5,main]] exiting
    Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 18.61 sec
    
    Results :
    
    Tests run: 2, Failures: 0, Errors: 0, Skipped: 0
    
    
    
    The key log messages are highlighted in bold and are described:
    1.  "mvn clean test" builds the project and runs the test.
    2. The server started in under 3 seconds, 2703 ms to be precise.
    3. The portable JNDI name for the EJB is "java:global/classes/App" (convenience name for a bean with one view) and the fully-qualified notation is "java:global/classes/App!org.glassfish.embedded.samples.App". The convenience name is constructed in the "global" namespace + the unqualified name of the directory + bean name. The later is created by adding the fully-qualified name of the interface to the former.
    4. The server shuts down after the tests are run, shows that 2 tests (one default + one newly added) ran, and both passed.

So no explicit GlassFish downloading and/or configuring, just deployed a simple EJB, and ran the tests - everything within one VM.

A future blog will show how to add other Java EE functionality to this app.

Technorati: totd embedded ejb glassfish javaee v3

Monday Apr 12, 2010

TOTD #127: Embedding GlassFish in an existing OSGi runtime - Eclipse Equinox

GlassFish has a modular architecture based upon OSGi and bundles Apache Felix as the OSGi runtime. TOTD #103 explains how to run GlassFish with two other OSGi runtimes (Equinox and Knopflerfish). However you may already have an OSGi runtime in your environment and like to run GlassFish within it. Sahoo blogged about how to embed GlassFish in Equinox.

This Tip Of The Day (TOTD) provides complete set of steps with Equinox and the different download options.

  1. There are two download options for Equinox - SDK or Framework. The framework is an easier option to start with as its just a single JAR. So create a top-level directory as "equinox-3.5.2" and download the latest framework JAR from here. Complete details about the starting and configuring the framework are described here.
  2. Start the framework and check its status as:
    ~/tools/equinox-3.5.2 >java -jar org.eclipse.osgi_3.5.2.R35x_v20100126.jar -console
    
    osgi> ss
    
    Framework is launched.
    
    id State Bundle
    0 ACTIVE org.eclipse.osgi_3.5.2.R35x_v20100126
    
    
    Notice only one bundle, i.e. Equinox main bundle, is currently active.
  3. Download and unzip the latest GlassFish 3.1 nightly build.
  4. Shutdown the framework by typing "exit" on the console or Ctrl+C. Copy "glassfish/osgi/equinox/configuration/config.ini" to "equinox-3.5.2/configuration" directory. This is required because the version number of some packages exported by JRE is not uniform across frameworks. This will hopefully be fixed in future versions of the frameworks.
  5. Sahoo's blog describes an OSGi bundle that controls the lifecycle of GlassFish. Download and unzip the OSGi bundle's Maven project.
  6. Edit "src/main/java/sahoo/embeddedgf/GFActivator.java" file and change the value of "installRoot" and "instanceRoot" on line 73 and 74 to match the location of your GlassFish install. Build the bundle as:
    mvn package
    

    which generates "target/embeddedgf-1.0-SNAPSHOT.jar". The bundle performs three tasks:
    1. Install all the bundles from "glassfish/modules" directory.
    2. Creates a configuration with "com.sun.aas.installRoot" and "com.sun.aas.instanceRoot" properties.
    3. Starts the main GlassFish bundle.
  7. Start the framework again, install the bundle, and check its status as:
    osgi> install file:///Users/arungupta/samples/v3/osgi/embeddedgf/target/embeddedgf-1.0-SNAPSHOT.jar
    Bundle id is 1
    
    osgi> ss
    
    Framework is launched.
    
    id      State       Bundle
    0       ACTIVE      org.eclipse.osgi_3.5.2.R35x_v20100126
    1       INSTALLED   sahoo.embeddedgf_1.0.0.SNAPSHOT
    

    Now GlassFish bundle is installed but not started. Optionally, the framework may be started with "-clean" switch that clears out the cache and starts with a clean slate.
  8. Start the newly installed bundle and see the log messages as:
    osgi> start 1
    
    osgi> [#|2010-04-10T10:46:04.616-0700|INFO|glassfishv3.0|com.sun.grizzly.config.GrizzlyServiceListener|_ThreadID=10;_ThreadName=Configuration Updater;|Perform lazy SSL initialization for the listener 'http-listener-2'|#]
    
    [#|2010-04-10T10:46:04.700-0700|INFO|glassfishv3.0|null|_ThreadID=11;_ThreadName=Thread-13;|Grizzly Framework 1.9.19-beta1 started in: 26ms listening on port 4848|#]
    
    [#|2010-04-10T10:46:04.700-0700|INFO|glassfishv3.0|null|_ThreadID=12;_ThreadName=Thread-9;|Grizzly Framework 1.9.19-beta1 started in: 50ms listening on port 8181|#]
    
    [#|2010-04-10T10:46:04.709-0700|INFO|glassfishv3.0|null|_ThreadID=13;_ThreadName=Thread-8;|Grizzly Framework 1.9.19-beta1 started in: 135ms listening on port 8080|#]
    
    . . .
    
    [#|2010-04-10T10:46:11.625-0700|INFO|glassfishv3.0|null|_ThreadID=21;_ThreadName={felix.fileinstall.poll=5000, felix.fileinstall.bundles.new.start=true, service.pid=org.apache.felix.fileinstall.76a03b47-814c-4359-ad37-f5d12e752a6f, felix.fileinstall.dir=/Users/arungupta/tools/glassfish/3.1/apr9/glassfishv3/glassfish/domains/domain1/autodeploy/bundles/, felix.fileinstall.filename=org.apache.felix.fileinstall-autodeploy-bundles.cfg, service.factorypid=org.apache.felix.fileinstall, felix.fileinstall.debug=1};|{felix.fileinstall.poll (ms) = 5000, felix.fileinstall.dir = /Users/arungupta/tools/glassfish/3.1/apr9/glassfishv3/glassfish/domains/domain1/autodeploy/bundles, felix.fileinstall.debug = 1, felix.fileinstall.bundles.new.start = true, felix.fileinstall.tmpdir = /var/folders/+E/+E6YtSvGGEKNwOA77I-9Fk+++TI/-Tmp-/fileinstall--1798045578591636699, felix.fileinstall.filter = null}|#]
    
  9. Check the status of installed bundle as:
    osgi> ss
    
    Framework is launched.
    
    id      State       Bundle
    0       ACTIVE      org.eclipse.osgi_3.5.2.R35x_v20100126
                        Fragments=89, 106, 109
    1       ACTIVE      sahoo.embeddedgf_1.0.0.SNAPSHOT
    2       RESOLVED    org.glassfish.appclient.acc-config_3.1.0.SNAPSHOT
    3       RESOLVED    org.glassfish.admin.cli_3.1.0.SNAPSHOT
    4       RESOLVED    org.glassfish.admin.core_3.1.0.SNAPSHOT
    5       RESOLVED    org.glassfish.admin.util_3.1.0.SNAPSHOT
    
    . . .
    
    220     ACTIVE      org.glassfish.web.weld-integration_3.1.0.SNAPSHOT
    221     RESOLVED    org.jboss.weld.osgi-bundle_1.0.1.SP1
    222     RESOLVED    com.ctc.wstx_0.0.0
    223     RESOLVED    org.glassfish.connectors.work-management_3.1.0.SNAPSHOT
    
    osgi>
    

    So now all the GlassFish modules are installed and the required ones are started. "http://localhost:8080" shows the default web page and "asadmin" can be used to issue the standard commands.

If you downloaded Eclipsed SDK, then the framework needs to be started as:

java -jar plugins/org.eclipse.osgi_3.5.2.R35x_v20100126.jar -console

and the configuration file needs to be copied to "plugins/configuration" directory.

A future blog will show how to run GlassFish inside Eclipse as an RCP, however this requires issue #11782 to be fixed.

There are several other OSGi entries on this blog or on Sahoo's blog.

How are you using GlassFish's OSGi capabilities ?

Technorati: glassfish osgi embedded eclipse equinox

Wednesday Mar 18, 2009

TOTD #75: Getting Started with Grails using GlassFish v3 Embedded


For a change, this blog entry is talking about something that exists for a while now :)

Basically, I wanted to setup a demo environment for Grails and GlassFish v3 Prelude on my machine and so decided to dcument the steps along the process. More detailed steps with explanation are available on GlassFish/Grails Getting Started Wiki.
  1. Download and unzip GlassFish v3 Prelude.
  2. Run GlassFish Update Center to install the Grails module as shown:

    ~/demos/glassfishv3-prelude >./bin/updatetool

    The software needed for this command (updatetool) is not installed.

    If you choose to install Update Tool, your system will be automatically
    configured to periodically check for software updates. If you would like
    to configure the tool to not check for updates, you can override the
    default behavior via the tool's Preferences facility.

    When this tool interacts with package repositories, some system information
    such as your system's IP address and operating system type and version
    is sent to the repository server. For more information please see:

    http://wiki.updatecenter.java.net/Wiki.jsp?page=UsageMetricsUC2

    Once installation is complete you may re-run this command.

    Would you like to install Update Tool now (y/n): y

    Install image: /Users/arungupta/demos/glassfishv3-prelude/bin/..
    Installing pkg packages.
    Installing: [pkg:/pkg@1.0.7,0-15.1269:20081008T212532Z, pkg:/python2.4-minimal@2.4.5.0,0-15.1269:20081008T212544Z]
    Installing updatetool packages.
    Installing: [pkg:/updatetool@2.0.0,0-15.1269:20081008T212613Z, pkg:/wxpython2.8-minimal@2.8.8,0-15.1269:20081008T212630Z]
    Registering notifier: Already registered.
    Initialization complete.

    Software successfully installed. You may now re-run this command (updatetool).
  3. Now run the Update Center again to see a screen as shown below:


  4. Select "GlassFish support for Grails Framework" and click on "Install" to install the module locally. This creates a new directory "grails" in your GlassFish v3 Prelude directory and install Grails 1.0.4 there.
  5. Set environment variables as:

    ~/demos/glassfishv3-prelude/glassfish/grails >export GRAILS_HOME=~/demos/glassfishv3-prelude/glassfish/grails
    ~/demos/glassfishv3-prelude/glassfish/grails >export PATH=$GRAILS_HOME/bin:$PATH

  6. Create a template application as:

    ~/demos/glassfishv3-prelude/glassfish/grails/samples >grails create-app bookstore

    Welcome to Grails 1.0.4 - http://grails.org/
    Licensed under Apache Standard License 2.0
    Grails home is set to: /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails

    Base Directory: /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples
    Note: No plugin scripts found
    Running script /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/scripts/CreateApp.groovy
    Environment set to development
        [mkdir] Created dir: /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore/src
        [mkdir] Created dir: /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore/src/java
        [mkdir] Created dir: /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore/src/groovy
        [mkdir] Created dir: /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore/grails-app
        [mkdir] Created dir: /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore/grails-app/controllers
        [mkdir] Created dir: /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore/grails-app/services
        [mkdir] Created dir: /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore/grails-app/domain
        [mkdir] Created dir: /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore/grails-app/taglib
        [mkdir] Created dir: /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore/grails-app/utils
        [mkdir] Created dir: /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore/grails-app/views
        [mkdir] Created dir: /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore/grails-app/views/layouts
        [mkdir] Created dir: /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore/grails-app/i18n
        [mkdir] Created dir: /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore/grails-app/conf
        [mkdir] Created dir: /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore/test
        [mkdir] Created dir: /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore/test/unit
        [mkdir] Created dir: /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore/test/integration
        [mkdir] Created dir: /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore/scripts
        [mkdir] Created dir: /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore/web-app
        [mkdir] Created dir: /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore/web-app/js
        [mkdir] Created dir: /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore/web-app/css
        [mkdir] Created dir: /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore/web-app/images
        [mkdir] Created dir: /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore/web-app/META-INF
        [mkdir] Created dir: /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore/lib
        [mkdir] Created dir: /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore/grails-app/conf/spring
        [mkdir] Created dir: /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore/grails-app/conf/hibernate
    [propertyfile] Creating new property file: /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore/application.properties
         [copy] Copying 2 files to /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore
         [copy] Copied 1 empty directory to 1 empty directory under /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore
         [copy] Copying 2 files to /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore/web-app/WEB-INF
         [copy] Copying 5 files to /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore/web-app/WEB-INF/tld
         [copy] Copying 28 files to /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore/web-app
         [copy] Copying 18 files to /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore/grails-app
         [copy] Copying 1 file to /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore
         [copy] Copying 1 file to /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore
         [copy] Copying 1 file to /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore
         [copy] Copying 1 file to /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore
    [propertyfile] Updating property file: /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore/application.properties
    Created Grails Application at /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore

  7. Create a domain specific class as:

    ~/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore >grails create-domain-class book

    Welcome to Grails 1.0.4 - http://grails.org/
    Licensed under Apache Standard License 2.0
    Grails home is set to: /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails

    Base Directory: /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore
    Note: No plugin scripts found
    Running script /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/scripts/CreateDomainClass.groovy
    Environment set to development
         [copy] Copying 1 file to /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore/grails-app/domain
    Created Domain Class for Book
         [copy] Copying 1 file to /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore/test/integration
    Created Tests for Book

  8. Add attributes to the domain class by editing "grails-app/domain/Book.groovy" such that it looks like:

    class Book {
      String title
      String author
    }

  9. Create a new controller as:

    ~/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore >grails create-controller Book

    Welcome to Grails 1.0.4 - http://grails.org/
    Licensed under Apache Standard License 2.0
    Grails home is set to: /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails

    Base Directory: /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore
    Note: No plugin scripts found
    Running script /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/scripts/CreateController.groovy
    Environment set to development
         [copy] Copying 1 file to /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore/grails-app/controllers
    Created Controller for Book
        [mkdir] Created dir: /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore/grails-app/views/book
         [copy] Copying 1 file to /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore/test/integration
    Created ControllerTests for Book
  10. Edit the generated controller in "grails-app/controller/BookController.groovy" to specify scaffold for the domain class. It looks like:

    class BookController {
        def scaffold = Book
    }
  11. Run the app as shown below:

    ~/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore >grails run-app

    Welcome to Grails 1.0.4 - http://grails.org/
    Licensed under Apache Standard License 2.0
    Grails home is set to: /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails

    Base Directory: /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore
    Note: No plugin scripts found
    Running script /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/scripts/RunApp.groovy
    Environment set to development
    Starting GlassFish embedded server...    [mkdir] Created dir: /Users/arungupta/.grails/1.0.4/projects/bookstore/classes
      [groovyc] Compiling 8 source files to /Users/arungupta/.grails/1.0.4/projects/bookstore/classes
        [mkdir] Created dir: /Users/arungupta/.grails/1.0.4/projects/bookstore/resources/grails-app/i18n
    [native2ascii] Converting 11 files from /Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore/grails-app/i18n to /Users/arungupta/.grails/1.0.4/projects/bookstore/resources/grails-app/i18n
         [copy] Copying 1 file to /Users/arungupta/.grails/1.0.4/projects/bookstore/classes
         [copy] Copying 1 file to /Users/arungupta/.grails/1.0.4/projects/bookstore/resources
         [copy] Copying 1 file to /Users/arungupta/.grails/1.0.4/projects/bookstore
    Running Grails application..
    Application name : bookstore
    Web App Root :/Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore/web-app
    web.xml:/Users/arungupta/.grails/1.0.4/projects/bookstore/resources/web.xml
    Mar 18, 2009 10:19:09 PM CommonClassLoaderManager Skipping creation of CommonClassLoader as there are no libraries available
    INFO: urls = []
    no resource bundle found for version, using default GlassFish version
    Mar 18, 2009 10:19:09 PM AppServerStartup run
    INFO: [Thread[GlassFish Kernel Main Thread,5,main]] started
    Mar 18, 2009 10:19:09 PM com.sun.enterprise.v3.services.impl.GrizzlyProxy start
    INFO: Listening on port 8080
    Mar 18, 2009 10:19:10 PM org.glassfish.admin.mbeanserver.ConnectorStartupService$ConnectorsStarterThread startConnector
    INFO: Started JMXConnector, JMXService URL = service:jmx:rmi:///jndi/rmi://192.168.1.145:8686/jmxrmi
    Mar 18, 2009 10:19:10 PM com.sun.enterprise.v3.admin.adapter.AdminEndpointDecider setGuiContextRoot
    INFO: Admin Console Adapter: context root: /admin
    Mar 18, 2009 10:19:10 PM com.sun.enterprise.v3.server.AppServerStartup run
    INFO: GlassFish v3 Prelude startup time : Embedded(418ms) startup services(887ms) total(1305ms)
    Mar 18, 2009 10:19:10 PM com.sun.enterprise.web.WebContainer createHttpListener
    INFO: Created HTTP listener http-listener-1 on port 8080
    Mar 18, 2009 10:19:10 PM com.sun.enterprise.web.WebContainer createHosts
    INFO: Created virtual server server
    Mar 18, 2009 10:19:11 PM org.apache.catalina.loader.WebappLoader setClassPath
    INFO: Unknown loader org.glassfish.grails.MaskingClassLoader@3b948e75 class org.glassfish.grails.MaskingClassLoader
    Mar 18, 2009 10:19:12 PM org.apache.catalina.loader.WebappLoader setClassPath
    INFO: Unknown loader org.glassfish.internal.api.DelegatingClassLoader@191fa2af class org.glassfish.internal.api.DelegatingClassLoader
    Mar 18, 2009 10:19:12 PM org.apache.catalina.core.ApplicationContext log
    INFO: PWC1412: WebModule[/bookstore] ServletContext.log():Set web app root system property: 'bookstore-development-0.1' = [/Users/arungupta/demos/glassfishv3-prelude/glassfish/grails/samples/bookstore/web-app/]
    Mar 18, 2009 10:19:12 PM org.apache.catalina.core.ApplicationContext log
    INFO: PWC1412: WebModule[/bookstore] ServletContext.log():Initializing log4j from [file:/Users/arungupta/.grails/1.0.4/projects/bookstore/resources/log4j.properties]
    Mar 18, 2009 10:19:12 PM org.apache.catalina.core.ApplicationContext log
    INFO: PWC1412: WebModule[/bookstore] ServletContext.log():Initializing Spring root WebApplicationContext
    [0] spring.GrailsWebApplicationContext Refreshing org.codehaus.groovy.grails.commons.spring.GrailsWebApplicationContext@430b4506: display name [org.codehaus.groovy.grails.commons.spring.GrailsWebApplicationContext@430b4506]; startup date [Wed Mar 18 22:19:14 PDT 2009]; parent: org.springframework.web.context.support.XmlWebApplicationContext@6ceb51a8
    [0] spring.GrailsWebApplicationContext Bean factory for application context [org.codehaus.groovy.grails.commons.spring.GrailsWebApplicationContext@430b4506]: org.springframework.beans.factory.support.DefaultListableBeanFactory@1f43243e
    Mar 18, 2009 10:19:17 PM org.apache.catalina.core.ApplicationContext log
    INFO: PWC1412: WebModule[/bookstore] ServletContext.log():Initializing Spring FrameworkServlet 'grails'
    Mar 18, 2009 10:19:17 PM com.sun.enterprise.web.WebApplication start
    INFO: Loading application bookstore at /bookstore
    Server running. Browse to http://localhost:8080/bookstore

    Notice, here GlassFish v3 Embedded Server is used for running the application. It is now accessible at "http://localhost:8080/bookstore" and looks like:



  12. Clicking on the "BookController" shows:


  13. Click on "New Book" to add a new book as:

  14. Each entry can be updated/deleted after clicking on "Create" ...



    or "Book List" as shown below:



In a matter of few minutes, we created a simple Grails scaffold that runs using GlassFish v3 Embedded Server.

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

Technorati: totd glassfish v3 grails embedded prelude

Tuesday Jul 29, 2008

Grails on GlassFish v3 - Embedded or Stand-alone


Grails 1.0.3 was released a few weeks ago. This blog uses the instructions originally posted here and shows how to deploy a simple Grails application on GlassFish.
  1. Download Grails 1.0.3 and unzip.
  2. Download the latest \*-overlay.zip from here and unzip on your Grails installation as shown:

    ~/tools/grails-1.0.3 >unzip ~/Downloads/grails-gfv3-1.1-overlay.zip
    Archive:  /Users/arungupta/Downloads/grails-gfv3-1.1-overlay.zip
       creating: lib/glassfish-v3/
      inflating: lib/glassfish-v3/gf-embedded-api-1.0-alpha-4.jar 
      inflating: lib/glassfish-v3/web-all-10.0-build-20080430.jar 
      inflating: lib/grails-gfv3-1.1.jar 
      inflating: scripts/RunAppGf.groovy
  3. Create a sample app as explained in Getting Started With Grails on GlassFish.
  4. Run the app using embedded GlassFish as:

    ~/tools/grails-1.0.3/samples/helloworld >grails run-app-gf

    Welcome to Grails 1.0.3 - http://grails.org/
    Licensed under Apache Standard License 2.0
    Grails home is set to: /Users/arungupta/tools/grails-1.0.3

    Base Directory: /Users/arungupta/tools/grails-1.0.3/samples/helloworld
    Note: No plugin scripts found
    Running script /Users/arungupta/tools/grails-1.0.3/scripts/RunAppGf.groovy
    Environment set to development
    Starting GlassFish embedded server...     [copy] Copying 1 file to /Users/arungupta/.grails/1.0.3/projects/helloworld
    Running Grails application..
    Application name : helloworld
    Web App Root :/Users/arungupta/tools/grails-1.0.3/samples/helloworld/web-app
    web.xml:/Users/arungupta/.grails/1.0.3/projects/helloworld/resources/web.xml
    Jul 28, 2008 2:25:38 PM com.sun.enterprise.v3.server.AppServerStartup run
    INFO: HK2 initialized in 620 ms
    Jul 28, 2008 2:25:38 PM com.sun.enterprise.v3.server.AppServerStartup run
    INFO: com.sun.enterprise.naming.impl.ServicesHookup@2aef3499 Init done in 646 ms
    Jul 28, 2008 2:25:38 PM com.sun.enterprise.v3.server.AppServerStartup run
    INFO: com.sun.enterprise.v3.server.Globals@3710f32d Init done in 648 ms
    Jul 28, 2008 2:25:38 PM com.sun.enterprise.v3.server.AppServerStartup run
    INFO: com.sun.enterprise.v3.server.SystemTasks@632dc291 Init done in 655 ms
    Jul 28, 2008 2:25:38 PM com.sun.enterprise.v3.server.AppServerStartup run
    INFO: com.sun.enterprise.v3.services.impl.HouseKeeper@64c3d9c0 Init done in 658 ms
    Jul 28, 2008 2:25:38 PM com.sun.enterprise.v3.server.AppServerStartup run
    INFO: com.sun.enterprise.v3.services.impl.CmdLineParamProcessor@3a151d3b Init done in 664 ms
    JMXMP connector server URL = service:jmx:jmxmp://localhost:8888
    Jul 28, 2008 2:25:39 PM com.sun.enterprise.v3.services.impl.GrizzlyProxy start
    INFO: Listening on port 8080
    Jul 28, 2008 2:25:39 PM com.sun.enterprise.v3.server.AppServerStartup run
    INFO: com.sun.enterprise.v3.services.impl.GrizzlyService@2ddd5c89 startup done in 1059 ms
    Jul 28, 2008 2:25:39 PM com.sun.enterprise.v3.services.impl.ApplicationLoaderService postConstruct
    INFO: loader service postConstruct started at 1217280339578
    Jul 28, 2008 2:25:39 PM com.sun.enterprise.v3.server.AppServerStartup run
    INFO: Application Loader startup done in 1353 ms
    Jul 28, 2008 2:25:39 PM com.sun.enterprise.v3.server.AppServerStartup run
    INFO: Glassfish v3 started in 1355 ms
    Jul 28, 2008 2:25:41 PM org.apache.catalina.loader.WebappLoader setClassPath
    INFO: Unknown loader org.glassfish.grails.MaskingClassLoader@5cbde5b4 class org.glassfish.grails.MaskingClassLoader
    Jul 28, 2008 2:25:41 PM com.sun.enterprise.web.WebModuleContextConfig authenticatorConfig
    SEVERE: webModuleContextConfig.missingRealm
    [0] spring.GrailsWebApplicationContext Refreshing org.codehaus.groovy.grails.commons.spring.GrailsWebApplicationContext@4c721585: display name [org.codehaus.groovy.grails.commons.spring.GrailsWebApplicationContext@4c721585]; startup date [Mon Jul 28 14:25:44 PDT 2008]; parent: org.springframework.web.context.support.XmlWebApplicationContext@631a8160
    [0] spring.GrailsWebApplicationContext Bean factory for application context [org.codehaus.groovy.grails.commons.spring.GrailsWebApplicationContext@4c721585]: org.springframework.beans.factory.support.DefaultListableBeanFactory@3e11bc1d
    Server running. Browse to http://localhost:8080/helloworld

  5. Browsing to "http://localhost:8080/helloworld" shows:


  6. Create a controller

    ~/tools/grails-1.0.3/samples/helloworld >grails create-controller home

    Welcome to Grails 1.0.3 - http://grails.org/
    Licensed under Apache Standard License 2.0
    Grails home is set to: /Users/arungupta/tools/grails-1.0.3

    Base Directory: /Users/arungupta/tools/grails-1.0.3/samples/helloworld
    Note: No plugin scripts found
    Running script /Users/arungupta/tools/grails-1.0.3/scripts/CreateController.groovy
    Environment set to development
         [copy] Copying 1 file to /Users/arungupta/tools/grails-1.0.3/samples/helloworld/grails-app/controllers
    Created Controller for Home
        [mkdir] Created dir: /Users/arungupta/tools/grails-1.0.3/samples/helloworld/grails-app/views/home
         [copy] Copying 1 file to /Users/arungupta/tools/grails-1.0.3/samples/helloworld/test/integration
    Created ControllerTests for Home
  7. Edit the generated controller in "grails-app/controllers/HomeController.groovy" such that it looks like:

    class HomeController {

        def index = {
            render "Grails using embedded GlassFish!"
        }
    }
  8. Refresh the web page in the browser and it looks like:



    and clicking on "HomeController" shows the output as:

More details about GlassFish embedding in Grails are available here.

This application can also be deployed on stand-alone GlassFish v3 Technology Preview 2 as explained here. This blog explains how to configure JNDI resources for a Grails application and I plan to explore that in upcoming days.

Once the Servlet engine in Grails is made configurable then GlassFish can be used as the target deployment platform from "run-app" script.

NetBeans 6.5 M1 provide extensive support on Grails application development - details are available here.

Technorati: grails glassfish v3 embedded netbeans

Wednesday May 21, 2008

Embeddable GlassFish in Action - Servlet in a Maven project

Kohsuke announced the embedability of GlassFish v3 - this is really cool! Now you can run GlassFish inside an existing JVM, without the need to start it externally. The API javadocs are available here. This blog explains how to host a Servlet using these APIs and write a simple Maven test to invoke the Servlet - all within the same VM.

The blog creates a Maven project using NetBeans but Maven CLI can be used as well.

In the NetBeans IDE, if Maven plugin is not already installed, then install it using "Tools", "Plugins","Available Plugins".
  1. Create a new Maven project
    1. Create a new project in NetBeans IDE and select "Maven" types as shown below



      Click on "Next >".
    2. Take the default "Archetype" as shown:



      Click on "Next >".
    3. Enter the "Project Name" and "Artifact Id" as shown below:



      and click on "Finish". The following output is shown in NetBeans Output window:



      This confirms the successful creation of the project.

      The command-line equivalent for all the above steps is:

      mvn archetype:create -DarchetypeGroupId=org.apache.maven.archetypes -DgroupId=org.glassfish.embedded.samples -DartifactId=webtier
  2. Update pom.xml with repositories & dependencies
    1. Expand "Project Files" and open "pom.xml". Add the following repositories (right after <url>...</url> tags)

      <repositories>
          <repository>
            <id>glassfish-repository</id>
            <name>Java.net Repository for Glassfish</name>
            <url>http://download.java.net/maven/glassfish</url>
          </repository>
          <repository>
            <id>download.java.net</id>
            <name>Java.net Maven Repository</name>
            <url>http://download.java.net/maven/2</url>
          </repository>
        </repositories>
    2. Add the following fragment after "<repositories>" to set the target JDK as 1.5:

      <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>
         </plugins>
       </build>
    3. Add the following dependencies (inside "<dependencies>" and after "</dependency>")

      <dependency>
            <groupId>org.glassfish.distributions</groupId>
            <artifactId>web-all</artifactId>
            <version>10.0-build-20080430</version>
          </dependency>
          <dependency>
            <groupId>org.glassfish.embedded</groupId>
            <artifactId>gf-embedded-api</artifactId>
            <version>1.0-alpha-4</version>
          </dependency>
  3. Add Servlet class
    1. Right-click on "Source packages", select "New", "Java Class..." and enter the value as shown below



      and click on "Finish".
    2. Replace the template class with the following Servlet

      package org.glassfish.embedded.samples.webtier;

      import java.io.IOException;
      import java.io.PrintWriter;
      import javax.servlet.ServletException;
      import javax.servlet.http.HttpServlet;
      import javax.servlet.http.HttpServletRequest;
      import javax.servlet.http.HttpServletResponse;

      /\*\*
       \* @author Arun Gupta
       \*/
      public class SimpleServlet extends HttpServlet {

          @Override
          protected void doGet(HttpServletRequest request,
                  HttpServletResponse response)
                  throws ServletException, IOException {
              PrintWriter out = response.getWriter();
              out.println("Wow, I'm embedded!");
          }
      }

      This is a simple Servlet class.
  4. Add deployment descriptor (this step could be made optional with possibly a default mapping)
    1. In the "Files" window, expand "src", "main", right-click and select "New", "Folder..." as shown below ...



      and give the folder name as "resources" as shown ...



      ... click on "Finish".
    2. Using the same mechanism, create a new folder "WEB-INF" in "resources". Right-click on "WEB-INF" and select "New", "XML Document..." as shown:

    3. Enter the name as "web" as shown


    4. Click on "Next >", take defaults and click on "Finish". Replace the content of generated "web.xml" with the following ...

      <?xml version="1.0" encoding="UTF-8"?>
      <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
          <servlet>
              <servlet-name>SimpleServlet</servlet-name>
              <servlet-class>org.glassfish.embedded.samples.webtier.SimpleServlet</servlet-class>
          </servlet>
          <servlet-mapping>
              <servlet-name>SimpleServlet</servlet-name>
              <url-pattern>/SimpleServlet</url-pattern>
          </servlet-mapping>
      </web-app>

  5. Add a new test to invoke the Servlet
    1. In "Projects", expand "Test Packages" and open "org.glassfish.embedded.samples.webtier.AppTest" as shown:

    2. Add the following fragment at end of the class:

          private final String NAME = "AppTest";

          public void testServlet() throws Exception {
              int port = 9999;
              GlassFish glassfish = newGlassFish(port);
              URL url = new URL("http://localhost:" + port + "/" + NAME + "/SimpleServlet");
              BufferedReader br = new BufferedReader(
                      new InputStreamReader(
                      url.openConnection().getInputStream()));
              assertEquals("Wow, I'm embedded!", br.readLine());
              glassfish.stop();
          }

          private GlassFish newGlassFish(int port) throws Exception {
              GlassFish glassfish = new GlassFish(port);
              ScatteredWar war = new ScatteredWar(NAME,
                      new File("src/main/resources"),
                      new File("src/main/resources/WEB-INF/web.xml"),
                      Collections.singleton(new File("target/classes").toURI().toURL()));
              glassfish.deploy(war);
              System.out.println("Ready ...");
              return glassfish;
          }
    3. Right-click in the editor window and select "Fix Imports" as shown


    4. Take all the defaults as shown



      and click on "OK".
    5. The complete project structure looks like:

  6. Run the Test (mvn test)
    1. In Projects window, right-click the project and select "Test" as shown:

    2. The Output window shows the result as:



      Notice how GlassFish v3 started in 598 milliseconds (around 0.5 sec) and all the tests passed.
This is a work in progress and we would like to hear your feedback at users@glassfish and GlassFish Forum.

How are you using GlassFish embeddability ?

Technorati: glassfish v3 embedded servlet netbeans
About

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


Java EE 7 Samples

Stay Connected

Search

Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today