The Source for Java Technology Collaboration
User: Password:



Sahoo's Blog

 Sahoo Sahoo is an engineer at Sun Microsystems, working in Java EE application server development engineering group. He contributes to glassfish project. Besides that he is also involved in writing a portability checking tool for Java EE applications. Prior experiences include working in C++ language binding for an object database management system, developing enterprise applications using CORBA & messaging middleware. Although his full name is Sanjeeb Kumar Sahoo, he prefers to be called by his last name *Sahoo*.



Our second hybrid application - EJB as OSGi Service

Posted by ss141213 on June 16, 2009 at 01:02 AM | Permalink | Comments (0)

Last time, we talked about our first hybrid (Java EE + OSGi) application where we discussed not only about development of hybrid applications including kind of maven plugins to use, deployment steps, etc., but also about the lifecycle of OSGi bundle and Java EE artifacts. Now, it's time for our second hybrid application which demonstrates an EJB as an OSGi service.

Set up
1. Download the latest nightly build of GlassFish v3, install and start glassfish:

java -jar glassfishv3/glassfish/modules/glassfish.jar

2. Start embedded JavaDB by running

glassfishv3/glassfish/bin/asadmin start-database

3. Download "OSGi web container" bundle from here and install it by copying it:

cp osgi-web-container-3.0-SNAPSHOT.jar glassfishv3/glassfish/domains/domain1/autodeploy-bundles/

Sample Application
You can download the complete sample from here. Unzip it. Let's look at the UML diagrams below. The first one is a package diagram showing dependencies, the second one shows the components of the system and the third one shows that they are all deployed in the same node.
uml.jpg
As you can see, we have three modules and the source code organization reflects that as well. Let's briefly go over the modules:
1. common
This is just an OSGi bundle. It exports sahoo.hybridapp.example2 package which contains a single interface called UserAuthService.

2. service
This is a web application bundle, i.e., a hybrid application containing both OSGi and Java EE artifact. It imports sahoo.hybridapp.example2 package. It has following components:
2a. UserAuthServiceEJB This is a Singleton EJB designated to be initialized at startup. It is annotated like this:

@Singleton
@Startup
public class UserAuthServiceEJB implements UserAuthService

Please refer to EJB 3.1 spec for more information on these annotations.
UserAuthServiceEJB has a static variable called

static volatile UserAuthService selfRef;

which is initialized by an ejb reference in the postConstruct() method of the EJB:
    
@PostConstruct
public void postConstruct() {
selfRef = sessionContext.getBusinessObject(UserAuthService.class);
System.out.println("UserAuthServiceEJB.postConstruct: " + selfRef);
}

2b. Activator - This is an OSGi bundle activator which looks up a data source in JNDI, ceates a table there and then registers the EJB reference (selfRef) in OSGi service registry under the service interface sahoo.hybridapp.example2.UserAuthService. For simplicity, we have not used any service properties here.

3. client
This is just an OSGi bundle. It imports sahoo.hybridapp.example2 package. It has an activator which waits for UserAuthService to be available and then invokes it. Look carefully at the activator code and see how it uses ServiceTracker to be notified of service availability. When it sees the service, it invokes it. All this is accomplished in these few lines:


private class UserAuthServiceTracker extends ServiceTracker {
UserAuthServiceTracker() {
super(bctx, UserAuthService.class.getName(), null);
}

@Override
public Object addingService(ServiceReference reference)
{
UserAuthService service = (UserAuthService)context.getService(reference);
service.register("f..", "b..");
return service;
}

}

Build and Test
1. If you don't want to build, then the final artifacts are in target dir, else simply run

mvn clean install
in hybridapp2 directory.

2. To deploy, simply copy the artifacts like this (please note, because of a bug as described last time), while copying the .war file, give it a .jar extension as a work around.

cp common/target/hybridapp2-common.jar glassfish/domains/domain1/autodeploy-bundles/
cp client/target/hybridapp2-client.jar glassfish/domains/domain1/autodeploy-bundles/
cp service/target/hybridapp2-service.war glassfish/domains/domain1/autodeploy-bundles/hybridapp2-service.jar

Since deployment order is immaterial, you can copy them in any order.

Benefits of EJB as OSGi service
1. An OSGi service is able to take advantage of Java EE container services like declarative transaction, declarative security, resource pooling, etc.

2. Local client views of an EJB are accessible from other applications collocated in the same JVM. Please note, since Java EE can not assume a module management system is in place, it takes a safer route of isolated class space for application classes. This does not have to be the case when we are using hybrid applications. We can safely cross application boundaries and call local EJBs.

3. Better modularity of application: as shown here, the app has been broken into three independent deployment units. Once they are deployed, they can be managed (e.g., patched) separately.

