Java EE 6 Wizards for Eclipse

GlassFish Tools bundle v1.2 and our GlassFish plugin will add support for some Java EE 6 wizards. While the current Eclipse 3.5.x does not support Java EE 6 (it will be in Eclipse 3.6, possibly next year), our GlassFish server adapter can deploy and run EE 6 type of applications. It provides the entire set of Java EE 6 APIs to a project, with javadoc code completion, It is possible to create new wizards that would check if the server target is GlassFish v3 and to the best we can do, create Java EE 6 artifacts in the projects. It might not be optimal (i.e current Eclipse could expect some changes in web.xml while our wizards can ignore entirely web.xml editing.

List of possible wizards

Servlet 3.0 (using annotation) and without web.xml modification

  1. Status: p0 done
  2. P1: possibly better tuning in the generated code (i.e Like Nb does, with some sample code in a comment to actually do stuff in the doget() call - done

Async Support for Servlets and Filters

  1. Status: p1
  2. Info from Rajiv (spec lead): When you add a new Servlet, there should be an option (possibly a checkbox) to say if a servlet is an async servlet. When marked true, the @WebServlet should have the element asyncSupported=true.

In addition to this, when selecting the async option, we should ask the developer if they would like to add an AsyncListener as well to the project and generate a skeleton AsyncListener

Same for Filter. @WebFilter(..., asyncSupported=true). For Filter in the dialog that says add filter mappings, there is also the target for dispatch conditions. We need to add ASYNC dispatch type to that list of checkboxes. Also I don't know if this possible or not, but the entire request processing chain must be async to be able to support async, So for example if you have a filter and a servlet, then to be able to support async, both the filter and servlet must support async, otherwise you cannot support async. It would be nice if NB could detect that early in the cycle and let the developer know that everything in the request processing cycle must be async enabled. This is more of a runtime failure but early indications to the developer will be good.

  1. Code snippet (Simple hello world response asynchronously sent from a separate thread):
@WebServlet(urlPatters="/foo", asyncSupported=true)
public class MyServlet extends HttpServlet {
   public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
              if (!req.isAsyncSupported()) {
           throw new ServletException("Async not supported when it should");
       }

       final AsyncContext ac = req.startAsync();

       Timer asyncTimer = new Timer("MyTimer", true);
       asyncTimer.schedule(
           new TimerTask() {
               @Override
               public void run() {
                   try {
                       ac.getResponse().getWriter().println("Hello world");
                       ac.complete();
                   } catch (IOException ioe) {
                       ioe.printStackTrace();
                   }
               }
           },
           5000);
        }
}
// Asynch listener: 
MyAsyncListener implements AsyncListener {
   public void onComplete(...) {
   }
   public void onTimeout(...) {

   }
   public void on Error(...) {

   }
}

simple web.xml wizard

  1. Status: p1
  2. use case is if the project does not have a web.xml but the developer wants to create one...

Filter 3.0 (using annotation) and without web.xml modification

  1. Status: p0 done
  2. Code snippet:
...
@WebFilter(filterName="NewSimpleFilter", urlPatterns={"/*"})
public class NewSimpleFilter implements Filter {

...

//see complete example in NB generator (Web->Filter)

Web Application ServletListener 3.0 (using annotation) and without web.xml modification

  1. Status: p0 done
  2. See Nb wizard (Web->Web App Listener). It should ask for interfaces to implement (Context Listener, HTTP listener, etc) and avoid web.xml changes.

EJB 3.1 with stateful, stateless, or singleton and can have local/remote/none/both, including in Web Projects

  1. Status: p0 done
  2. Notes: To use, the project must be a web or ejb project.

The session bean wizard lets you create stateful, stateless, or singleton and can have local/remote/none/both. The main differences b/w that wizard and the standard eclipse one:
a) singleton is offered
b) local is off by default, no-interface is on instead
c) allowed to do in web project
d) second page of the wizard is missing a few sections - talked to Ken S. and he said they were not needed (mapped name, ejb 2.1 section).

EJB 3.1 @LocalBean support

  1. Status: p1 done

EJB Timer wizard (simple, exposing one time method as a sample)

  1. Status: p0 done
  2. Goal is to exposed some type of notion of the EJB timer concept
  3. Code generation can be as simple as a sample, printing something the GlassFish log file
import javax.ejb.Schedule;
import javax.ejb.Stateless;
import javax.ejb.Timer;
@Stateless  public class MyEJBSchedule { 
    @SuppressWarnings("unused")
    @Schedule(second="*/10", minute="*", hour="8-23", dayOfWeek="Mon-Fri", info = "MyTimer")
    private void scheduledtimeout(Timer t) {
        System.out.println("@Schedule called at:  "+ new java.util.Date());
    }     
}
  1. The wizard could ask for some parameters to better control the output of the @Schedule annotation (cron format)

web-fragment.xml in library project

Java EE 6 sample projects (see what Nb is reusing in terms of samples)

  1. Status: p1
  2. first step is to "eclipsetize" the EE 6 samples from https://glassfish-samples.java.net/ (see src code), then to provide a build step and an Eclipse plugin to expose them as Eclipse Samples.

