Art of Conversation – Part 1

It has been a while since my last blog. A combination of work and reimagining conversation support led to this hiatus. After the last blog, I wanted to do a series on the applicational aspect of Vorpal viz. how do you go about using the various features in Vorpal to implement a custom XMPP service. However I found IQ support wanting; in particular correlating IQ request/response to be really tedious. I’ve also felt, for quite sometime now, that my initial design for conversation support which I blog about here to be extremely simplistic. So I took the opportunity to redesign these.
The good news is that if you are using previous version of Vorpal to develop your application, nothing apparent have change; everything should works as is. If you have any issues, please open an issue or post your problem in the forum. Bad news? Conversation support is quite tricky because it affects the framework greatly so if you find any NPE which wasn’t in earlier releases of Vorpal, please let me know.
Rather than writing a long blog on conversation, I’m going to break this subject into 3 or 4 blogs convering concepts, implicit and explicit conversations and interactions between these.

What are Conversations?

What is the purpose of conversation? Simply put conversation allows a Vorpal application to keep states about an interaction between 2 jabber entity. This is very similar to HTTP session support using HttpSession. In Vorpal states can be kept in ConversationContext, very similiar to HttpSession, and/or in stateful objects marked with @Conversation (think Stateful Session Bean). Every conversation is marked with a unique conversation id.
The default conversation provider gets the conversation id from the following 
  • when there is a <thread> element in <message>. This is part of the XMPP standard. See XEP-0201.
  • or by using implied conversation id support between any 2 Jabber entities when <thread> element is missing. 
All packet falling under the same conversation (viz. having the same conversation id) will be able to access to the same state information stored in ConversationContext or @Conversation message handlers.
The way implied conversation id works is by examining the to or from of a packet and figure out a thread id from there. Vorpal will first look for 
  • conversation between an entity and a chat room (ok an entity as well). It does this by looking for the following pattern ‘@conference.‘ in either the from or to. If it finds it then Vorpal can use the chat rooms JID as a conversation id
  • if the interaction is not with a chat room, then Vorpal will sort the full JID of to and from of a packet and concatenate them giving us a unique conversation id
The advantage of implied conversation id over those explicity marked with <thread> element is that implied conversation supports all 3 types of packets (message, iq and presence) whereas <thread> is only supported in message. The down side of it is that because its implied viz we compute the conversation id using information from the packet, you are really at the mercy of this algorithmn and have no control over the conversation states.

Conversation Types

Vorpal supports 2 types of conversation:
  1. implicit conversation – these are for a request response cycle; they are started automatically started automatically when you send IQ (get/set) packets and are terminated automatically when the corresponding IQ response (result/error) is received or vice versa
  2. explicit conversations – these are conversations that are started by the service by calling Conversation.begin(). Under certain situation explicit conversations are also started automatically; however you must terminate the conversation. We’ll look at this in a future blog (of this series)

Conversation Examples from the Playground

I’ll go into the nitty gritty details of conversation in my next blog. For the impatient, have a look at Eliza in playground. It contains 2 Netbeans project;
  • ElizaService is the external component that implements Eliza. I got the source here. To run it you need to define ‘arkham’ as a subdomain in your XMPP server and the shared secret is ‘ICannotSleep’. Or you can change the deployment settings
  • Arkham is a Java Eliza client
Deploy ElizaService to Glassfish with Jabberocky. To verify that Eliza has been deployed successfully run a discovery service on it. The following screenshot from Gajim shows Eliza service.
There are 2 ways of accessing Eliza. 
  1. The first is to use a standard XMPP client like Gajim. Create a chat room (muc). Then send a direct invitation to eliza@arkham.your_domain. Once Eliza has joined the chat room it will send a greeting to the root. Now you can interact with it by telling Eliza your problem. To end the therapy session, simply type quit or bye
  2. The second is to use Arkham which essentially does the same thing as 1 above. The only difference is that it will initiate a search of for the Eliza service first on the server before connecting. If it cannot find the service, it’ll notify you. Arkham uses client side Vorpal
Eliza shows how to use the client and the server to create a virtual conversation; I’ll be talking about this in greater detail in my next few blogs.
For those who want to check out these new features please download the latest from here. If you have downloaded the package prior to July 29 2012, please download it again. 
Note: I’m trying to get a hang Blogilo after I’ve decided to change from ScribeFire. So you’ll have to excuse me if there are any issues with formatting, etc.
Till next time