4. Deployment order is a thing of past. OSGi takes care of class loading dependencies and then application can take advantage of facilities like Service Tracking to build very dynamic application. As shown in this example:

if client bundle comes up before service bundle, then it simply waits for the service to be available.

You can observe this by removing hybridapp2-service.jar from autodeploy-bundles/ and copy it back.

Continue Reading...



Developing Hybrid (OSGi + Java EE) applications in GlassFish

Posted by ss141213 on June 14, 2009 at 01:02 AM | Permalink | Comments (0)

(If you are in a hurry, then download the sample and jump to "build and test" section after doing the necessary set up.)

In my last blog, I mentioned about adding a new module in GlassFish called "OSGi web container for GlassFish." I am glad to say that, it is fully functional now. I have been able to use JSPs, JSFs, Servlets (of course), annotations, resource injection, transactions, EJBs, etc. in a hybrid application (more on hybrid application below). If you noticed, I mentioned EJBs. Although I call it "OSGi web container," since GlassFish now supports "EJB inside war" as standardized by Java EE 6, the new container allows you to use both Web and EJB components in a hybrid application.

What exactly is a hybrid application? I call an application that uses both Java EE & OSGi a hybrid application. Both the technologies have their strengths. While Java EE excels when it comes to security, transaction management, rich component model, persistence, resource pooling, messaging, etc., OSGi brings modularity, dynamism, life cycle management to the table. They make a very powerful combination. Since their combined use is a new development, to make things easier, I shall walk you through the steps of developing and deploying hybrid applications in GlassFish v3.

Setting the stage:
1. Download the latest nightly build of GlassFish v3 and install.
Installation is nothing but unzipping what you downloaded. Builds are promoted once a week. Since this is a work in progress, there may be some important bug fixes that have gone in since last promotion. So, I recommend you use the latest nightly build. After this step, I suggest you ensure installation was successful by starting glassfish. You can start by running:

java -jar glassfishv3/glassfish/modules/glassfish.jar
or
asadmin start-domain

(You need Java SE 6 to run GlassFish v3)

2. Start embedded JavaDB by running

glassfish/bin/asadmin start-database

3. Download "OSGi web container" bundle from here.
Copy the jar file to glassfishv3/glassfish/domains/domain1/autodeploy-bundles/ dir. You can do this while the server is running and the new module will be started automatically. You can see it in the server's output.

Sample Application
As I stated last time, there are two packaging options. In either case, what you develop is a a Web ARchive (WAR file). In one case, it is a plain vanilla war file, where as in the second case, the war file's META-INF/MANIFEST.MF has OSGi meta data in it that makes the war file an OSGi bundle. Let's consider the second case first, because I see that more often used than the first one while writing hybrid applications. From now on, I will refer to such a war as Web Application Bundle (WAB in short).

Download the complete sample from here and unzip it. Those who don't want to build, the final war file is inside hybridapp1/target folder of the zip file. Let's look at the relevant details:

1. pom.xml
I have used Maven, you are free to use Ant or something else as build tool. The project is laid out as per the default layout of a war project; all the Java classes are in src/main/java, where as web artifacts are in src/main/webapp folder. If you look at the pom.xml, you shall notice that I use maven-war-plugin to package the application as a war file and maven-bundle-plugin to generate the OSGi meta data.

2. Java EE artifacts
The web app contains a couple of servlets, an EJB. It uses Java EE 6 features like @WebServlet to designate a servlet. SO, there is no need for a web.xml. Unfortunately, maven-war-plugin complains if it does not find a web.xml. So, we have an empty web.xml there.

3. Activator.java - the OSGi bundle activator.
A bundle activator is a public class which is instantiated and its start method called when the OSGi bundle is activated (started). So, any application wide initialization can be done here. The reverse happens when the bundle is stopped. In our example, in start method, we lookup a data source using JNDI and create a table in database. In stop method, we drop the table. Important thing to notice is, we are able to use JNDI and JDBC in a bundle activator, which is running outside Java EE context. We will soon talk how the two containers (OSGi container and Java EE container) manage various parts of the same application.

Build and test
Run mvn package to produce target/hybridapp1.war. If you don't have maven, don't worry. The target directory already has the war file. Now copy hybridapp1.war to glassfishv3/glassfish/domains/domain1/autodeploy-bundles/, but while copying rename it to hybridapp1.jar. This is a temporary thing, as there is a bug in the underlying code which does not recognize war files in autodeploy-bundles dir as OSGi bundles. We have a fix, but it has not found its way into a build of GlassFish yet.

That's it. If your server is running, you will see the OSGi bundle getting installed and started as part of which the web application gets deployed. If it is not running, start it for this to happen. You can manage the life cycle of the OSGi bundle by file system commands like cp, rm, touch, etc. See an earlier blog on this. Now that the application is deployed, you can point your browser to

