Friday Apr 01, 2011

GlassFish 3.1 released

GlassFish 3.1 was released, find it at http://glassfish.java.net/downloads/3.1-final.html

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 Jun 09, 2009

GlassFish V3 Extensions, part 4 : OSGi Declarative Services

Neil Bartlett was absolutely right that my last entry might have been a little too deep so I am simplifying the whole example in this entry by using plain OSGi Declarative Services in GlassFish v3. Declarative Services are described by Neil there and even more concisely by Peter Kriens with bnd at this location.

So I am going to have 2 modules in this example :

  • service bundle, this is my plain OSGi bundle, which packages two classes, the API and one implementation of that API. 
  • webclient, plain war file that use Java EE injection to access the OSGi declared service in the above service bundle.
Files can be downloaded there, there are two sub directories for each module. 

OSGi Declarative Service bundle

The OSGi bundle project is using maven to build as usual with GlassFish V3, the project contains 5 files

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

 Let's dive in the content now, first the service definition (unchanged from last entry) :

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

The powerful implementation is using a different package and consist of the following java class :

package examples.services.impl;
import examples.services.api.SimpleService;
public class SimpleServiceImpl implements SimpleService {
    public String getString() {
        return "Simple Declarative Service implementation at your service !";
    }
} 

now the serious things can start, first with the manifest file containing the OSGi metadata :

Bundle-Version: 1.0
Bundle-SymbolicName: examples.services.declarative
Bundle-Name: Services definition bundle for OSGi Declarative Services in GlassFish
Export-Package: examples.services.api
Service-Component: OSGI-INF/simpleservice.xml
Bundle-ManifestVersion: 2 

Two things are worth mentioning, first only the API package is exported, the implementation package is a private entity of the module. Encapsulation is one of the benefits of modularization. Second the "Service-Component" entry points to a separate xml file describing the services provided by this module (hence the name Declarative Services I suppose). 

The content of the service definition file, is defined by the OSGi alliance specification, in this example the resulting xml is pretty simple :

<?xml version="1.0"?>
<component name="decl-service-1" immediate="true">
	<implementation class="examples.services.impl.SimpleServiceImpl"/>
	<service>
		<provide interface="examples.services.api.SimpleService"/>
	</service>
</component> 

Note that I gave a name (decl-service-1) to that service implementation, the curious reader should now experiment with creating more than services implementations, giving a different name to each of them. Build the project (mvn install).

The Java EE client

Very similar to the last blog entry where I was using Java EE injection (through the @Resource annotation), the webclient has not changed much :

import ...
import examples.services.api.SimpleService;
@WebServlet(urlPatterns={"/hello"})
public class HelloWorld extends HttpServlet {
    @Resource(mappedName="decl-service-1")
    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);
 	    if (simpleService!=null) {
		pw.println("SimpleService says " + simpleService.getString());
		pw.println("<br>");
	    }
	} catch(Exception e) {
	    e.printStackTrace();
	}
    }
} 

Needless to say that the servlet is not importing the implementation package, just the API. In fact even if it tried, it would fail at runtime (not compile time unfortunately until JDK 7 starts supporting modules and OSGi metadata) since only the API package is exported by the bundle. Another mvn install to get the resulting war file.

Getting things together

GlassFish V3 does not ship with all the OSGi services, just the basic runtime, so first, to be able to use OSGi declarative services you need to download the support for Declarative Services for Felix from there , you will need to take the SCR jar file. Once downloaded you should deploy it to the application server and deploy the service bundle as well as the webclient web application (they should be in the respective target directories of your project if you built successfully)

asadmin deploy --type osgi org.apache.felix.scr-1.0.8.jar
asadmin deploy --type osgi simple-declarative-service.jar
asadmin deploy webclient.war

now point your web browser to http://localhost:8080/webclient/hello

Service class is interface examples.services.api.SimpleService<br>
First service is examples.services.impl.SimpleServiceImpl@ec0c06f 
SimpleService says Simple Declarative Service implementation at your service ! 

Now combine this with the example of my last blog entry, you can see that I can now have my service API implemented either with a Spring component, or by a plain old OSGi Declarative Service and the actual implementation location will be immaterial to the servlet client code. Ah ! a good service based architecture can solve many problems just like a level of indirection can often lead to better code...

My next entry ? Maybe implementing my service with an EJB component, and show how one service can be implemented by a Spring bean, by an OSGi Declarative Service and by an EJB and have all three of them injected in the same servlet instance and be invoked transparently by the servlet code... would you be interested ?

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 

Friday Feb 22, 2008

New GlassFish V3 Milestone

We just pushed out a new V3 milestone, it's available at https://glassfish.dev.java.net/downloads/v3-techPreview-2.html.