Screencast: Are you there?

In this screencast we will show how to use @Presence to allow a XMPP external component to respond to subscription and probe messages. This is a continuation of our series of tutorial on developing CustomerQuery component with Vorpal framework.

The source thaw was developed in the screencast is availble here.

Till next time

Screencast: Developing Discoverable XMPP Components with Vorpal

A screencast explaining how disco#info and disco#items works in XMPP. There is also a ‘live’ coding show how to use @IQ and @Query nnotation.

Comments and feedback are welcomed.

Another Screencast – Stateful Objects with Conversation

I’ve really caught the screencast bug; here is another screencast on conversation support in Vorpal. In the screencast I use Vorpal to develop an Eliza service.

Here is how it works. IM users establish a chat session with eliza@arkham.batcomputer JID (or whatever subdomain you choose to deploy it in). If the in coming messages to Eliza has <thread> element, then Vorpal can use that to establish a conversation.

To begin a ‘therapy session’ with Eliza, send to eliza@arkham.batcomputer a message with start as the message content. Vorpal will create an instance of Eliza and hold that for the duration of the conversation. When you decided to end the session, simply send it a message with quit. Vorpal will clear all the objects in the conversation’s context.

Note: the above screencast is about 16:28 mins. Not sure why Youtube thinks its 49:18 mins

I’ve blogged extensively about conversation support and the programming model in my previous posting call Conversations with Vorpal.

You can get the source code of the demo here.
Get the latest Jabberwocky bundle here.
The Eliza source used in the screencast is available from http://chayden.net/eliza/Eliza.html.

Till next time.

Screencast – Developing XMPP Services with Jabberwocky and Vorpal

I’ve decided to move to the 21st century by recording my first screencast. After hunting and testing various Linux tools, I’ve settled on recordMyDesktop.

The following 2 screencast on this blog are my effort.

So what’s the screencast about? I’ve blog extensively about XMPP and the two framework that I’ve been working on, Jabberwocky and Vorpal. I thought it’ll be nice to show how to use these frameworks.

Part 1 of the screencast talks about the various ways you can develop XMPP services.
These includes service bots, server plugin and external component. The
second segment of this part describes a use case for querying a
database using XMPP.

In part 2 of the screencast, I will show how to implement the use case described above with Jabberwocky and Vorpal along with JavaEE services including CDI and JPA.

The source for the code from part 2 can be found here.

Please provide your comments and feedbacks. Till next time.

Integrating CDI with Vorpal and the Cuckoo Bird Effect


Nest with Cuckoo bird’s egg

I first came across the insidious practices of the Cuckoo bird in Clifford Stoll’s book The Cuckoo’s Egg. The Cuckoo bird is a brood parasite. They never build any nests of their own; so when its time for them to lay their eggs, they lay their eggs in the nest of other species (of bird) whose egg resembles that of their own. Unawares, the “foster” bird will feed the Cuckoo’s nestling when they hatch. In the book Cuckoo’s Egg, a hacker used a similar method to trick the host computer to give him root access through movemail.

Fascinating stuff you say but what does this piece of trivia have to do with Vorpal? Vorpal uses a similar technique, though for benign reasons, to coax Glassfish application server into giving it what it wants – JavaEE resources (object lifecycle management, JPA, transaction, Stateless Session Bean, validation, etc). Vorpal achieve this firstly by masquerading as a Web Application and secondly by integrating with CDI. The first allows a Vorpal application to be deployed into Glassfish and the second allowed the Vorpal applications to consume container resources.

In this blog, I will show you how you can use Vorpal with CDI. Note that the Vorpal programming model that I describe here is still valid. CDI supports builds on this. This blog is not a CDI tutorial. I’ll just be listing what are the features that are supported by Vorpal. Those of you who are not familiar with CDI are encouraged to go through this tutorial before continuing.

Message Handler Lifecycle

When you are using Vorpal with CDI, all Vorpal message handler class must be annotated with either @RequestScoped or @ApplicationScoped. The semantics of these 2 annotations are similar to those in a Java EE 6 application. Vorpal also supports a third lifecycle annotation call @com.kenai.jabberwocky.framework.ConversationScoped. This annotation is conceptually similar to @javax.enterprise.context.ConversationScoped but supports XMPP conversation semantics. As conversation support is quite involved, I’ll explain this in my next blog. Vorpal does not support @SessionScoped.