http://localhost:8080/hybridapp1

Follow the registration link and then login link. You can see the server.log to see that user name and password got stored in database.

Now, let's delete hybridapp1.jar from autodeploy-bundles folder. As soon as you do that, server's output will show that the bundle got uninstalled and the application got undeployed as well. Now if you try to visit any of the aforementioned URLs, you will get a 404 error.

Relationship between life cycle of OSGi bundle and Java EE Application
Our war file is both a web application as well as an OSGi bundle, which is why it is called a Web Application Bundle. There are two containers involved here, viz: a) OSGi container, which is managing it as an OSGi bundle, b) Java EE container, which is managing it as a web application.

The actual state transition of the bundle looks like this:
OSGiBundleStateDiagram.jpg

The sequence of events is like this:
When you copy the WAB to autodeploy-bundles dir, it first gets installed in OSGi runtime and the framework tries to start it. On the STARTING event, our "OSGi web container" picks it up and deploys it in Java EE runtime after which point OSGi runtime calls the activator's start method and the bundle goes into ACTIVE state.
When you remove the WAB from autodeploy-bundles dir, the bundle gets uninstalled. Of course, uninstall is a superset of stop, so it is stopped first. As part of stopping, the stop method of activator gets called. Once activator.stop returns, STOPPED event is raised and the application gets undeployed from Java EE runtime. Then the OSGi bundle goes into RESOLVED state.

Understanding bundle life cycle and deployment sequence
To have a better understanding of the life cycle and the deployment sequence, let's switch to a more direct mode of operation. Instead of using autodeploy-bundles directory to manage the bundle, let's directly interact with the OSGi runtime. There are two options, viz:
a) we can use Felix shell over telnet protocol,
b) we can use the Felix Web Console.

I will use the former one as I prefer command line tools.
Start glassfish and remove example1.jar from autodeploy-bundles/.
Run these commands (comments are enclosed by ()):

telnet localhost 6666
ps
install file:///tmp/hybridapp1/target/hybridapp1.war
start
(Now you can see the web application getting deployed. Access the URLs at this point of time.)
stop
(The web app gets undeployed and URLs are no more accessible.)
start
(It is back again)
uninstall
(The bundle gets removed from the system.)

I hope this is sufficient for you to get started. Now, let your imagination take over and let us know how you are able to take advantage of this hybrid approach. In my next article, I show how you can use an EJB as an OSGi service.

Continue Reading...



OSGi enabled web applications inGlassFish

Posted by ss141213 on June 04, 2009 at 03:29 PM | Permalink | Comments (0)

Since the OSGi-fication of GlassFish started, the initial response was very encouraging, but we were often asked as to how we planned to expose the benefits of OSGi platform to end users in a more direct way. We are committed to making this possible as is evident from the following quote from our initial proposal:

"If GlassFish can benefit from OSGi, why not applications deployed in GlassFish? Application developers would like to use sophisticated versioning, class loading, dependency management and component model of OSGi. There is a growing demand for servers that expose such facilities to application developers. So, we shall investigate the use of OSGi by applications."

I am glad to say that we have made considerable progress in this area. I just now put back a very preliminary implementation of OSGi EEG RFC #66 in GlassFish workspace that allows web applications (war files) to be deployed as OSGi bundles and there by taking advantage of OSGi platform as well as Java EE platform. Web applications and OSGi is a subject which is being actively discussed in OSGi Enterprise Expert Group (EEG) as RFC #66. As I said, what I have put back is just the start. Basic servlet. JSP, JSF, JDBC, JNDI, etc. works. Injection should work, but I have not tried yet. I know for sure JPA does not yet work as JPA classloading requirements conflict with OSGi's. Work is in progress to resolve it - stay tuned. So, how do you use these features in GlassFish? There are basically two starting points:

a) You have a plain vanilla war file.

b) You have a war file that has OSGi metadata in it.

In the former case, you have to somehow instruct the server that it has to add necessary OSGi metadata to the war file. You should also be able to customize the transformation step. It is achieved by use of a special URl protocol called webbundle together with use of URL query parameters. The server has a custom URL handler for this protocol and it does an in place manifest rewrite when it encounters this scheme. To use it, you can do something like this in GlassFish:


telnet localhost 6666
install webbundle:file:///tmp/mybundle.war
start #bundle_id

(telnet support in GlassFish is provided by use of remote shell as described here.)

The above commands will make your web app available at localhost:8080/mybundle/. Now you can control the life cycle of the web app via the OSGi bundle. e.g., if you stop the bundle by issuing stop #bundle_id, the web app gets undeployed. To deploy it again, issue the start command.

