Friday Dec 11, 2009

GlassFish V3 Extensions, part 5 : Wombat container

With the release of the GlassFish v3, we have built a Java EE 6 application server that is :

  • Modular : based on OSGi, GlassFish v3 is a modular application server with a set of 200+ modules loaded on demand when users deploy applications that use such features.
  • Extensible : well, that's obvious that anything built on OSGi is extensible at the very least, extensible the OSGi way, but we have also added a set of APIs for fine control over extensibility points added to the product.
  • Embeddable : want to test your web app in maven ? you got it...

I am not going to dwell on a long laundry list of features we support or changed in this release, this would require a book (seriously, we rewrote so many parts, it's monumental) so I will just demonstrate some of these extension points by adding a new container to GlassFish. This new container will run a new component type called the Wombat component. Therefore I am proposing to write a wombat-container implementation in this entry. Sources can be found here.

Wombat Component

A wombat component is just a POJO annotated with a @Wombat annotation. The annotation looks like :

@Retention(java.lang.annotation.RetentionPolicy.RUNTIME)
public @interface Wombat {
    /\*\*
     \* Name to disambiguate different wombats
     \*
     \* @return a good wombat name
     \*/
    public String name();
} 

Nothing fancy here, there is a mandatory name attribute that need to be set to disambiguate various wombat components your application might package. Each wombat component has a set of public methods that make up its interface and can be called from any client code. The lifecycle of the wombat components is managed by the wombat container and such wombat components should be injectable in any Java EE components (that supports injection of course) without much effort.

Let's have a look at my first Wombat component :

@Wombat(name="simple")
public class SimpleWombat {
     public String saySomething() {
        return "Bonjour";
    }
}

Wombat Container, core functionalities

When implementing a GlassFish container extension, you need to implement 4 distinct interfaces, let's review them now :

  1. Sniffer : a sniffer is a singleton object that is instantiated when the first deployment (or application reload on startup) is invoked. Its main responsibility is to sniff the deployable artifacts and indicate to the deployment backend whether or not the deployable artifact contains components it is interested in. To make it clear, it sniffs the jars you deploy and check wether or not it contains Wombat components. The idea behind the sniffers is that they should be extremely lightweight since all sniffers get a change to check anything deployed, so you certainly don't want the sniffer to spend too much time doing so or loading too many modules to do their work.
  2. Container : a container is a singleton object again that represents the lifecycle of the component container. It's instantiated at the first deployment of a component (basically when the sniffer claims that at least one component of a supported type has been found in the deployable artifact). So here, first time you deploy an application (.jar) that contains at least one annotated class with @Wombat, the container is instantiated. In theory when the last component is un-deployed, we could destroy the container but many containers do not support being restarted so it stays alive until next startup when it won't be instantiated again (since there are no more component to serve). 
  3. Deployer : a deployer is also a singleton, thread safe object that deploys components to the container. In this case, the deployer is responsible for loading the component class, ensuring that everything is fine with the components inside the deployable artifacts and return a instance of a ApplicationContainer. 
  4. ApplicationContainer : there is one instance of that type per application and per container. So for instance, say you deploy 2 war files with wombat components embedded in, each deployment cycle will create a new instance of ApplicationContainer. These instances are responsible for suspend/resume and start/stop operations on the components. 

Still with me ? Good, it's almost over with the theory, one more thing : It's important to understand how everything works when dealing with applications containing several component types. For instance, take a war file containing a servlet and a wombat component. In such cases, each sniffer will pick up the application, a container of each type will be instantiated and the application will be deployed using each deployer returned by each container. At the end, deployment will end up with a number of ApplicationContainer instances (2 in the war example above). 

 Let's look now how this is implemented, first the sniffer :

@Service(name="wombat")
public class WombatSniffer implements Sniffer {
    public boolean handles(ReadableArchive source, ClassLoader loader) {
        return false;
    }
    public Class<? extends Annotation>[] getAnnotationTypes() {
        Class<? extends Annotation>[] a = (Class<? extends Annotation>[]) 
						Array.newInstance(Class.class, 1);
        a[0] = Wombat.class;
        return a;
    }
    public String[] getContainersNames() {
        String[] c = { WombatContainer.class.getName() };
        return c;
    } 

The interesting methods are handles() and getAnnotationTypes(). getAnnotationTypes() should return all annotations that identify components implemented by this container. In our example it's the @Wombat annotation type. You can imaging for instance that the EJBSniffer is returning @Stateless and other EJB related annotations. The returned annotation types are used by the deployment infrastructure to scan for all annotations in one pass rather than relying on each sniffer doing a pass for its annotation types. handles() should return true if the sniffing of the deployable artifact revealed any component supported by this container, this is useful when component can be defined in xml deployment descriptors. In this particular case, it returns false all the time since we only use annotations.

 Once the sniffer handles() returns true or if one of the annotation returned by getAnnotationTypes() has been spotted, the Container identified by getContainerNames() is instantiated. Let's look at that code : 

@Service(name="org.glassfish.examples.extension.WombatContainer")
public class WombatContainer implements Container {
    public Class<? extends Deployer> getDeployer() {
        return WombatDeployer.class;
    }
    public String getName() {
        return "wombat";
    }

As you can see the wombat container does not have many things to do when it's brought into memory, our web container for instance is slightly more complicated... The interesting method is the getDeployer(), let's look at the deployer code now :

@Service
public class WombatDeployer implements Deployer<WombatContainer, WombatAppContainer> {
    public boolean prepare(DeploymentContext context) {
        return false;
    }
    public WombatAppContainer load(WombatContainer container, DeploymentContext context) {
        WombatAppContainer appCtr = new WombatAppContainer(container);
        ClassLoader cl = context.getClassLoader();
        ReadableArchive ra = context.getOriginalSource();
        Enumeration<String> entries = ra.entries();
        while (entries.hasMoreElements()) {
            String entry = entries.nextElement();
            if (entry.endsWith(".class")) {
                String className = entryToClass(entry);
                try {
                    Class componentClass = cl.loadClass(className);
                    // ensure it is one of our component
                    if (componentClass.isAnnotationPresent(Wombat.class)) {
                        appCtr.addComponent(componentClass);
                    }
                } catch(Exception e) {
                    throw new RuntimeException(e);
                }
            }
        }
        return appCtr;
    }
    public void unload(WombatAppContainer appContainer, DeploymentContext context) { }
    public void clean(DeploymentContext context) { }
    private String entryToClass(String entry) {
        String str = entry.substring("WEB-INF/classes/".length(), entry.length()-6);
        return str.replaceAll("/", ".");
    }

As you can see, Deployer has 4 important methods, prepare, load, unload and clean. Prepare is called when the application is loaded, application containers cannot rely on the final class loader to be available during the prepare phase. The load phase loads the component container but does not start the component, it should not be possible to make client invocations yet. Unload and clean are the undeployment/unloading counterparts of the prepare and load methods. The load() method implementation is rather not sophisticated, it loads all classes from the archive and checks if the class is annotated with the @Wombat annotation. If so, it keeps track of all classes that are wombat components. 

Finally, the last part, the ApplicationContainer implementation :

public class WombatAppContainer implements ApplicationContainer {
    final WombatContainer ctr;
    final List<Class> componentClasses = new ArrayList<Class>();    
    public WombatAppContainer(WombatContainer ctr) {
        this.ctr = ctr;
    }
    void addComponent(Class componentClass) {
        componentClasses.add(componentClass);
    }                      
    public boolean start(ApplicationContext startupContext) throws Exception {
        for (Class componentClass : componentClasses) {
            try {
                Object component = componentClass.newInstance();
                Wombat wombat = (Wombat) componentClass.getAnnotation(Wombat.class);
                ctr.habitat.addComponent(wombat.name(), component);
            } catch(Exception e) {
                throw new RuntimeException(e);
            }
        }
        return true;
    }
    public boolean stop(ApplicationContext stopContext) {
        for (Class componentClass : componentClasses) {
            ctr.habitat.removeAllByType(componentClass);
        }
        return true;
    }
    public boolean suspend() {
        return false;
    }
    public boolean resume() throws Exception {
        return false;
    }
} 

As you can see the code is fairly straightforward once again. On start, we instantiate all wombat components the deployer found, then we add them to the habitat so they can be looked up using the NamingManager. The stop command undo what the start command did and we don't support suspend/resume in this example.

We now have all the code necessary to implement our wombat container. Let's look now at the optional features one might want to add to a GlassFish V3 container. 

Configuration

it's of course important to add configuration for our new wombat container and have that configuration store in our central configuration file, the domain.xml. This is particularly important to users so that they feel the extension is well integrated with the rest of GlassFish. Also by using the configuration infrastructure, you get REST access to the configuration for free and other freebies. To be able to save your configuration to the domain.xml, you only need to declare a few annotated interfaces (similar to JAXB interfaces). So let's take the following configuration format :

<wombat-container-config number-of-instances="5">
    <wombat-element foo="something" bar="anything"/>
</wombat-container-config>

As you can see, this xml snippet is just defining the content of the wombat container, it is agnostic under which element in the domain.xml it will added to or even where it will be stored, that magic is handled by the GlassFish configuration.

Let's have a look at our 2 annotated interfaces defining this configuration :

@Configured
public interface WombatContainerConfig extends Container {
    @Attribute
    public String getNumberOfInstances();
    public void setNumberOfInstances(String instances) throws PropertyVetoException;
    @Element
    public WombatElement getElement();
    public void setElement(WombatElement element) throws PropertyVetoException;
} 
@Configured
public interface WombatElement extends ConfigBeanProxy {
    @Attribute
    public String getFoo();
    @Attribute
    public String getBar();
}

It's pretty much self-explanatory, 2 classes for the 2 elements. The parent element define a sub-element annotated with @Element interface, the attributes are annotated with @Attribute. This is all you need to do read and store configuration data from our domain.xml. The configuration backend will take care of implementing these interfaces with the necessary hooks to read and write the XML correctly (or whatever format we might choose in a future release). The wombat container can use the getter methods to access the configuration as it is defined in the domain.xml it is running with. 

One last thing, how can you get the configuration added to the domain.xml when the container has been newly added (first time access). Let's revisit the sniffer class with some new methods since it is the natural place to handle first time initializations. I am not repeating the methods I already mentioned above : 

@Service(name="wombat")
public class WombatSniffer implements Sniffer {
    @Inject(optional=true)
    WombatContainerConfig config=null;
    @Inject
    ConfigParser configParser;
    @Inject
    Habitat habitat;
    public Module[] setup(String containerHome, Logger logger) throws IOException {
        if (config==null) {
            URL url = this.getClass().getClassLoader().getResource("init.xml");
            if (url!=null) {
               configParser.parseContainerConfig(habitat, url, WombatContainerConfig.class);
            }
        }
        return null;
    } 

 The key here is that we have an optional dependency on WombatContainerConfig so if is not present in the domain.xml, the instance variable will remain null. When the first wombat deployment is under way, deployment infrastructure will call setup(). Within the setup method implementation, if the instance is null, that mean there is no wombat container configuration present in the domain.xml and we add it using the small xml snippet mentioned above (and packaged in the container jar file in the init.xml). The config parser is a utility API that can be used to parse a random xml snippet and add it to the right location in the domain.xml. By the way, location, location, yes but how is that location defined ? Look at WombatContainerConfig, it extends the Container interface, that's the marker interface that tell the configuration backend that it's a container configuration (we have a few documented extension hooks like this). After set up is called, the domain.xml will look like : 

<domain....>
.... 
   <configs>
    <config name="server-config">
      <wombat-container-config number-of-instances="5">
        <wombat-element foo="something" bar="anything" />
      </wombat-container-config>
      <http-service>
.... 
</domain>  

as you can see wombat-container-config element was added to the right location under config so that when clustering is enabled, the wombat container config can be referenced or have values specific to a node or a configuration.

Extras

 Now that we have added configuration, it would be nice to be able to change it. The simplest way to do that is to add a CLI command, but you can also add an admin GUI plugin if you feel more adventurous, it's not any harder. Let's look at the CLI admin command implementation.

@Service(name="wombat-config")
public class WombatConfigCommand implements AdminCommand {
    @Param
    String instances;
    @Inject
    WombatContainerConfig config;
    public void execute(AdminCommandContext adminCommandContext) {
        try {
            ConfigSupport.apply(new SingleConfigCode<WombatContainerConfig>() {
                public Object run(WombatContainerConfig wombatContainerConfig) 
			throws PropertyVetoException, TransactionFailure {
                    wombatContainerConfig.setNumberOfInstances(instances);
                    return null;
                }
            }, config);
        } catch(TransactionFailure e) {            
        }
    }
}

As you can see, he too gets the Wombat configuration injected and the command is defining a single parameter (instances) which will be used to change the number of instances attribute on the wombat configuration. Like any configuration change in GlassFish V3, the command must use a Configuration change transaction to ensure some ACID properties to the configuration change. 

This command can be invoked by doing :

asadmin wombat-config --instances 10

and you will see the wombat-config xml snippet in domains/domain1/config/domain.xml change from 5 (it's initial value) to 10. There are more extensions capability like I mentioned earlier, you can add an admin GUI plugin, you can have some code run when the user creates a new domain (to get once again some default configuration stored in the newly created domain.xml) and few other advanced goodies.

The client

So we have now a complete container implementation for wombat components, let's build it and install it in glassfish :

cd wombat-container
mvn install
cp target/wombat-container.jar <glassfishv3>/glassfish/domains/domain1/autodeploy/bundles

Now we need to create some wombat components and use them inside a client like a servlet. To do that, I am defining a web application which will contain a simple servlet and a single wombat component. Please note that this servlet is a converged application since it contains both Java EE artifacts like the servlet and foreign components like the Wombat component. The structure of this application is however a simple war file, no need to have to package the wombat components in a different file.

./pom.xml
./src
./src/main
./src/main/java
./src/main/java/components
./src/main/java/components/SimpleWombat.java
./src/main/java/HelloWorld.java
./src/main/webapp
./src/main/webapp/WEB-INF
./src/main/webapp/WEB-INF/web.xml

let's look at the sources, SimpleWombat.java first :

@Wombat(name="simple")
public class SimpleWombat {
    public String saySomething() {
        return "Bonjour";
    }
}

and the servlet :

@WebServlet(urlPatterns={"/hello"})
public class HelloWorld extends HttpServlet {
    @Resource(name="Simple")
    SimpleWombat wombat;  
    public void doGet(HttpServletRequest req, HttpServletResponse res)
            throws IOException, ServletException {
        PrintWriter pw = res.getWriter();
        try {
            pw.println("Injected service is " + wombat);
            if (wombat!=null) {
                pw.println("SimpleService says " + wombat.saySomething());
                pw.println("<br>");
            }
  	} catch(Exception e) {
        	e.printStackTrace();
        }
    }
} 

to use the client, just build and deploy

cd webclient
mvn install
asadmin deploy target/webclient.war

and access the page at http://localhost:8080/webclient/hello 

As you can see, I reuse the same @Resource type of dependency I used to inject my OSGi declarative services in my previous blog so you can really use only Java EE APIs to use extended features.  

Conclusion

 In this blog entry, I demonstrated how easy it can be to add a new container for new component types to GlassFish V3. You might ask yourself why would you ever need to do that and in all honesty, very few people will need to but the truth is that certain domain specific problems could be easily resolved by added domain specific components with their specific lifecycle, responsibilities or invocation methods. Also with the various web related framework flourishing, the scripting languages bases solutions, there are more and more application types these days. One more thing, we used the infrastructure described above to implement all of the Java EE containers (like EJB, Web, JPA, WebServices...) and others like our Rails containers so I am pretty confident you can leverage these features, we tested them well...

Tuesday Apr 21, 2009

GlassFish V3 Extensions, part 3 : Spring, Java EE 6 and OSGi

Few months ago, I met with Yan Pujante from LinkedIn to show him some progress of GlassFish V3, I saw him again at the EclipseConference few weeks back where he made an interesting presentation on the difficulty of moving monolithic web applications (several megabytes) into a service based architecture. You can find his slides there. I have decided the devote this entry on how you can use GlassFish V3 to help solving that issue with OSGi and Spring. 

First, remember from my last entry, I created an OSGi bundle which contains a simple interface, this represents the service interface. Today, I will implement this interface with two Spring DM, and access such services from a Servlet without having any OSGi/Spring dependency introduced...

I am pretty bad at explaining things, hopefully this diagram will explain it all... 


As you can see, I have 3 bundles in play, a pure OSGi bundle called API which contains my service definition (just a plain java interface), a Spring OSGi application called IMPL which contains 2 Spring beans and finally a Java EE 6 web application called WEBCLIENT that looks up services implementation and invoke their methods.

Project Files

I have included all the project files to reproduce this, there are three directories and a top level pom.xml to build the three projects

  1. api : contains the simple service definition I blogged in my last entry
  2. impl : contains the Spring Beans implementations
  3. webclient : contains the Java EE 6 web application to access my services.
Here is a list of the files and the sources are here.

Spring integration

First, we need to extend GlassFish v3 with the Spring container, go to SpringSource and download the GA release 1.1.3, you will find a number of jar files in the lib directory, you do not need all of them, in particular you already have a web container with GlassFish so all you really need is the Spring core platform, find below the list of bundles I came up with that allowed me to run my beans (you might need more as you add features).

I have tried the 1.2 release but it seems it requires to run on Equinox rather than Felix due to some bundle fragment support missing. This will be a good opportunity for a follow up blog to show how to run GlassFish v3 with Equinox and Spring 1.2. For now, pick 1.1.3, that will work fine.

To install these bundles in glassfish you can just copy them inside the modules directory or you can create a subdirectory under modules (call it spring).  This is my modules/spring directory content :

com.springsource.org.aopalliance-1.0.0.jar
com.springsource.slf4j.api-1.5.0.jar
com.springsource.slf4j.log4j-1.5.0.jar
com.springsource.slf4j.org.apache.commons.logging-1.5.0.jar
log4j.osgi-1.2.15-SNAPSHOT.jar
spring-aop-2.5.5.jar
spring-beans-2.5.5.jar
spring-context-2.5.5.jar
spring-context-support-2.5.5.jar
spring-core-2.5.5.jar
spring-osgi-core-1.1.3.jar
spring-osgi-io-1.1.3.jar
Once you have done that, you can start your GlassFish instance :
asadmin start-domain

Now let's deploy the extender bundle from Spring. I am not copying that bundle inside modules/spring directory like the other ones because I need this bundle to be automatically started (remember from my last entry that bundles in modules are not started until explicitly tagged in the felix config file). Deploying the bundle will take care of starting it for me so just do 

asadmin deploy --type osgi dist/spring-osgi-extender-1.1.3.jar

The extender bundle will basically listen to any OSGi bundle installation and check wether or not that bundle contains Spring artifacts. If it does, it deploys those in the Spring container so all we have to do is to install Spring application in our OSGi runtime for the Spring container to pick up the tab.

Build the Spring beans implementation

Now is time to build and deploy the implementation of my service as defined in my last entry. Remember to deploy the API bundle first otherwise deploying the implementation will fail since the API bundle will be missing (once again, described here).

Reminder : asadmin deploy --type osgi api/target/simple-service-api.jar

For the sake of making that blog entry as long and painful as possible, I have added 2 implementations of the interface deployed with my API bundle.

package examples.services.impl;
import examples.services.api.SimpleService;
/\*\*
 \* Implementation of the simple service, returns a hard-coded
 \* String value
 \* 
 \* @author Jerome Dochez
 \*/
public class MyServiceImpl implements SimpleService {
    public String getString() {
        return "simple service at your service";
    }
}

and

package examples.services.impl;
import examples.services.api.SimpleService;
/\*\*
 \* Implementation of the simple service, returns a hard-coded
 \* String value
 \* 
 \* @author Jerome Dochez
 \*/
public class SecondServiceImpl implements SimpleService {
    public String getString() {
        return "second service at your service";
    }
}

 This is how I defined my Spring Beans :

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
  <bean name="simpleService" class="examples.services.impl.MyServiceImpl" />
  <bean name="secondService" class="examples.services.impl.SecondServiceImpl" />
</beans>

Now I need to make that Spring application OSGi aware, for that I need to add 2 more files, the manifest file for the plain OSGi metadata, and a new Spring deployment descriptor to specify which beans gets registered in the OSGi registry.

My OSGi manifest looks like this :

Bundle-Version: 1.0
Bundle-SymbolicName: examples.services.impl.simple-service-bundle
Bundle-Name: Implementation of some services using Spring Beans framework
Import-Package: examples.services.api
Export-Package: examples.services.impl
Bundle-ManifestVersion: 2

As you can see, I am importing the API bundle, and exporting my implementation classes.

My simple-service-osgi.xml is a bit complicated but looks like this...

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:osgi="http://www.springframework.org/schema/osgi"
  xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                      http://www.springframework.org/schema/osgi http://www.springframework.org/schema/osgi/spring-osgi.xsd">

  <!-- Export the simpleService bean (defined in a separate
       config file in this case) as an OSGi service -->

  <osgi:service id="simpleServiceOsgi" ref="simpleService"
    interface="examples.services.api.SimpleService" />
 
  <osgi:service id="secondServiceOsgi" ref="secondService"
    interface="examples.services.api.SimpleService" />
</beans>

The two Spring beans implementing the SimpleService contract will be registered in the OSGi registry under the simpleService and secondService names, this will be important when it is time to look them up.

Finally let's build this using maven, this is the pom file

<?xml version="1.0"?><project>
  <modelVersion>4.0.0</modelVersion>
  <groupId>examples.services.impl</groupId>
  <artifactId>simple-service-bundle</artifactId>
  <version>1.0</version>
  <packaging>jar</packaging>
  <name>Simple Service Provider implementation</name>
 
  <dependencies>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-test</artifactId>
      <version>2.5.5</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-core</artifactId>
      <version>2.5.5</version>      
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>2.5.5</version>      
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-beans</artifactId>
      <version>2.5.5</version>      
      <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>examples.services</groupId>
        <artifactId>simple-service-api</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>
  </dependencies>
 
  <build>
      <finalName>${project.artifactId}</finalName>
     <plugins>
    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-jar-plugin</artifactId>
        <configuration>
          <archive>
            <manifestFile>src/main/resources/META-INF/MANIFEST.MF</manifestFile>
          </archive>
        </configuration>
      </plugin>
    </plugins>
    </build>

Deploying the Spring application

Ok that was rough, but if you are still with me, it should get pretty easy from now on, from the impl directory, do

mvn install
asadmin deploy --type osgi target/simple-service-bundle.jar 

Deploying the implementation using the --type osgi parameter installs the bundle inside the OSGi runtime. The Spring extender bundle is automatically notified of such installations and will deploy my beans.

The Client 

Now that we have deployed our services beans in the Spring beans container, I need to have a client to access such beans. One good opportunity to try the new Java EE 6 servlet features ! I love annotations, and getting rid of xml deployment descriptors is a blessing to me (I love everything to be close to the code so I don't have to cross reference too much). 

A Java EE 6 servlet is not that different than previous platform versions, it is now annotated with @WebServlet giving a URL pattern (here it is /hello). We now have a GlassFish specific feature :  Services registered in the OSGi registry can be looked up using the standard Java EE @Resource annotation. So one important thing to notice here is that the servlet is not using any OSGi APIs nor any Spring APIs nor does it know where the implementation of such services resides.

import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.annotation.WebServlet; 
import javax.servlet.\*;
import javax.servlet.http.\*;
import javax.annotation.Resource;
import examples.services.api.SimpleService;

@WebServlet(urlPatterns={"/hello"})       
public class HelloWorld extends HttpServlet {

    @Resource(mappedName="secondService")
    SimpleService secondService;

    @Resource(mappedName="simpleService")
    SimpleService simpleService;

    public void doGet(HttpServletRequest req, HttpServletResponse res)
            throws IOException, ServletException {
 
        PrintWriter pw = res.getWriter();
        try {
            pw.println("Service class is " + SimpleService.class + "<br>");
            pw.println("First service is " + simpleService);
            pw.println("<br>");
            pw.println("Second service is " + secondService);
            pw.println("<br>");

            if (simpleService!=null) {
                pw.println("SimpleService says " + simpleService.getString());
                pw.println("<br>");
            }
            if (secondService!=null) {
                pw.println("SecondService says " + secondService.getString());
                pw.println("<br>");
            }
        } catch(Exception e) {
            e.printStackTrace();
        }
    }
}

maven war plugin is not uptodate with Java EE 6 and wants a web.xml no matter what, so I included an empty one in the project files.

Finally the pom.xml which has the war packaging type and the servlet 3.0 APIs as well as my service definition APIs dependencies.
...
    <groupId>examples.services</groupId>
    <artifactId>webclient</artifactId>
    <packaging>war</packaging>
    <version>1.0-SNAPSHOT</version>
    <name>Web client accessing Simple Provider Services</name>
...
    <dependencies>
        <dependency>
            <groupId>examples.services</groupId>
            <artifactId>simple-service-api</artifactId>
            <version>1.0-SNAPSHOT</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.glassfish</groupId>
            <artifactId>javax.servlet</artifactId>
            <version>3.0-SNAPSHOT</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>
...

Ok so again let's build and deploy this war fil (note there is no --type osgi parameter to the deploy command as we are deploying a plain Java EE application)

mvn install
asadmin deploy target/webclient.war

Everything together

We have deployed our three bundles (hopefully successfully if I have not missed some crucial information along to way) and it's time to see if our web application can be injected successfully with my services implementation, point your browser to

http://localhost:8080/webclient/hello

and you should see...


Victoire !

Thanks for following me up to here, remember the few points I have demonstrated here  :

  • Spring integration into an umodified GlassFish
  • Deployment of Spring Applications using the GlassFish deployment backend
  • Service based lookup of OSGi services using standard Java EE annotations
  • Deployment of OSGi bundles for extending GlassFish runtime.
Salut


        
    

Thursday Apr 09, 2009

GlassFish V3 Extensions, part 2 : Managed OSGi bundles

     I am back this time to talk about a feature I just added to GlassFish v3. When extending GlassFish, you really have a few different ways to do so, you can write a plain old jar file and put it in the lib directory but preferably, you should write an OSGi bundle. The best for maximum portability is to write a jar which can be an OSGi bundle and also a plain old jar when possible. So once you have your brand new OSGi bundle, how can you install it in GlassFish v3 so it becomes part of the ecosystem ?

    There are basically two ways to do that today :

  • place the bundle in the glassfish/modules directory.

  • deploys the bundle just like you deploy any other application.

    Let's look at the disadvantages of each solution : 

  1. modules directory : Using the modules directory solution is easy and quick, and seems to be the natural way of adding functionality to GlassFish. However it has a few disadvantages :

    • no module management, you need to manage the files in modules yourself (adding, updating, removing).

    • no clustering support. we don't have clustering support in v3 yet but using the modules directory will not guarantee that all server instances will be updated when you add or remove bundles from the modules directory.

    • hard to figure out which bundles in modules directory are yours versus the ones we delivered. 

    • bundles are not started in OSGi automatically in V3, they are just installed, so if they have a bundle activator for instance, you need to start them manually. One easy way to do that is to change the autostart list in the felix configuration at glassfish/osgi/felix/config/config.properties.

  2. Deployment : using deployment method you need to manage dependencies correctly when you deploy. So far you can only deploy one bundle at a time (ok, if you don't like that, file an RFE) so if your bundles import other bundles and so on, you better deploy them in the right order.

I think solution 2 has many advantages, it's a managed operation which is protected by the admin password if you set up on, it also does not require to have access to the application server file system and it's remotable. To illustrate solution 2, I am now going to build a new OSGi bundle and deploy using the normal "asadmin deploy" command. Let's start with building a new bundle using maven, something really simple, an API bundle containing one service definition that looks like this :

package examples.services.api;
/\*\*
 \* Simple service defition
 \* @author Jerome Dochez
 \*/
public interface SimpleService {
    /\*\*
     \* Returns a implementation specific string
     \* @return a String
     \*/
    public String getString();
}


So nothing that will get me a Nobel prize here ;-) Let's see the project files now.

./pom.xml
./src/main/java/examples/services/api/SimpleService.java
./src/main/resources/META-INF/MANIFEST.MF


Due to the simplicity of the project, I manually coded the manifest file rather than using BND, also it helps the no-magic theme here.

Bundle-Version: 1.0
Bundle-SymbolicName: examples.services.simple-bundle-api
Bundle-Name: Services definition bundle for OSGi integration in GlassFish
Export-Package: examples.services.api
Bundle-ManifestVersion: 2


Finally, the complete pom.xml file looks like this...

 <?xml version="1.0"?>
<project>
    <modelVersion>4.0.0</modelVersion>
    <groupId>examples.services</groupId>
    <artifactId>simple-service-api</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>
    <name>Simple Service Provider API definition</name>
    <developers>
        <developer>
            <id>dochez</id>
            <name>Jerome Dochez</name>
            <email>jerome.dochez@sun.com</email>
            <url>blogs.sun.com/dochez</url>
        </developer>
    </developers>
    <build>
        <finalName>${project.artifactId}</finalName>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <configuration>
                    <archive>
                        <manifestFile>src/main/resources/META-INF/MANIFEST.MF</manifestFile>
                    </archive>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

Build your code

mvn install 

Ok so time to deploy your new bundle in V3, this is really hard, just do 

 >asadmin deploy --type osgi target/simple-bundle-api.jar

--type osgi is necessary so the bundles is installed in the OSGi runtime rather than in Java EE containers. now let's check if the bundle is installed correctly, let's start the felix console :

>telnet localhost 6666
Tower:impl dochez$ telnet localhost 6666
Trying 127.0.0.1...
Connected to localhost.
Escape character is '\^]'.

Felix Remote Shell Console:
============================

-> 

type "ps" and you should get a list of all the installed bundles, one should be our newly deployed OSGi bundle (note that your bundle ID might be different) 

[ 188] [Active     ] [    1] Services definition bundle for OSGi integration in GlassFish (1.0)

lets make sure this is how bundle :

-> headers 188

Services definition bundle for OSGi integration in GlassFish (188)
-------------------------------------------------------------------------
Manifest-Version = 1.0
Archiver-Version = Plexus Archiver
Bundle-Name = Services definition bundle for OSGi integration in GlassFish
Built-By = dochez
Bundle-SymbolicName = examples.services.simple-bundle-api
Export-Package = examples.services.api
Bundle-Version = 1.0
Build-Jdk = 1.6.0_07
Created-By = Apache Maven
Bundle-ManifestVersion = 2

when you are done with the bundle, just undeploy :

>asadmin undeploy simple-bundle-api

Voila !


Next article will be a lot more interesting, we will be using our newly deployed OSGi bundle with a mix of Spring, OSGi and Java EE 6 code...

Saturday Mar 07, 2009

GlassFish V3 Extensions, part 1 : Grizzly adapters support

I am embarking on an attempt to describe some of the extensibility points that GlassFish v3 has to offer. In this first article, I will describe how you can deploy raw unmodified grizzly adapters like any other GlassFish application. 

As you probably know, GlassFish v3 is built on top of grizzly, yet up to now, it was not possibly to deploy a native Grizzly adapter  directly inside V3.

Jean Francois was asking me to add this support some time back so people could leverage investments they made in developing grizzly extensions by using them in an application server that will soon support clustering and other goodies out of reach for the grizzly community.

As usual with GlassFish V3, now Grizzly applications are treated just like any other applications and you can use familiar tools to manage them.

So, to run your favorite adapter, you simply have to declare it using a small XML file, using the following format

<adapters>
   <adapter context-root="/cometd" class-name="com.foo.bar.CometdAdapter">
   </adapter>
</adapters> 

 you can also initialize the adapter with the following Beans type of pattern :

<adapter ...>
 <property name="foo" value="bar"/>
</adapter>

Internally Adapter.set<name> = <value> will be called, like:

setFoo(bar)

Of course, you can place as many adapters as you want in the xml file. Finally, place the xml file inside your jar at META-INF/grizzly-glassfish.xml and then using the latest snasphot build , just deploy your jar file or directory like any other GlassFish application :

asadmin deploy adapter.jar
OR asadmin deploy myadapterdirectory 

 Please note that the context-root parameter on the deploy command is not applying to grizzly applications since they can have multiple adapters at multiple context-roots.

 Now, Jean Francois has already developed some extensions so folks can also start deploying grizzlet directly into GlassFish, more to come from him. The source code for the grizzly container is about 5 classes, and it is a great example on how to extend the GlassFish application server to add support for new application types, find it here.

Thursday Nov 06, 2008

GlassFish V3 Prelude debuts today

Today we are releasing GlassFish V3 prelude, as the architect for the product, I feel compelled giving you my view of what this release mean for us and for you. After an aggravated loss of hair, endless evenings working on various bits and pieces and bringing together a great team of talents, I am proud of what we have achieved so far :

  • Major rework of the GlassFish code base, refactoring, modularizing, removing code was not a trivial task and we learned a lot about software practices when dealing with a module environment.

  • Extensibility is the huge value of prelude and V3 in general. Modularity is good but you might ask yourself, why is it good for me ? In a nutshell, extensibility is the answer. With modular application server, you can shrink it or extend from the smallest distribution (Rails Gem, about 3Mb) to the most sophisticated distributions like Prelude with metro stack (about 35Mb)

  • Developer features. What do developers want ? something fast, that does not get in they "way" and be productive. Prelude starts in less than 2 seconds on my screaming fast PC. It has new features that can change your life as a Java developers (more below), you really should try it out if you want fast iterative development cycles.

  • First Java EE 6 features available through the update center and more to come. (In fact, if you are brave and take our nightly builds, you get even get the servlet 3.0 features already).

It's always hard to blog on general features about something as important as an application server but let me give a stab at the things I believe you should know.

Modularity

As you probably know by now, GlassFish V3 prelude is based on an industry standard OSGi R4 implementation called Felix, Sahoo has been championing this integration, and Richard Hall (dev@felix) who joined Sun in the meantime are the references for any OSGi related information. It also run on Equinox if you rather use that environment.


Modularity was a necessity for us because it's been increasingly difficult to reconcile the growth of the Java EE platform, the choice of third party technologies that people want to use in their applications with the demands for a fast responsive application server. Modularity was the only possible solution, that allowed us the split appart the implementations in different parts and then through some intelligence with starting the different capabilities installed we have managed to keep GlassFish V3 startup time linear independently of how many features are actually installed.

 

Pay as you go ! Modularity is great but what is very important is to leverage modules and service based architecture that will allow for lazy initialization of features as they are requested. In fact, I believe that if you do Modules even based on OSGi but you don't rework your architecture to allow for lazy loading then modularization is an overhead more than an advantage. I already know of a few examples of application servers like that ;-)


So in V3, startup is 2 seconds, deploy a web application, take another 2 seconds hit, deploy yet another web application, 50ms. Get the picture ? Startup only really read the configuration (domain.xml) and starts Grizzly. The first web application triggers the web container start up, takes another 2 seconds. Yet if you deploy yet another web application or redeploy the fist one, this time, it's only 50 ms since everything has been started.

Extensibility

Modularity was also a good way of providing new features, especially around extensibility. I have spent a lot of effort into designing crucial extensibility parts of the application server.

   1. Container

      Probably the most important design center of V3 is to become "The" container for server side Java. So if you have some piece of application that runs on a server and gets invoked remotely (e.g. http, corba, etc...), you can run it on GlassFish. In fact, it's even more than Java, it really is about anything server side on the JVM. That's why today we support technologies like Rails (with the JRuby interpreter) or Grails in V3.

   2. Configuration

      As you may know, GlassFish is configured through the domain.xml file. Up to V3, this file had a structure we were defining and could not be extended. Starting in V3, anyone can provide facilities that will be discovered and used to load and store third party configuration artifacts. Why is this important ? Say you have a special library or container that is available on GlassFish, you would want to provide a nice unified configuration of GlassFish to the user and to do that, you should put it in domain.xml. Also when clustering features will be available, the infrastructure will take care of transfering these artifacts to remove server, etc.

   3. Admin Commands

      As you extend the application server, you want to be able to add new administrative commands to configure your extensions. This is both necessary for remote configuration, but also for again giving users a feeling of a unified product.

   4. Admin GUI

      Last piece is to be able to extend the console, which is our GUI front end to modify the application server configuration. A plugin architecture has been developped to help external users to extend the console, this is the last cornerstone to again providing a nice unified view of the product's configuration.

Embedded

Kohsuke has done some work to make GlassFish V3 prelude embeddable. Check it out there, it allows for running V3 prelude in any native or java process, pretty cool...

Developer features

In V3, we have added a few features which will radically change your productivity in server side Java development. First of all, keeping sessions on redeploy, and compile on save.

   1. KeepSessions

      When developing an application that heavily uses HTTP sessions to keep user's states, development can be very tedious. You test the application, find a problem, edit the code, compile, build, deploy and then you have to recreate your session when the problem occured (for instance recreate the shopping cart). In V3, you can now preserve sessions during redeployment so that you can basically reload the page in the browser to test the new code you have added.

   2. Compile on Save

  Latest Java IDE have had this features of underlying invalid code or provide a lot of metadata and most of that is done by compiling the code behind the scenes. Now it was only a step to be able to hook up some events when the recompilations of edited code was successful (on a save of course) and force redeployement. We have added this intelligence to both the Netbeans and Eclipse plugins so we can now redeploy the application when you just "save" the java source file.


So now combine the two features and from the long list of actions you had to do to test new code you are down to only save the source file. You overall iterative development cycle is test the application, find a problem, edit the code, test the change. This is what scripting languages have provided for years, yet this is Java so you can get the best of both worlds. 


These features are available with Netbeans and Eclipse, check out this on how to use those plugins in your favorite IDE. Check it out there, he should be giving out some nice screen shots on how to do that. 

Conclusion

I am personally very excited by these two features and I truelly believe that if you only want to spend 15 minutes trying GlassFish, this is what you should try, because that's my best shot at convincing you of using it a lot longer...


Have fun, download the prelude from there and give us feedback.


Friday Apr 11, 2008

GlassFish V3 runs on OSGi

As some of you may remember when I introduced the HK2 project last year, I described it as a friendly environment to OSGi where we would eventually be capable of running GlassFish V3 on top of an OSGi runtime. Thanks to the good work of Sahoo, this vision has finally been completed and I am happy to report that since last week, we are now capable to run GlassFish V3 on top of Apache Felix, one of the OSGi runtime available to the open source community.


In fact, we have also tried KnopflerFish (I like the name of course) and it runs fine so we are pretty confident that any OSGi runtime will be supported with minimum effort.


Now the interesting question that everyone will be asking soon, are we switching to OSGi as our underlying module subsystem ? Today I can say yes, we will. Some people might say that we changed our mind about OSGi, we didn't. From the beginning I always said we wanted to be friendly to OSGi, we just realized that vision... It is pretty clear that there is a big industry support for OSGi and it is important that GlassFish can be part of that excitement. I cannot commit on which implementation we will eventually use because we are still experimenting with some of them and we need to following conditions to be met :


    \* open source

    \* friendly license to one of our dual open source licenses as well as to our Java EE licensees.

    \* good community (forums, mailing list) to get our questions answered

    \* possibility of a commiter to be able to push our bug fixes.


Whichever implementation we choose will get a huge boost from this endorsement because we will certainly have engineers capable of fixing bugs, adding features but also we have top performance engineers at Sun that will help with the overall performance of the OSGi runtime. 


Sahoo will probably blog in a day or two explaining in details the technicalities of the solution we adopted but let me introduce it here. We are still capable of running in both HK2 mode and in OSGi mode, I am not sure how long we will maintain the HK2 mode but so far the startup is a lot faster in HK2 (1 second) versus OSGi (2 seconds). Ok no big deal I suppose but we will work on that. It's hardly surprising that HK2 is faster, it is not meant to be a generic modular subsystem like OSGi, it is quite optimized for our V3 work !


None of GlassFish code depends on OSGi libraries (or very very little), we isolated those dependencies in HK2 which makes it very easy for us to switch OSGi runtimes or even module management runtime with no code changes. The HK2 project will continue as it is offering a lot more than just module management, in particular we have the following features that we continue to use heavily :


    \* module management isolation layer

    \* module management through Repositories (coming in OSGi R5)

    \* lightweight component model

    \* dependency injection 

    \* configuration handling


So if you want to play with the OSGi version of GlassFish V3, I would recommend downloading the latest binaries from there.

It's our latest build, don't expect miracle and please file bugs when you find one.

 

and to run GlassFish in OSGi mode, simply do from your installation directory

    	java -DGlassFish_Platform=Felix -jar modules/glassfish-10.0-SNAPSHOT.jar

to run in hk2 mode, just do

	java -jar modules/glassfish-10.0-SNAPSHOT.jar 

Thursday Nov 29, 2007

JDK 6 with Leopard today !

So I have been one of the vocal voices that protested to Apple a few weeks back that Leopard does not bundle JDK6, it's been a disappointment compounded by the fact the JDK5 that ship with Leopard is quite incompatible with previous versions. Hard to say if my favorite Java Apps are incorrectly written or they just broke the compatbility but it is clear that IntelliJ for instance does not run on Leopard. 

Of course it starts fine but soon it fills up the system.log with stack traces and your machine will soon spend a lot time indexing these messages, bringing it to its knees. It was first reported by this now famous post and we all shared some anger at the situation.

Anyway, Soylatte have now ported OpenJDK (the now Open Source Java implementation from Sun) to Leopard, so the show will go on ! Of course this is not an acceptable solution for end users, running this port which actually use the X11 port instead of the Apple native UI has its draw backs :

    - it's poorly integrated with the rest of the operating system

    - no Aqua integration

Fabrizio blogged how to use Netbeans 6 with this port, it pinched my curiosity about my other daily tool, IntelliJ IDEA.

    - I download the linux version of IntelliJ, and decided to give it a try... and ...

 


 

Ok so this is probably not the panacea but for the developer it has a few redeeming qualities, for instance
the non visual aspects of the port are working just fine, I can run GlassFish V3 with jdk6 without a glitch
So I am now developing exclusively using the linux version on the mac, after setting the fonts to BistreamVera Sans with Antialiased and Bitstream Vera Sans Mono for editing, switch the theme to Alloy Glass and it's almost bearable...

To start IntelliJ, you just need something like

export IDEA_JDK=/Users/dochez/java/tools/jdk6
sh /Users/dochez/java/tools/idea-7364/bin/idea.sh

One last thing, the ALT key is not mapped correcly in X-Darwin, that is until you modify the .Xmodmap with the following entries, this will nicely swap your option and command key to map linux-style keyboards...

clear mod1
clear mod2
keycode 66 = Meta_L
keycode 63 = Alt_L
add mod1 = Alt_L Alt_R
add mod2 = Meta_L

So this is not perfect, but it has some advantages, they key bindings are Solaris/Linux style which for folks like me who get exposed to multiple OS is a blessing. I think Kohsuke will pay me a beer or better sake for that one, and we might see him hacking on a mac soon... Then again, after his "build this maven module" plugin contribution, I am in debt.. 

One last thing, I could not get ~/.xinitrc to work with X11 on Leopard : X11 would just not start any longer. Maybe a bug, not sure, feedback appreciated... so I have to run the xmodmap ~/.Xmodmap command manually once at each X11 startup.

Overall this is not perfect but for people like me that need JDK6 for development, it works great. Kudos to SoyLatte folks !
 

Friday Nov 16, 2007

How to build a gem

It's been quite public for some time that we have a special distribution of GlassFish V3 as a Ruby Gem file. Ruby gems are the packaging technology for ruby extensions, and having a gem distribution of GlassFish is interesting to the JRuby users community. 

Arun has blogged there about how to use the gem so I will just describe here how to build it.

To build the gem, you will need to following software :

  1. subversion to checkout the code
  2. maven to build
  3. jruby 1.0.1

The gem building is not part of the mainstream GlassFish build because it requires JRuby... The first thing to decide  is whether you want to checkout the entire GlassFish V3 workspace or just checkout the gem distribution module.

Case 1 : Entire V3 workspace

 First you should look into this document if you plan to change/add code to V3.

svn checkout https://svn.dev.java.net/svn/glassfish-svn/trunk/v3
cd v3
mvn install 

Once you have done that you have a glassfish build, you can just build the gem distribution by :

cd distributions/gem
mvn install 

Case 2 : Just the Gem 

To checkout the gem module 

svn checkout https://svn.dev.java.net/svn/glassfish-svn/trunk/v3/distributions/gem

cd gem
mvn install 

Now in either case, you will find the gem file in target/dependency/glassfish/pkg directory, and you can install it in your jruby installation by doing

gem install target/dependency/glassfish/pkg/GlassFish-10.0.0-java.gem 

Once this is done, you just need to refer back to Arun's blog on how to use the Gem !

 


Monday Jun 11, 2007

GlassFish V3 update

We published the first version of the V3 build during JavaOne, and it was time for an update of bits for the folks that don't want to build themselves...

The new build does not have new features compared to the list announced at JavaOne, it is basically bug fixes coupled with some rework of the implementation that I did not have the time to finish in may. One of the cool new feature is how the admin commands are discovered and processed by the runtime.

One of the difficulties associated with supporting multiple container types from various sources and that you want to make it easy for these container providers to simply use the runtime services offered by GlassFish. One of these services are administrative commands, during my JavaOne session, I actually demonstrated how to add new command : version.

So as everything in V3, we rely on HK2 components to identify administrative commands. So in this case, the AdminCommand interface is annotated with @Contract, so all you have to do to add a new command to GlassFish V3 is to create a Service implementing the AdminCommand interface and the runtime will find it :

package com.foo.bar;

@Service(name="super")
public class MySuperCommand implements AdminCommand {
...
}

Now this is nice but we can do better, for instance because admin commands are Services, we can use injection, so say for instance you want to have access the domain configuration, you just do

@Inject
Domain domain;

and the domain information will be injected in the instance field before the command execute() is invoked, that's nice but why not extending this to the command parameters. Too many times, I have seen command implementations code just ensure that all mandatory parameters to the command are present, values are correct, and extraction from the String[] representation.

This is where the new annotation @Param become useful, annotate any instance field of the command implementation with the @Param annotation to make it a command parameter. So for instance adding the following

@Param
String name

adds a name parameter to the command. Of course, parameters can be optional

@Param(optional=true)
String myoptionalparam

or the default parameter for the legion of lazy typers like me :

@Param(default=true)
String path
so you can now do : 
asadmin deploy --path foo.war
or
asadmin deploy foo.war

Of course there can be only one default parameter. Also the param tag is automatically linked to the resource file of your classloader, so when you add the

com.sun.foo.bar.mysupercommand=Some random super command
com.sun.foo.bar.mysupercommand.path=path to the file the command applies to.

strings to your LocalStrings.properties, the system will find them and use it for any type of error checking or help :

$prompt>asadmin super
FAILURE : super command requires the path parameter : path to the file the command applies to.

$prompt>asadmin super --help
Some random super command

Parameters :
        path : path to the file the command applies to.

The above behaviours are completely handled by the system, the command will not be executed as long as all mandatory parameters are provided by the users. There is more of course, like automatic help page and localized page creation.

Other things new in this build :
  1. HK2 injection manager is now reusable with other types of annotation than @Inject. I got the idea from Adam Bien, I also use it to inject the @Param we saw above
  2. Adding drivers to lib/shared will make them automatically discovered by the persistence provider.
  3. Support for all content types as defined in the domains/domain1/config/default-web.xml
  4. gem support (you can now build a gem file from the distribution and use jRuby to automatically install GlassFish V3 within a jRuby install)
Enjoy, spam me with comments.

Wednesday May 02, 2007

Hundred Kilobytes Kernel


From my first GlassFish V3 screencast I posted here last month, I received quite many inquiries about how we started implementing GlassFish V3. Questions like how can it start so fast, how do you implement the module subsystem and so on... It became very clear that we had done could be reused by others to create modular applications.

So we have created a new java.net project called HK2, for Hundred Kilobytes Kernel. This project is really a set of reusable technologies that serves a foundation for the GlassFish V3 implementation.

  • At the core, there is a module subsystem loosely based on the JSR277 for easy upgrade to Java SE 7

  • a component model above it which heavily use Inversion of Control , automatic dependencies resolution and life cycle management


 

 

HK2 is very small today, about 80Kb so it really is a great technology to use in any Java software development, it can be used in phones up to application server (obviously). HK2 depends on JDK 1.5 although it could easily be accommodated to run on earlier versions.

HK2 relies on maven 2 to build jar modules very easily, although maven is not dependency, it just makes things a lot easier.


As a side note, HK2 as a name triggers my imagination with the K2 mountain, therefore it will be its symbol.

Check it out at http://hk2.dev.java.net

Send feedbacks, I will also be talking about this extensively at JavaOne :

  1. TS-6503 : GlassFish V3 Architecture Review on Thursday 05/10/2007 at 2:50 PM -3:50 PM

  2. BOF-6678 : GLASSFISH V3 Architecture Review on Tuesday 05/08/2007 at 9:00 PM -9:50 PM

  3. BOF-4989 : Embedding the Grizzly Framework with Jean-François Arcand on Tuesday 5/08/2007 at 10:00 PM -10:50 PM
Technorati Tags: ,

Monday Mar 26, 2007

First GlassFish v3 screencast

I took some time off coding to do a screencast on GlassFish v3, this should be interesting to many. GlassFish V3 started for me a few months back with the creation of the v3 cvs branch and since then, I have been happily coding some experimental pre-work.

Today, GlassFish v3 which will be a modular application server has reached a milestone. It supports four types of container :

  • Standard Web Applications
  • Ruby on Rails using JRuby 0.9.8
  • Phobos
  • PHP using the Quercus engine.

Startup time is under 1s (about 900 ms) on my MacBook pro, I am officially opening a competition on who can provide me with the best startup number using a commercially available processor...

But a good screencast is better than words so watch it, enjoy it, forward it but more importantly, talk to me about it if you have any feedback.

GlassFish v3 first screencast

As a reminder all the code you see demonstrated in the screencast is available today in cvs, if you are interested developing this outstanding application server, contact us !

Thursday Mar 09, 2006

GlassFish is Universal

Today, we are gathered to celebrate a new achievement of the GlassFish community.

After being used by a vibrant community around the world, GlassFish is the first application server officially adopted by Aliens. We are now Universal

The delegate from the Meelaneese race, a mate called "Robertoch Inni Ci" (nicely pictured here) has signed an extensive agreement to use and enhance the GlassFish Project.

You can learn more from our new GlassFisher friend from his blog, and although he talks about moons, his actual planet location remains a mystery.
Ok le'ts be serious for minute. Starting with build 40, the two native binaries used by the application server are now universal binaries which mean they run on PowerPC as well as the new exciting Intel based Macs.

Here are my findings and adventures on how to transition your JNI libraries to universal binaries.
One of these native component, the libcliutil.jnilib which is a JNI library used to implement one function so we don't echo the password when using the asadmin command in interactive mode. The other component, called the native launcher was used in 8.x to launch the application server with the right JVM parameters. It has since then been replaced with a Java Launcher but we keep this version for backward compatibility reasons.

The changes to support cross compilation were actually not that easy to find, the reason being that Apple's documentation (although being very nicely written and presented) rely too much on XCode to build your native binaries. Well, some folks still want to use good old makefiles to build their software and that was not easy to find the appropriate gcc flags :

-arch i386 -arch ppc -isysroot /Developer/SDKs/MacOSX10.4u.sdk

The -isysroot is very important when you use a PowerPC based Mac since they have the universal and PPC SDKs installed. With an Intel Mac, you only have the universal installed or at least it is the default one. If you do not add this option, you will get this kind of exception :

/usr/lib/libSystem.B.dylib does not contain an architecture that matches the specified -arch flag: i386

Now you may think that I am lucky to own all this Apple hardware, and indeed, my wife works at Apple afterall :).

This time however, I didn't get to own the Intel iMac I used to change the makefiles, I got the machine from James Gosling who was kind enough to lend me his iMac for some time so I could do this. And that machine (entry level 17inch iMac) really suprised me how fast it was. I am ready to trade my dual PowerMac G5 for those anytime !

I just wished that working on James Gosling's machine made me smarter... well that's a totally different story !

Tuesday Feb 21, 2006

Project GlassFish spins out a beta !

Rejoice !

This is a important day for the GlassFish community. Today, we officially released the Sun Java System Application Server 9.0 Beta which is based on the GlassFish project. Already confused with all these products terminology, I am with you, we could hardly have made it more complicated if we had really tried but consult Tony's wisdom, he will enlighten why everything has a place in the Sun (ah, I could not resist that one).

So what is the fuss about yet another beta... Well, first this is the first beta based on the GlassFish Open Source project, this is therefore the result of hundreds of developers working for at least 2 years. More importantly, this is the first beta of a Java EE 5.0 Application Server.

We worked with the specifications writers for two years to make the developer experience the center of all new features. For me, it really all started with a meeting every Monday evening at 4pm with me, Roberto Chinnici, Bill Shannon and Linda DeMichiel to resolve one of the most hated feature of J2EE 1.4 : XML deployment descriptors. The meeting was let's say always lively...

The first intimidating steps was JavaOne 2005, where Bill presented Java EE 5 during the technical keynote followed my own session to present the current state of affairs. After Abhijit's retirement, I became the GlassFish architect which is really a pompous title to say I am taking care of the stability and the future of the implementation.

We received very positive feedback during JavaOne and continued to work hard to push the specifications and the implementation to beta quality. But let's look at what is new to get you started with Java EE 5 :

  • AJAX : Java EE 5 with Java Server Faces has all the qualities to accomodate the specific requirements of an AJAXified application. Consult our local expert Greg Murray in this interview or the Aquarium page
  • JSF : Talking about JSF, you need to go check Ed's blog for the latest news on the web tier.
  • Persistence : A new persistence API based on Plain Old Java Objects (POJO) has been worked on by Linda and Mike Keith. This API will be available in Java SE as well as Java EE environments. I recommend you follow Sahoo's blogpage for tips and details on how to use this new technology. or the Aquarium persistence
  • EJB3 : The persistence APIs being separated from the EJBs definition will give a new life to this component model : simplified, lean and powerful, the new EJBs should be considered for all back end tasks. Look at Ken's samples, they are a great way to get you up to speed.
  • JAX-WS : the JAX-RPC APIs have came and gone. There were numerous issues with their evolution or ease of use, Roberto Chinnici came up with a new API for Web Services. Of course, Dhiru updated the JSR 109 to include such technologies in the Java EE environment. Go to my blog or to Vijay's blog to details and tricks on web services.
  •  JAXB, StaX and other XML goodies. There are plenty of web resources on how to use XML apis in Java, but I have to recommend the prolific Kohsuke's  train of thoughts

But wait, if you think we stopped at just implementing the specifications, heck no, we also have a full list of product features that will make your experience with our application server easy and complete.

  • Grizzly connector : check Jean Francois's blog on the optimized HTTP path we have in SJS Application Server.
  • Tools integration : we have plugins ! That's right, whether you use NetBeans 5.0 or better NetBeans 5.5 preview, they integrate with GlassFish. That's not all, you like Eclipse, we support that too. Ludo and Vince both maintain active blogs that talk about tools.
  • Admin framework : all administrative tasks of the application server can be done either through a CLI command, an API, or the admin GUI. One reference for administration : Kedar.
  • Web Services : there is life beyong basic web services. First for performance related information, FastInfoset is what you are looking for, Paul has also a blog to get you started. Then there is JBI with this how-to. Also remember to check WebServices Management with this tip
  • Deployment : from autodeploy to Java Web Start, deployment is faster than ever and packed with features, start with Tim's blog.

And we have documentation too, check the download page for the update SJS Application Server 9.0 documentation.

Well that's it, I hope I got you all excited about this new beta, one last thing, there is where you can download it. Please use it, write your ideas and experiences to the beta forum (user forum) or the GlassFish forum (more developer centric). We are looking for your feedbacks.

Wednesday Feb 15, 2006

GlassFish with Mustang


  No I am not playing with genetics to mix horses and fish DNA... I am just going to explain how to run the GlassFish application server with Mustang which is the JDK 1.6 codename.


The Beta2 of the Java SE 6 was released today. This is an exiting release, especially for folks like me who were never impressed with how previous JDK displayed fonts or obeyed to the native platform look and feel. Now when you install JDK 1.6, you get the native look and feel and font antialiasing. This makes Java applications look as neat as any other native applications now !     
Download the Java SE 6 beta from there and take the Glassfish bits. You can either take the beta or the active development version from the download page. I am on Solaris 10 running on one of these awsome AMD machine but the following intructions should be easily transferable to Windows.

I installed the JDK bits in /Users/applications/jdk1.6.0, let's check my installation and set my environment to use JDK 1.6
-bash-3.00$ which java
/usr/bin/java
-bash-3.00$ export JAVA_HOME=/Users/applications/jdk1.6.0
-bash-3.00$ $JAVA_HOME/bin/java -version
java version "1.6.0-beta"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.6.0-beta-b59g)
Java HotSpot(TM) Client VM (build 1.6.0-beta-b59g, mixed mode)

Ok, we are all set on the JDK side (you could also update your PATH but that's not necessary), now I am going to install the GlassFish bits in say ~dochez/glassfish.
-bash-3.00$ java -Xmx250m -jar~/Desktop/glassfish-installer-9.0-b32g.jar 
-bash-3.00$ cd glassfish/
-bash-3.00$ ant -f setup.xml
Buildfile: setup.xml
....
validate-java:
     [echo] Current Java Version1.6.0-beta
....

That's it, pretty simple.

Now how can you change the version of the JDK used when you have already installed GlassFish. That's equally simple. The JDK path is stored in one location : <GlassFish_home>/config/asenv.conf
AS_JAVA="/Users/applications/jdk1.6.0"
you can replace this value with another path (as long as it is at least JDK 1.5) to play with different JDKs.


Tuesday Jan 10, 2006

GlassFish runs JWSDP samples...again...

So I decided to revert the deployment check that we added in the GlassFish build32 reported by ias The issue was that we added a deployment check for pre-Java EE 5 applications to ensure that classes were not containing Java EE 5 annotations.

I decided to add the check because I anticipated that many folks would want to try the new cool features of Java EE 5 the cheap way : they would just take an existing J2EE 1.4 applications and add a couple of annotations to their sources to try injection. The result of such an experiment is always a NullPointerException since injection is not supported for pre-Java EE 5 applications. For injection to work, they also need to also update their deployment descriptor version to Java EE 5 so annotation processing can happen.

Well, little I knew that JWSDP 2.0 samples needed to run on top of the Application Server 8.1 (with the updated JWSDP bits), therefore that's exactly what they wanted : J2EE 1.4 xml and annotations...

As it turns out, they are using JSR 181 annotations which only their runtime would interpret. Well, JSR 181 being part of Java EE 5, we flagged those and failed deployment.

Here goes my safeguard idea...

So we could still do it, making a small exception case for JSR 181 annotations (since they are optional in J2EE 1.4). However, we also found out that doing this check has a deployment time cost (about 10% performance degradation for pre Java EE 5 applications) but can be turned off if necessary.

Should we do it ?

I would like to hear from the community...

About

dochez

Search

Categories
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