Miles to go …

April 30, 2010

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

Filed under: General — arungupta @ 11:25 am

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

Share and Enjoy:
  • Print
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • DZone
  • StumbleUpon
  • Technorati
  • Twitter
  • Slashdot
Related posts:
  1. TOTD #128: EJBContainer.createEJBContainer: Embedded EJB using GlassFish v3
  2. Oracle at Jazoon 2010 – Java SE, Java FX, Java EE 6, GlassFish, JPA 2.0, JSF 2, Servlets 3.0, OSGi, Cloud, HTML 5, Open DS, …
  3. TOTD #120: Deployment Descriptor-free Java EE 6 application using JSF 2.0 + EJB 3.1 + Servlets 3.0
  4. TOTD #133: JPA2 (JPQL & Criteria), JavaDB, and embedded GlassFish – perfect recipe for testing
  5. TOTD #139: Asynchronous Request Processing using Servlets 3.0 and Java EE 6

7 Comments »

  1. Hey, if GlassFish embedded is now "usable", I’ll have to add support to it in my Wembed project: http://projectkenai.com/projects/wembed/pages/Home

    Last time I checked, it was still in early beta so I’m happy to hear it is now polished enough so I can test it.

    I’m using embedded servlet containers to test applications, using HtmlUnit integration tests, against different containers inside Ant.

    That, and as a simple way of installing demos as using Wembed is double click and you get a nice status window and a log console, using the container of your choice.

    GF would make the 4th container, so the more, the merrier.

    Thanks for the info

    Comment by GreenEyed — May 7, 2010 @ 3:42 am

  2. Greeneyed,

    See another related entry for a slightly more advanced sample:

    http://blogs.sun.com/arungupta/entry/totd_133_jpa2_jpql_criteria

    Let me know once you’ve added support for GlassFish in Wembed, would love to publicize it.

    Comment by Arun Gupta — May 7, 2010 @ 8:50 am

  3. Ummm, I almost got it to work. I can start the server and deploy the web application, but trying to execute a JSP produces tons of "PWC6199: Generated servlet error" about packages and classes not being found, but the packages are the one like javax.servlet, org.glassfish.jsp.api etc. and the classes are HttpServletRequest…

    And those classes are obvioulsy inside the glassfish-embedded-all jar… so it seems as if the JPS compiler is not using this jar… weird.

    Unless I have to add that jar myself to the web application libraries, I don’t get it. :?

    S!

    Comment by GreenEyed — May 7, 2010 @ 1:35 pm

  4. Hi Arun,
    I was finally able to add GlassFish support to Wembed.
    However, given that there is currently no support for descriptor-specified datasources in GlassFish-embedded, it is really not that useful.

    S!

    Comment by GreenEyed — May 16, 2010 @ 10:37 am

  5. Scratch my last comment :) , I have been able to get it to work thanks to the new Java EE 6 features and some tweaks to the classpath.

    So, in the end it was not that bad that I suggested Java EE 6 to add the feature of defining datasources from the application through a standard descriptor ;) .

    I’ll refine and check everything and I’ll pack a release with GlassFish support. Yes!!

    S!

    Comment by GreenEyed — May 16, 2010 @ 12:05 pm

  6. @GreenEyed, did your JSP Compilation issues got resolved?

    Comment by Siraj — May 20, 2010 @ 3:35 pm

  7. Hi Siraj,
    Yes, they did. It was a strange classpath problem due to the way I was building the jar and adding libraries to the classpath.
    GlassFish was the only one giving me such problems, but it might be caused byt the packaging of the glassfish-all jar file.

    In any case, I changed the way I launch the embedded containers and it worked,
    I still have some issues regarding the temporary directory that gets created that sometimes it’s not removed, but other than that, it works.
    S!

    Comment by GreenEyed — May 21, 2010 @ 11:49 pm

RSS feed for comments on this post. TrackBack URL

Leave a comment

The views expressed on this blog are my own and do not necessarily reflect the views of Oracle.
Powered by WordPress