In the latter case, i.e., case #b above, you just have to add a specific meta-data called Web-ContextPath in the manifest.mf to mark the OSGi bundle as a Web Application Bundle, (WAB) in short. Once you have done that, you can either install and start by running the shell commands without using webbundle protocol or simply copy the bundle to glassfish/domains/domain1/autodeploy-bundles/ dir. How this directory works is already described in a previous blog.

Although I want to write more now, it's pretty late here. SO, catch you soon with instructions to install the new feature in GlassFish with some concrete example. Thanks.



Running GlassFish on other OSGi platforms

Posted by ss141213 on May 30, 2009 at 12:05 PM | Permalink | Comments (0)

Although GlassFish v3 Preview comes with Felix pre-installed, it's pretty easy to make it run on Equinox and other platforms. Given below are the simple steps...

1. Download Equinox or if you have it, use that.

2. cp org.eclipse.osgi_3.3.2.R33x_v20080105.jar $GlassFish_HOME/osgi/equinox/
(replace 3.3.2.R33x_v20080105 by the actual version found in jar name in your equinox installation. It changes from version to version.)

3. Start GlassFish, but while starting let it know that you want to run on Equinox, else by default it uses Felix. To do this, you have couple of choices:

a) You can set an environment variable called GlassFish_Platform as Equinox.

b) You can set a system property called GlassFish_Platform as Equinox.

Why do we have these two options? The system property is handy when you are starting using "java -jar" command. The environment variable is useful when you are starting using the classic way, i.e., "asadmin start-domain."

Putting them in practice: (I am using Bash shell in the following example)
1. In the following example, we set the option once in the environment and every subsequent use of "asadmin start-domain" starts GlassFish on Equinox.


export GlassFish_Platform=Equinox
asadmin start-domain

2. In the example below, asadmin start-domain is used to start GlassFish, but you are able to specify the enviornment variable on the same command.

GlassFish_Platform=Equinox asadmin start-domain

3. If you are used to "java -jar" style of starting GlassFish (a new thing in GlassFish v3), then do this:

java -DGlassFish_Platform=Equinox $GlassFish_HOME/modules/glassfish.jar

Frequently Asked Questions:

1. What is the order of precedence?

In our bootstrap code that decides which platform to use, System property takes precedence over environment. So, if you set GlassFish_Platform in both system property and in environment, system property wins.

2. What are the allowable values for GlassFish_Platform?

The set of acceptable values are statically defined in an Enum like this:
public enum Platform {Felix, Knopflerfish, Equinox, Static}

So, you can specify any one of them. The default value is Felix.

3. What platform does "Static" mean in the above Enum?

Well, GlassFish can run without OSGi as well. Static refers to that mode. There appears to be some use case for this mode.

4. OK, I see Knopflerfish being mentioned as one of the platforms. How can I run on that?

When we started our OSGi effort, we were using only R4 APIs and hence we could run on all three popular, open source OSGi platforms. Later on, we had to rely on some R4 version 4.1 APIs - to be precise, on "transient" start/stop of bundles supported via new API called Bundle.start(int), Bundle.stop(int). Knopflerfish still does not implement them. Last time, when I checked with them, they told that they will switch from R4 to R4.2 directly. So, latest GlassFish v3 (something like GlassFish 3.0-Preview) does not currently run on Knopflerfish. Having said that, GlassFish 3.0-Prelude can run on Knopflerfish.

5. Where do I find configuration file for each platform?

Here is where you can locate the configuration files:
Felix -> glassfish/osgi/felix/conf/config.properties
Equinox -> glassfish/osgi/equinox/configuration/config.ini
Knopflerfish -> Not available, as latest GlassFish does not run on it.

6. Must I have my OSGi framework jars copied to GlassFish installation directory? What if I am sharing an installation and don't have permission to change the installation?

No, you don't have to copy the OSGi framework jars to glassfish/osgi directory. You can keep them on a separate location and refer to that using environment or system variables. e.g., you can do this:
mkdir /usr/equinox
cp org.eclipse.osgi_3.3.2.R33x_v20080105.jar /usr/equinox/
cp -r glassfish/osgi/equinox/configuration/ /usr/equinox/
java -DGlassFish_Platform=Equinox -DEQUINOX_HOME=/usr/equinox/ glassfish.jar

Of course, you can set those properties using environment variables as well if you don't want to set them every time.

7. While running on Equinox, I get a WARNING like this:
WARNING: Failed to install .../glassfish/modules/osgi-main.jar because of org.osgi.framework.BundleException: Bundle "com.sun.enterprise.osgi-main" version "0.3.64" has already been installed from: initial@reference:file:../../modules/osgi-main.jar/

It is coming because our management agent, which goes through modules dir to install all the modules, is trying to install a module called osgi-main.jar, but that module is already configured in config.ini to be autostarted. You can safely ignore the warning.