JAX RS wizards (no need to change web.xml) (reuse/extend what is there in Metro Plugin?)

  1. Status: p0 - all 3 patterns done
    1. P0: Creates RESTful web service using one of the following patterns: simple root resource, container-item, client-controlled container-item.
  2. For example, a simple root resource rs ws:
package foo;

import javax.ws.rs.core.Context;
import javax.ws.rs.core.UriInfo;
import javax.ws.rs.Consumes;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.GET;
import javax.ws.rs.Produces;


@Path("generic")
public class GenericResource {
    @Context
    private UriInfo context;
    public GenericResource() {
    }

    @GET
    @Produces("application/xml")
    public String getXml() {
        throw new UnsupportedOperationException(); //TODO return proper representation object
    }
    @PUT
    @Consumes("application/xml")
    public void putXml(String content) {
    }
}
  1. P1: Creates JavaScript client stubs for RESTful web services.
  2. P1: Add the RS tester client web app (html +JS from NetBeans inside Eclipse)

    JAX RS from Entity beans? Is it complex to do via Eclipse Meta model?

  3. Status: p1

JSF 2.0: xhtml wizard, facelet, facelet taglib, composite component,...NetBeans 6.8 JSF page. Eclipse Facelet support is still in incubation link so we will need to check the status and possibly add this module to our bundle.

  1. P2: Based on current discussion, this is ongoing work done by the Oracle guys inside Eclipse, but still in incomplete incubation mode, to be done for Next June 2010, not before. We might have to wait for that...
  2. P0: but for now, the minimum thing we can do is to provide a simple xhtml file wizard (it does not exist yet in Eclipse WTP) that creates some simple xhtml file (and check if xhtml1-strict.dtd DTD is registered )
<?xml version="1.0" encoding="UTF-8"?>
<!--
Simple XHTML file
-->
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
        <title>TODO supply a title</title>
    </head>
    <body>
        <p>
            TODO write content
        </p>
    </body>
</html>
{code}}
h1. P0: More complex xhtml referring to JSF and a template.xhtml (to create as well)...(Need to check for xhtml1-transitional.dtd presence?).

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/xhtml1-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"
xmlns:f="http://java.sun.com/jsf/core">
<h:body>

This text above will not be displayed.

<ui:composition template="/template.xhtml">

This text will not be displayed.

<ui:define name="title">
Facelets
</ui:define>
This text will also not be displayed.

<ui:define name="body">
Hello from Facelet !
</ui:define>

This text will not be displayed.

</ui:composition>

This text below will also not be displayed.

</h:body>
</html>

--------------------

template.xhtml is:

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets">
<h:head>
<h:outputStylesheet name="css/default.css"/>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Facelets - Template</title>
</h:head>

<body>
<h1>
<ui:insert name="title">Default Title</ui:insert>
</h1>
<p>
<ui:insert name="body">Default Body</ui:insert>
</p>
</body>

</html>
{code}}

Bean Validation wizard

? Maven project targeting Java EE 6? prototype posted on the web.

  1. Status: P1
  2. The key here is to be able to generate a default maven project with this type of pom.xml (EE 6 war)
<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>com.mycompany</groupId>
  <artifactId>mavenproject1</artifactId>
  <packaging>war</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>mavenproject1 Java EE 6 Webapp</name>
  <url>http://maven.apache.org</url>
  <repositories>
      <repository>
          <id>java.net2</id>
          <name>Repository hosting the jee6 artifacts</name>
          <url>http://download.java.net/maven/2</url>
      </repository>
  </repositories>
  <dependencies>
    <dependency>
      <groupId>javax</groupId>
      <artifactId>javaee-web-api</artifactId>
      <version>6.0-SNAPSHOT</version>
      <scope>provided</scope>
    </dependency>

    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.2</version>
      <scope>test</scope>
    </dependency>
    
  </dependencies>
  <build>
    <plugins>
      <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>
      <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>
    <finalName>mavenproject1</finalName>
  </build>
</project>
For a Java EE 6 EJB Module project:

<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>com.mycompany</groupId>
  <artifactId>mavenproject2</artifactId>
  <packaging>ejb</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>mavenproject2 Java EE 6 EJB</name>
  <url>http://maven.apache.org</url>
  <dependencies>

    <dependency>
      <groupId>javax</groupId>
      <artifactId>javaee-api</artifactId>
      <version>6.0-SNAPSHOT</version>
      <scope>provided</scope>
    </dependency>

    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.2</version>
      <scope>test</scope>
    </dependency>
    
  </dependencies>

  <repositories>
      <repository>
          <id>java.net2</id>
          <name>Java.Net Maven2 Repository, hosts the javaee-api dependency</name>
          <url>http://download.java.net/maven/2</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.6</source>
          <target>1.6</target>
        </configuration>
      </plugin>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-ejb-plugin</artifactId>
        <version>2.1</version>
        <configuration>
          <ejbVersion>3.1</ejbVersion>
        </configuration>
      </plugin>
    </plugins>
    <finalName>mavenproject2</finalName>
  </build>
</project>