Once you have annotated with any one of the 3 annotations listed, you can also use lifecycle methods like @PostConstruct and @PreDestroy.

Here is a simple example of an object using CDI

@RequestScoped @Message
@Body(“Hello {*name}”)
public class HandleMessage {
   private final String name;
   @PostConstruct void init() {
      //Do something
   }
}

As in the example above, the HandleMessage class is a request scoped object meaning that a new instance of HandleMessage will be created when there is a match and HandleMessage is selected for firing.

Note the asterisk before name in @Bind. This is a new matching feature and it denotes none or more. If you specify “Hello {name}“, then a match will include a String literal following “Hello ” in the body like “Hello Fred Flintstone“. However with an asterisk, @Body will  match “Hello ” as well. See my previous blog for matching and firing.

Resource Injection

Vorpal supports full CDI resource injection. Injection points include

Furthermore all Vorpal annotations, eg. @Body, @Message, @XmlElement, @Bind, etc. are CDI qualifiers if they are use on fields and method parameters. If you are annotating members and methods, then the @Inject annotation is optional. There are also some predefined injection types like ComponentManager, Conversation, ThreadID and ConversationContext.

@RequestScoped @Message
@Body(“Hello {*name}”)
public class HandleMessage {
   private final String name;
   @From private JID from;
   @Inject @To private JID to; //@Inject is optional
   @Inject ComponentManager mgr; //Predefined type injection
   //Constructor injection
   @Inject public HandleMessage(@Bind(“name”)String n) {
      name = ((null == n) || (n.trim().length() <= 0))? “Fred”: n;
   }
   @PostConstruct void init() {
      //Do something
   }
   //Method injection
   @Inject void setSubject(@Subject String subject) {
      —
}

From the example above

  • Notice the member injection. Since all Vorpal annotations are CDI qualifiers, the @Inject annotation is optional
  • Vorpal defines a set of injectable objects which I’ve listed above. You can inject any of these types without qualifiers; as there are no qualifiers, you have to annotate the member with @Inject
  • You can injected any valid CDI resources into constructor, member and method
  • setSubject() is an example of method injection

Capture and @Named

Vorpal works by matching incoming XMPP messages against message handlers. Captures are bound to members and parameters by the @Bind annotation. See example above. If you are using Vorpal with CDI, you can continue to use @Bind to bind capture values; if however you are a CDI purist, you can use @Named instead. Every capture export themselves as @Named. These @Named objects have a slightly different semantics to the regular JavaEE @Named objects in the following ways:

  1. Capture @Named are local to the class – viz. they are not visible outside of the class
  2. Capture @Named are bound to the ‘nearest’ capture – viz. members and methods injection capture @Named are bound to class level capture and a method parameters capture @Named are bound that method capture

Here is a simple example to illustrate the point

@RequestScoped @Message
@Body(“Hello {*name}”) @From(“{from}@jabber.org”)
public class HandleMessage {
   private final String name;
   //Member level capture, bound to class
   //’name’ is only visible in HandeMessage class
   @Inject @Named(“name“) private String name;
  