8. How do I add support for other OSGi platforms?
Currently, you have to make some changes in our bootstrap code to achieve this. To be precise: in two files: ASMain.java and a new file that you need to supply. This is because of lack of standard way of starting OSGi frameworks. Work is in progress in OSGi Core Platform Expert Group under RFC #132 to have a uniform API to start a framework. Once it is available as part of OSGi R4.2 platform, we will switch to it and integration with other frameworks will be much smoother.

Conclusion
Happy GlassFish-ing. As usual, please refer to The Aquarium for more information about GlassFish suite of projects and products. Your feedback is always welcome.



Use of Framework Extension Bundles in GlassFish V3

Posted by ss141213 on May 29, 2009 at 08:49 AM | Permalink | Comments (0)

When you run an application in a plain vanilla Java platform, your code can access publicly visible internal JDK classes. While I understand it is a bad thing, but I do understand that sometimes developers have genuine reasons to access those internal APIs. e.g., our security module in GlassFish has to use some of the JDK Security classes. When one moves those programs to an OSGi environment, the assumption that every public JDK class is always visible to applications goes for a toss. When we started with our OSGi effort in GlassFish V3, we immediately faced the problems. So, how does one manage the situation? There are basically two ways to manage it in OSGi, viz:

a) Parent Delegation:
Parent Delegation is controlled by a system property called org.osgi.framework.bootdelegation. It contains a list of package names, which allows use of wildcard (*) to help keep the property value to a manageable size. When OSGi framework tries to load a class for a bundle, if the class belongs to java namespace, it immediately delegates to parent classloader. If the class does not belong to java namespace, it consults the aforementioned property. If it is mentioned there, it delegates to parent class loader. Else it goes through a very well defined sequence to locate the class failing which it throws ClassNotFoundException or NoClassDefFoundError or a similar exception.

b) system packages:
Now, let's look at system packages. There is a special bundle in the OSGi runtime which is known by Bundle-SymbolicName:system.bundle. This bundle like other OSGi bundles can export packages. It is used to export packages, such as framework APIs, JDK APIs, available in parent class loader. As a result, it allows the parent class loader to be teated as yet another bundle. Those exported packages can then take part in normal OSGi package wiring process. The list of packages that can be exported are controlled by a system property called org.osgi.framework.system.packages. If I am not mistaken, in the upcoming R4.2 spec, CPEG is defining a new property called org.osgi.framework.system.packages.extra, but that's not important for this discussion.

Please consult the OSGi spec for accurate description of these features. The spec is very nicely written. The description above is not as clear as you will find in the spec, which is obvious.

Parent Delegation is a necessary evil. It is there to primarily help avoid strong assumptions made by some JDK classes about class loading, but it is also helpful in solving class loading problems as explained in one of my earlier blogs. It breaks modularity, so it should be used at the last resort. So, we decided to use the second option.

In the second option, there is also a challenge. How do we know the list of all such internal packages? The list is a union of internal packages needed by all the modules running in GlassFish. There lies the problem. The list of modules is not fixed. After all, GlassFish V3 has multiple profiles (or distributions), e.g., web profile, classic profile, etc. The problem is compounded by the fact that user can install new modules and they may have newer requirements about system packages. So, managing them via a single property does not scale. Fortunately, framework extension bundles come to the rescue.

framework extension bundles
Framework extension bundle is a special type of bundle fragment. It can only attach to system bundle. So, it must have Fragment-Host set as either system.bundle (which portably identifies system bundle in all OSGi platforms) or use a framework specific name for system bundle and it must have extension attribute set to framework. e.g., the following header will do:

Fragment-Host: system.bundle; extension:=framework

There are restrictions about what headers it can use, but like any other fragment, it can use Export-Package header to export additional packages. All those additional packages eventually get exported via system bundle only. Now, imagine this: system bundle is already backed by parent class loader. It actually has access to all the classes loadable via parent class loader, but for modularity reasons, it does not export all of them. If you want some packages to be exported by system bundle, just come up a framework extension bundle which contains no actual class. It only contains some manifest headers like this:


Fragment-Host: system.bundle; extension:=framework
Export-Package : sun.security; uses:="foo, bar"; version=1.0

Isn't this a powerful technique? This is actually one of the very few good use cases for fragment bundles. This allows us to decentralize the information which is so important in an extensible system like GlassFish V3. More over, system properties can't be controlled when a program is embedded in a host JVM.

GlassFish use case
What we do in GlassFish is we define org.osgi.framework.system.packages to contain the standard Java SE platform API packages only. We then install one or more extension bundles that are used to make internal JDK classes available via system bundle. Take a look at one written for EclipseLink's Oracle extensions



LinkageError caused by org.omg.CORBA package in OSGi environment

Posted by ss141213 on May 27, 2009 at 02:17 AM | Permalink | Comments (0)