Of course I need to apply the usual warnings, this is a milestone build, we know there is a lot of thing not working or not reliably working... So the intent of this build is really for people to get a feel about the V3 user experience, you can start it, deploy web applications, and if you are all lucky this will all work. I would certainly not recommend using V3 today for any real development/deployment activity. This is also the first weekly promotion of V3, we will now promote weekly build to keep followers with the latest bits without having to build the workspace.

Features that are included in this milestone are web container related technologies excluding JSF for now. We do support the Java SE persistence, JRuby on Rails applications, multiple http listeners, virtual servers configuration.

The list of supported commands are here, the supported containers are Web and JRuby on Rails, check my earlier blogs or Arun's screencasts.



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 Oct 15, 2007

The Road To Mercurial


As we have already stated, eventually GlassFish will move to Mercurial (Hg) as its primary source code management (SCM). However the road to Hg has proven more difficult than expected but let me start with why we need to move out from CVS.
  1. - CVS is fairly incompetent at moving files. With GlassFish v3, we will soon be changing the shape of the workspace to reflect our modularization effort and to stick closer to our new build system, maven2. So files will be moved around (possibly several times) until we stabilize the new brownian motion of modules relationships and without owning the cvs server (owned by java.net), we would have lost cvs history each time.
  2. - Hg is a distributed source code management system which is an advantage when dealing with massive projects like GlassFish.
  3. - Hg has the changeset concept where changes are treated as a group of related changes to several files which makes tracking and rollbacking a lot easier.
In fact, Sun is moving most of its open source projects to Hg, OpenSolaris and OpenJDK for instance so it's only natural we also move to this new SCM.
 
However moving is a difficult task, mainly because the tools to transfer the cvs history to mercurial are not capable of handling such a big repository as GlassFish V2. On top of that, our open source project host, java.net, cannot work with mercurial yet forcing us to manage our own infrastructure for user authentication, servers, and backup. We have better things to do...

So we have decided to move to Subversion ! Ok I know it sounds weird but hear me out :
  1. - java.net supports svn projects so no infrastructure work for us.
  2. - tools to move cvs history to subversion are very mature and worked flawlessly in our trial attempts.
  3. - in subversion, we can move files around without loosing history.
  4. - all IDEs in the universe supports subversion so our programmer's community don't get too impacted.
Does that mean we abandon Hg for subversion. No, the plan is still to move to Hg at some point. In particular, once we have settled our modules, we want to split the GlassFish repository in possibly 3 or 4 different java.net projects each with their private source code management. We think that creating new java.net projects will be a great time to move to mercurial.

So you have the full story, GlassFish developer, get to learn subversion for the time being and keep an eye on Mercurial.

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 09, 2007

My Own Bileblog ?

So I am at JavaOne, introducing HK2 and GlassFish V3 but today, I really ponder, should I create my own Bileblog ? It really started on JavaOne Day 0 when I went to the Groovy and Grails nfjs meeting.

It was ugly, bad demos looking to be revamped from demos I was doing with VB and the Java Plugin back in 98, panelists full of attitudes, the audience was actually rioting and challenging everything they were saying, but that did not seem to deter them much.

I was rolling on the floor laughing at the idiotic statements of Neal Ford, I sincerely hope that he was under the influence of some illegal substance (this was in san fran after all) because if he believes :
  • since all talented programmers (like him) do 100% unit tests, strong typing is just bureaucracy to satisfy the compiler. Oh right, let's replace the checks the compilers do for us with some good old tests we have to write manually, and anyway who ever do test 100% of their software, nasa maybe, boeing and airbus hopefully but nobody I know.

  • Nobody needs an IDE, they are just a nuisance created to make strongly typed language bearable, seems like these superstars of programming never needed any code refactoring of any sort. And they probably never worked with teams of more than 2 self proclaimed code artists.

And that was sad, because Guillaume Laforge is such a nice guy and Groovy could have a stronger position in the dynamic languages community with its natural integration with Java, its support for strongly type and untyped programming styles. So instead of reducing Groovy to just a pure untyped OO language, I think they should play the two faces of the coin, use types when you need them and keep the dynamic code for the integration, agile code that need many fast changes.

Anyhow, I will work soon to make Grails work in GlassFish V3, I am not as close minded as some folks I saw that evening.

But I really have high respect for Hani because it is not easy to do a good BileBlog, look at Cedric pathetic attempt to rant here, just plain sad, he really is smarter than that when you talk to him, he probably had to many vodkas the evening before writing his blog at the Sun party at the W. Doing a good Bileblog takes good knowledge of the technology and characters, and certainly no hangover...

Ok I have to confess that maybe I like Hani because he never biled me, I suppose I am too obscure to be his satire victim, but even if it happens, I think that just like a child I should take it as : negative attention is always better than no attention.

And no, I certainly don't consider Hani a paternal figure, good lord !

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: ,
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