   //Method injection – also bound to class
   @Inject void setFrom(@Named(“from“) String from) {
      —
   //name is bound to capture in @To
   @To(“{name}@{__domain__}”)
   public String handleMessage(@Named(“name“)String to) {
      …
   //name is bound to this method’s @To
   @To(“info-{name}@{__domain__}”) @Subject(“{subject}”)
   public String handleInfo(@Named(“name“) String name
         , @Named(“subject“) String subject) {
      …
}

Firstly notice that the @Named member (String name) and the @Named method (setFrom) parameter injection are bound to @Body and @From from the class level. Furthermore @Named are bound to their nearest capture. So @Named(“name”) in handleMessage method will be bound to the @To annotation on that method and not to @Body. Similarly for handleInfo, its @Named(“name”) will be bound to its @To annotation. If my explanation is a little confusing, you can see the various @Named association above from their colours. Another simple way of deciding which capture @Named is bound to which capture is to place your finger on the @Name, eg. on @Named(“name”) on handleInfo, and move up. The first capture with the same name that you encounter will be bound to that @Named. In this case, the it will be @To(“info-{name}@{__domain__}”).

One other point is that message handler methods are not annotated with @Inject. In the above example handleMessage and handleInfo are message handler methods because they do not have @Inject. If these methods were annotated with @Inject, then they would be invoked when HandleMessage is instantiated.

JavaEE 6 Resources

Once a message handler are under CDI control, the message handler can access all of the JavaEE’s platform resources via injection. I’ll not go into defining JavaEE resources like JPA, Stateless Session Bean, etc. The following code shows how you use JPA from within a message handler.

@RequestScoped @Message
@Body(“Hello {*name}”) @From(“{from}@jabber.org”)
public class HandleMessage {
   //Injecting EntityManager
   @PesistenceContext EntityManager em;
   private final String name;
   @Inject @Named(“name“) private String name;
   …

The latest bundle of Vorpal and Jabberwocky container can be found here. As of this blog, the latest bundle (Merdeka 2011) contains Glassfish containers, NetBeans plugin, Vorpal framework JAR (if you are not using NetBeans) and demo code. There are 2 demo code; the first Eliza demonstrate conversation support; however I feel that this is NOT a very good example and I’ll update it in the next release. The second is query, which basically shows using JPA from within a message handler. The persistence unit points to the default customer database on Derby/JavaDB. Both of these are NetBeans project so they should compile and deploy with out problem if you are using NetBeans (7.0 and 7.0.1).

There is a bug in the Jabberwocky container which prevents 2 or more Vorpal applications to be deployed at the same time. I’ll hopefully fix this in the near future.

CDI support for Vorpal is enabled in the usual way by adding a file call beans.xml to WEB-INF directory.

I’ll talk about conversation support in my next blog.

Writing External Components (for Jabberwocky) with NetBeans

I’ve been working on a NetBeans plugin for the past few weeks. I wanted the plugin because I wanted a place where you could develop, debug and deploy Jabberwocky external components. Download the latest package here. Select the Mayday 2011 download.
The package contains the following

  1. xmpp-gf-container.jar, jabberwocky_support.jar – the latest and greatest Jabberwocky container. I’ve hope to avoid updating the containers but certain issues (see below) have forced me to make changes to the container. See here on how to install the containers if you are new to Jabberwocky.
  2. update directory – this directory contains NetBeans plugin and also the Vorpal framework binaries which I talked about in my previous blog entry

Before I begin I have to say that I have made some rather major modifications to Jabberwocky packaging. Previously, it Jabberwocky components are XAR packages which is basically a JAR file. It is now a WAR package, yes it’s a JavaEE 6 compliant Web ARchive. There are 2 main reason for this change, the first is to do with Glassfish’s architecture (which sort of prevents me from doing certain things); the second is that make this change will allow me to work better with other Glassfish container. Also having a standard WAR package it really makes writing the NetBeans plugin a lot easier.

Installing NetBeans Plugin

The plugin is written for the latest version of NetBeans 7.0. (Don’t even bother trying it on any version other than 7.0). Startup NetBeans 7.0, go to Tools | Plugins | Downloaded | Add Plugins… Navigate to the update directory and select all the NBMs files as shown in the diagram below.


If this or any subsequent images is not clear, right click on the image and select View Image

Creating Jabberwocky External Component

Create a Web application in NetBeans. Select File | New Project | Java Web | Web Application. See diagram below

Select Next for the next 2 screens entering the relevant details for your web application like project name, context path, etc. Then you will come to the fourth screen which is the Frameworks screen as shown below

Select Jabberwocky framework. What this will now do is add the relevant libraries and deployment files into the WAR package. First choose the type of component

  1. Jabberwocky framework – this the the Vorpal framework. If you select this you do not have to fill in the package and class name. The framework will handle that for you
  2. AbstractComponent – selecting this means that you intend to create your external component by extending com.xmpp.component.AbstractComponent abstract class. Enter the package and class name that will extend AbstractComponent.
  3. Component – selecting this means that you intend to implement org.xmpp.component.Component interface. Enter the package and class name that will implement Component.

If your component has any properties, click on the Properties tab and enter the properties as name/value pair. Click Finish to complete the setup.

NetBeans will now display the project and open the xep-0114.xml configuration file.

If xep-0114 file is not opened in the editor area, double click on xep-0114 file in the project window to your left. The editor allows us to configure our external component when we deploy to Jabberwocky. Right at the top is the main component class. If you are using Vorpal (Jabberwocky framework), then you should not change the default class (com.kenai.jabberwocky.core.JabberwockyComponent). Otherwise if you are using the other two types of components, then the fully qualified class name will be display here and you can change this. But remember you can only deploy one external component per WAR package.

Next comes the subdomain properties. This is the subdomain that your component is going to deploy to. Enter the subdomain name, domain and the port number. The Shared secret field is disable. What this means is that you have defined the subdomain in Jabberwocky using the asadmin create-xmpp-subdomain; see this blog.

However if you want to automatically create the subdomain as you deploy the external component, select Create subdomain checkbox. This will enable the Shared secret field. Enter the shared secret of your subdomain (eg. landofthegiants from above is uppercase) or leave it blank to use the default shared secret. Note that this option only creates the subdomain definition in Jabberwock and not with the XMPP server. The Cleanup checkbox ask Jabberwocky to cleanup the subdomain definition when you undeploy your component.

Now you can write your component. If you are using Vorpal, then you need to write some message handlers. My previous blog gives a brief tutorial on using Vorpal.

If you are using AbstractComponent or Component, then the plugin will generate an appropriate template for you.

You need to also ensure that the Glassfish instance that you are deploying to supports Jabberwocky. To check if the Glassfish instance supports Jabberwocky, right click on the project node (eg. EchoUpperCaseComponent in the diagram above) and select Properties. The following dialog box will open.

The Server combo box will show a list of Glassfish instances that supports Jabberwocky. If the Glassfish instance that you have chose as your deployment server supports Jabberwocky, then that instance will be displayed here. If however you have accidentally selected Tomcat, then this combo box will be blank. Pull down the combo box to see which instance supports Jabberwocky. Also changing this do not change the actual deployment server of the web project. (I’ll fix this one day). You have to select Run under Categories and chose a Glassfish instance that matches this combo box.

Finally you are ready to deploy. Right click on the project node and select Deploy.

If all goes well you will see some communication between your component and the XMPP server in the output window.

If you switch over to the Services tab, you should also see your component deployed under Applications.

Note: if you fail to see any communications between your component and the XMPP server and you are sure its not because of your component, then undeploy your component from Glassfish. Open the build.xml file and save it. Then build and redeploy your component.

With this plugin I hope to make external component development on Jabberwocky easier. In my next blog I’ll show you how you can add external component to an existing WAR file.

Till then, give me feedbacks (love it, indifferent, sucks). If you discover any bugs send me a comment or file a bug at the Jabberwocky home.

Writing External Components for Jabberwocky

In my last 2 post (here and here) I talked about setting up Jabberwocky and deploying some components into the container. In this post I would like to show you how you can develop your own XEP-0114 components for Jabberwocky.

Setup (again!)

Download the latest bundle here. Select the valentine version. The zip bundle contains the following files

  1. jabberwocky_support.jar, xmpp-gf-container.jar – the XMPP container JAR files
  2. uppercase.xar, weather.xar – sample applications. See this
  3. hellocomponent_2011-02-15_13.41.25.zip – this is the application that we will be developing in this blog; contains source and also hellocomponent.xar. This is a NetBeans project so use NetBeans to open it
  4. com-kenai-jabberwocky-xmppcontainer.nbm – this is a NetBeans plugin that adds Jabberwocky libraries into NetBeans. More of this later
  5. xep-0114.xml – a Jabberwocky application descriptor file. More of this later

Glassfish

Copy jabberwocky_support.jar and xmpp-gf-container.jar into $GLASSFISH_HOME/glassfish/modules directory. If you have installed previous version, you can overwrite them with these new files. There is a detailed post here on how to install and verify the installation.

NetBeans

Download NetBeans 6.9.1 and install com-kenai-jabberwocky-xmppcontainer.nbm plugin. Verify that the plugin have been installed by doing the following Tools | Libraries and look for ‘Jabberwocky API’ in the Libraries window. See figure below


Developing Components

The External Component

  1. Create a new class library project in NetBeans. File | New Project | Java | Java Class Library. Click Next and enter the details of your project. Call it hellocomponent for the sake of this exercise
  2. Now create a package call mycomp; right-click on Source Packages node, New | Java Package. Call it mycomp.
  3. Right click on mycomp node, New | Java Class to create a Java class. Call the class HelloComponent.java.
  4. Now you have to decide how you want to implement the external component; you can do this by either by implementing org.xmpp.component.Component interface or by extending org.xmpp.component.AbstractComponent class. I’ve written a series of blogs on these 2 methods and their trade-offs. See this and this. So I won’t be going into any details here.

    If you are extending AbstractComponent, extend from com.kenai.jabberwocky.xmppcontainer.AbstractComponent (will refer to it as Jabberwocky component from now onwards) instead of org.xmpp.component.AbstractComponent. The reason is that Jabberwocky component is designed to run in the Jabberwocky container. If you try to deploy you component by extending AbstractComponent, Jabberwocky will prevent your component from being loaded.

    Jabberwocky component is method and feature compatible with AbstractComponent. This is so that if you are migrating an existing component that is based on AbstractComponent to Jabberwocky container, just change the package to com.kenai.jabberwocky.xmppcontainer. The Jabberwocky component class is bundled with the NetBeans plugin (com-kenai-jabberwocky-xmppcontainer.nbm) that you install in the previous section. So when you perform code completion in the editor, Jabberwocky component class and the original AbstractComponent class will be display in the popup; be sure to select the former.

    There are however some differences between the two:

    • compMan (ComponentManager) member in AbstractComponent has been renamed to componentManager in Jabberwocky component class
    • You cannot add (ComponentManager.addComponent()) or remove (ComponentManager.removeComponent()) other external component when you are running in Jabberwocky. These methods are basically noop and no exception are thrown. I’ve not figure out the implication of this. Will relook at this later.
    • Call ComponentManager.setProperty() will not persist your property across container reboots. Property persistence is quite easy to implement but I’m not sure how useful this is.

Component Descriptor

Create an xml file call xep-0114.xml with the following structure

<subdomain name=’greetings’ domain=’batcomputer’ port=’5275′>
   <component-class name=’mycomp.HelloComponent’/>
      <properties>
         <property name=’language’ value=’malay’/>
      </properties>

</subdomain>

  1. The subdomain specifies the name subdomain name, the domain name and the port number. In the example above, the subdomain name is greetings, the domain name is batcomputer and the port is 5275. You can omit the port attribute if it is 5275. So if you are addressing fred from this subdomain, the JID would be fred@greetings.batcomputer.
  2. The component-class tag specifies the fully qualified class name of your class that implements the Component interface or extends the Jabberwocky component class. In the current implementation, a descriptor can only support one component.
  3. properties tag encloses a series of property tags. These values can be read by your component using ComponentManager.getProperty(). I have an example of using this in the latest bundle. properties tag is an optional tag.

Packaging

Once you have your component and a descriptor, you need to package them into a XAR (XMPP ARchive) file. XAR is really a JAR file create using jar. The following diagram shows the structure of a XAR package

The name of this bundle is call hellocomponent.xar. The archive contains 2 directories (classes, lib) and a XML (descriptor file). Your component classes goes into the classes directory. This directory is mandatory. Do not JAR or ZIP your packages. Any libraries dependencies goes into the lib directory. You can omit lib directory if you do not have any libraries. Finally the component descriptor is located at the root of the package. JAR the directory and files and change the suffix from .jar to .xar.

Hopefully by the next iteration of the NetBeans plugin, I’ll automate this process so that when you perform a build, NetBeans will also create the XAR archive for you.

Deploying the XAR Archive

Lets assume that you are going to deploy hellocomponent.xar to

  • subdomain: greetings
  • domain: batcomputer (or whatever is the name of your domain)
  • shared secret: hello

First and foremost, go into your XMPP server and create a subdomain with the corresponding shared secret. If you are using openfire, I’ve talked about the setup here (scroll right to the end of the post).

Now you need to setup Jabberwocky container so that it knows about the domain, subdomain and share secret of the subdomain. I’ve also talked about it here as well. Look at ‘Configuring Domain and Subdomain’. You need to start Glassfish before you can do this.

Finally you deploy hellocomponent.xar with the following command

asadmin deploy hellocomponent.xar

Test the component by starting a chat with fred@greetings.batcomputer. Any name will do. If your component fails tostart up, check Glassfish’s log files. They can be found in $DOMAIN_DIRECTORY/logs/server.log. The default logging level is at INFO. You can change to log level to FINER for more details. See Glassfish Administration Guide.

Note: I’ve used Glassfish 3.0.1, NetBeans 6.9.1 and JDK 1.6 u23 to develop and test. Any other combination (especially Glassfish 3.1) of the above, YMMV.

Send me feedback. Till next time.

Follow

Get every new post delivered to your Inbox.

Join 54 other followers