Recently my colleague observed an unusual class loading error while experimenting in GlassFish V3. I really enjoyed analysing the issue and getting to the root of the problem. I will share my experience here.

JDK has a portion of OMG CORBA APIs belonging to org.omg.CORBA and similar package names. The bad thing is org.omg.CORBA package is an extensible package in the sense that different OMG CORBA services contribute classes to this package. I guess this is because they share the same IDL namespace and hence IDL compiler generates the same package name for all of them. Given that JDK does not have all the OMG CORBA services, not all org.omg.CORBA classes are part of JDK. e.g., CORBA Object Service - Transaction is one example. It is not there in JDK, yet it is required in an Java EE environment, as Java Transaction Service depends on it. So, our CORBA engineer produced an OSGi bundle called glassfish-corba-omgapi which contained all the org.omg.CORBA apis needed by GlassFish v3. The system.bundle also exports org.omg.CORBA package. Both the bundles exported with same version, which in itself is a mistake. If you are following me so far, then you can see that org.omg.CORBA package is exported by two bundles with identical version:
glassfish-corba-omgapi and system.bundle

Our JTS engineer realized that her JTS module is always importing org.omg.CORBA from system.bundle (this is a correct behavior) and hence she is not able to locate some COSTransaction class. To work around it, she removed org.omg.CORBA from org.osgi.framework.system.packages list, as a result now only glassfish-corba-omgapi bundle exports org.omg.CORBA package. Although this made the COSTransaction classes available, it resulted in the following LinkageError:


java.lang.VerifyError: (class: org/glassfish/enterprise/iiop/impl/GlassFishORBManager, method: initORB signature: (Ljava/util/Properties;)V) Bad type in putfield/putstatic
at org.glassfish.enterprise.iiop.impl.GlassFishORBFactoryImpl.postConstruct(GlassFishORBFactoryImpl.java:29)
at com.sun.hk2.component.AbstractWombImpl.inject(AbstractWombImpl.java:170)

Now the investigation begins.
javap -classpath orb-iiop.jar -p -c org.glassfish.enterprise.iiop.impl.GlassFishORBManager
shows the following bytecodes:


495: invokestatic #114; //Method com/sun/corba/ee/spi/osgi/ORBFactory.create:([Ljava/lang/String;Ljava/util/Properties;Z)Lcom/sun/corba/ee/spi/orb/ORB;
498: putfield #2; //Field orb:Lorg/omg/CORBA/ORB;

Basically, it translates to something like this:

org.omg.CORBA.ORB this.something = com.sun.corba.ee.spi.osgi.ORBFactory.create(properties);

As you can see com.sun.corba.ee.spi.osgi.ORBFactory.create(Properties) returns com.sun.corba.ee.spi.orb.ORB, which definitely extends org.omg.CORBA.ORB for the code to compile. So, let's inspect the hierarchy of this class:

(-> means extends and within bracket the jar that supplies the class is mentioned as well. Each jar has a separate class loader)


com.sun.corba.ee.spi.orb.ORB (glassfish-corba-orb.jar)
-> com.sun.corba.ee.org.omg.CORBA.ORB (glassfish-corba-omgapi.jar)
-> org.omg.CORBA_2_3.ORB (JDK's rt.jar)
-> org.omg.CORBA.ORB (JDK's rt.jar)

Note a *duplication* of class in the runtime:
glassfish-corba-omgapi.jar exports org.omg.CORBA package and has org.omg.CORBA.ORB.class in it.
JDK's rt.jar also has org.omg.CORBA.ORB.class.

Since org.omg.CORBA is no longer exported by system.bundle, GlassFishORBManager, which is loaded from org-iiop.jar module, gets org.omg.CORBA.ORB.class from glassfish-corba-omgapi.jar. As a result, the simple assignment is now looking like this:

org.omg.CORBA.ORB(glassfish-corba-omgapi.jar) = org.omg.CORBA.ORB (JDK's rt.jar)

As you can see, they are two different types and hence the VerificationError.

There are several ways to solve it.
1. If we add a *bootdelegation* property for org.omg.CORBA package, then everyone will see org.omg.CORBA.ORB from JDK's rt.jar and that will address the issue. Although this solution looks simple, it is not preferred, as it is a violation of modularity principle. More over, it leads to split packages which can lead to other issues at runtime like access violation of package scoped objects.

2. If we remove all the org.omg CORBA related packages (including org.omg.CORBA_2_3) from system packages list and ensure that they are exported by glassfish-corba-omgapi bundle, then also every one will see one version of classes and the problem will be solved. There is an assumption here that no other JDK class other than the CORBA implementation has direct reference to these packages. This assumption may not be true.

3. If we can put glassfish-corba-omgapi.jar in one of the java.endorsed.dirs and add all the new packages to system.packages list, then also everyone see one consistent version of classes. Since we can't assume we are using jre/lib/endorsed, this has the disadvantage of requiring user to specify -Djava.endorsed.dirs in command line, something which does not fly with "java -jar glassfish.jar" style invocation.

For now, I think we can start with option #2 and if we face any issues, we can go to #1.

Now let's see why the error was so cryptic in an OSGi environment. After all, OSGi is supposed to give us more helpful errors. The problem is our system packages are exported without any "uses" clause. "uses" clause plays a vital role in package resolution and correct specification of uses attribute might have given us a better error stating the class space was not consistent.

Having said that, I still don't understand why we didn't get a "loader constraint violation" when GlassFishORBManager was loaded. Is this because ORBFactory returns com.sun.corba.ee.spi.orb.ORB, where as GlassFishORBManager has a field of type org.omg.CORBA.ORB? Needs further investigation. Interested readers should look at the excellent classloading discussion by Liang and Bracha.



Be careful while using EntityManager.getDelegate()

Posted by ss141213 on May 25, 2009 at 02:01 AM | Permalink | Comments (2)

Recently a GlassFish user, who is using Hibernate JPA provider, asked how they can access the underlying Hibernate Session object from the injected EntityManager object. My answer was to use:

org.hibernate.Session session = ((org.hibernate.ejb.EntityManagerImpl) em.getDelegate()).getSession(); 
.

If it is that simple, why am I making an issue out of it? It is a highly non-portable API and you really have to write different code in different application servers even while using the same persistence provider. Well, read on to find out why...
Look at the javadocs of getDelegate() and tell me what it returns. The javadoc says it returns "the underlying provider object for the EntityManager." What does that mean? That's the subject of discussion.

In enterprise platform, when you look up and EntityManager in JNDI or when your component is injected with an EntityManager (by using @PersistenceContext), you really don't get the actual EntityManagerImpl of the provider. What you typically get is a wrapper which acts a frontend to the underlying object. The reasons for having such a wrapper are manifold. e.g., the wrapper is designed as a Serializable object so that it can be bound in JNDI, where as the provider's implementation may not be. More importantly, it's the wrapper which implements the EE semantics like persistence context propagation. If you are interested in looking at how such a Wrapper looks like, take a look at this GlassFish Wrapper implementation. As you can see, in GlassFish, getDelegate() returns the underlying provider's EntityManager implementation. So, if you are using Hibernate in GlassFish, then getDelegate() returns org.hibernate.ejb.EntityManagerImpl

As a result,


((org.hibernate.ejb.EntityManagerImpl) em.getDelegate()).getSession()
returns Hibernate Session object in GlassFish.

But, the above code would not work in JBoss. They suggest the following:


org.hibernate.Session session = (Session)manager.getDelegate();

It is difficult to say which implementation is correct, when the spec, in the javadoc of getDelegate, calls out the non-portability of the API like this:
"The result of this method is implementation specific."

Lack of clarity of the spec leads to pain for programmers. You think you have written to JPA spec and your code is portable as long as you are using Hibernate JPA provider, but it is not. It now varies from one application server to another. I would really love to know what WebLogic and WebSphere return for the above method, but that's a separate point. Actually, once a user filed the following bug in GlassFish:
https://glassfish.dev.java.net/issues/show_bug.cgi?id=2923, but we could not fix it because we think there is an advantage of the current implementation. Since we can't really say one of the two implementations is at fault, let's analyse the pros and cons of the two implementations.

From a design pattern point of view, the wrapper should call underlying object's method. So, this mean, EntityManagerWrapper.getDelegate() should call delegate.getDelegate(). It is a more logical choice. I guess this is what happens in JBoss, but in GlassFish, we return the delegate itself. But, returning the delegate in getDelegate() (just like what GlassFish does) means user now have access to to a much richer set of APIs that what is available via javax.persistence.EntityManager. One such extra API could be to get the Session object. So, I am inclined to favour GlassFish's implementation.

I really wish this is something that gets addressed in the upcoming JPA 2.0 spec. If it has already been addressed, even better. Please don't make the programmer suffer. They don't always have the time and resource to get to the underlying problem and they end up making value judgment about implementations.



Using Felix Web Console in GlassFish v3

Posted by ss141213 on May 05, 2009 at 04:25 AM | Permalink | Comments (2)

In a previous blog, I had shown how one could use Apache Felix Remote Shell to connect to GlassFish and administer the underlying OSGi runtime. Since, GlassFish installs some 100 odd bundles, it is not very easy to explore them using the shell. There are some improvements planned for Felix shell to address this issues, but then there are a lot of people who are just comfortable with GUI as opposed to CLI. For them, we have an answer - use Apache Felix Web Console.

One of the primary requirements to use Felix Web Console is an implementation of OSGi/HTTP Service. I have made available an initial implementation of the OSGi/HTTP service on top of GlassFish web container. So, we are all set to use Felix web console in GlassFish v3.

Steps to install & use Web Console

1. Download GlassFish OSGi HTTP Service bundle from http://download.java.net/maven/glassfish/org/glassfish/web/osgi-http/3.0-SNAPSHOT/osgi-http-3.0-SNAPSHOT.jar.
If you are using v3-Preview builds, then replace 3.0 by 3.0-Preview in the above link.

2. Download Apache Felix Web Console bundle from here.

3. Copy these two jars to glassfish/domains/domain1/autodeploy-bundles/ dir.
I have already mentioned in one of my previous blogs, how one can use copy and rm command to deploy/undeploy bundles in GlassFish v3.

Now, the bundles are up & running. Don't worry about some messages like Failed to instantiate plugin org.apache.felix.webconsole.internal.misc.ConfigurationRender. Reason: java.lang.NoClassDefFoundError: org/osgi/service/prefs/BackingStoreException appearing in the log.

4. Point http://localhost:8080/osgi/system/console/bundles in your favorite browser. Use admin/admin as username/password combination.

How does the web console look
Let me show you some screenshot of the web console. Screenshot below shows the bundles page. You can sort the bundles based on id, name, status, etc. You can clink on individual bundle link to see details of that bundle as shown in fig #2.

webconsole1.png

Screenshot below shows details about a particular bundle. You can see wiring details here, i.e., which bundles are importing packages from this bundle. I find this information very useful.

webconsole2.png

You can find a lot more screenshots in Web Console homepage.

Please wait for 5th may 2009 nightly build of GFv3 to be out before you try out, as I fixed a stopper bug in HTTP service. As usual, your feedback is always welcome. Happy GlassFishing.



Using filesystem operations to manage OSGi bundles in GlassFish

Posted by ss141213 on May 03, 2009 at 11:51 PM | Permalink | Comments (1)

A few days back, Jerome blogged about how to deploy OSGi bundles in GlassFish using "asadmin deploy --type=osgi" command. In his blog, he also mentioned why you should not copy your bundles to glassfish/modules directory. In this blog, I will talk about a filesystem based management agent that I have integrated in GlassFish and how you can take advantage of the same.

We have integrated Apache Felix File Install in GlassFish v3. It is a simple yet very powerful bundle. It even takes care of the dependencies among bundles. It can use "configuration admin service" to configure bundles by reading configuration data from properties file placed in the watched dir. Quoting from File Install homepage verbatim:

It uses a directory in the file system to install and start a bundle when it is first placed there. It updates the bundle when you update the bundle file in the directory and, when the file is deleted, it will stop and uninstall the bundle.

File Install can do the same for configuration files.

In the default installation of GlassFish v3, we have configured FileInstall to watch a directory called ${domain_dir}/autodeploy-bundles. ${domain_dir} typically expands to glassfish/domains/domain1, but it really depends how you have configured GlassFish. This is very similar to autodeploy directory that exists in GlassFish for non-OSGi JavaEE applications. Basically, it works like this:

You copy a bundle (a .jar file) to the watched dir (autodeploy-bundles) -> the bundles gets installed and then get started.
You modify the bundle in the watched dir -> the bundle gets updated.
You remove the bundle from the watched dir -> the bundle gets stopped and uninstalled.

To watch some other directory (let's say /tmp/bundles), create a properties file with following content and name it as org.apache.felix.fileinstall-something.cfg and copy it to autodeploy-bundles dir:

# directory to watch
felix.fileinstall.dir=/tmp/bundles/
# Time period of fileinstaller thread in ms.
felix.fileinstall.poll=5000
# debug level
felix.fileinstall.debug=1
# should new bundles be started or installed only? true => start, false => only install
felix.fileinstall.bundles.new.start=true

You will immediately see fileinstall creating /tmp/bundles and dedicating a thread to watch it.

If you want to explore this feature, I suggest you take a look at File Install homepage.

This feature is not available in any promoted builds yet; you will find it in trunk nightly builds of GlassFish v3 after 5th May 2009 or in promotion #b47a onwards.
Watch out the nightly build area or promoted build area. Happy



June 2009
Sun Mon Tue Wed Thu Fri Sat
  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        


Search this blog:
  

Categories
Community: Glassfish
Community: Java Enterprise
Community: JDK
J2EE
J2SE
Archives

June 2009
May 2009
February 2009
May 2008
April 2008
January 2008
November 2007
November 2006
October 2006
July 2006
May 2006
March 2006
January 2006
December 2005

Recent Entries

Our second hybrid application - EJB as OSGi Service

Developing Hybrid (OSGi + Java EE) applications in GlassFish

OSGi enabled web applications inGlassFish



Powered by
Movable Type 3.01D


 Feed java.net RSS Feeds