Wednesday Sep 16, 2009

  • Monitoring is a powerful feature in GlassFish V3.
  • Admin Commands are a powerful feature in GlassFish V3.  

In this blog I'll show you how to create an Admin Command that exercises the Monitoring Facilities.

Glossary:

  • ProbeProvider - A class or interface that has methods (Probes) that can be called at runtime.
  • Probe - A method that can be called at runtime that in turn will call any Listeners that are registered
  • Listener - A method that is registered to receive "events" coming from a Probe
  • Admin Command - An easy to call command running on GlassFish V3.  You can access it via REST, HTTP or asadmin.  You could easily do this whole tutorial inside a servlet instead.  I chose to use an Admin Command so you can see how to create and use commands.

Background

In this tutorial we will work with a ProbeProvider interface.  We write an interface with the methods (Probes) that we wish to call at runtime.  We never create an implementation of this interface.  Instead we hand it off to GlassFish.  GlassFish will magically create an implementation class for the interface and return an instance of that implementation.  Under the hood, GlassFish has automagically inserted code into your methods that will call any Listeners that you subsequently register.

Using an interface is a fairly unusual case.  The much fancier and more usual case is that you give GlassFish an instance of any POJO that has the proper annotations.  GlassFish will then rewrite the actual bytecode of the class and add calls to the Listeners!

Admin Command

  1. The command should setup the Probes and Listeners correctly the first time the command is run
  2. Each subsequent call should fire the appropriate probe

 The complete class is here

You provide LCPP and LCListener.  LCPP is the Probe Provider interface and LCListener is the Listener class.  The 2 lines that do all the registering and magic are here:

probe = probeProviderFactory.getProbeProvider(LCPP.class);
listenerRegistrar.registerListener(new LCListener());

That's all!  You now have a probe object that you can call methods on that will automatically call your listener class.

Probe Provider Interface

The interface is here.  As you can see it is mostly  a bunch of annotations and 2 methods:

void ping();
void ping2(@ProbeParam("message") String s);

Note that they must return void   You should make all parameters primitives or String to avoid trouble.

Probe Listener

 The source is here.  Now you can see how the Listener gets hooked up with the Probe.  The Listener needs the values from the ProbeProvider annotation in the Probe Provider class.  It's a lot easier to see how to do it by looking at the source then for me to explain it.

How to Test

  1. Take the files and drop them into a GlassFish extension project.  If you have GlassFish source just do what I did -- drop them into the core/kernel module.  Or you can just use the files as a guide and, say, create a Servlet instead of using an Admin Command.
  2. build and deploy the jar
  3. start the server
  4. tail the server log (even better -- run  asadmin start-domain --verbose)
  5. call asadmin ping <optional-string-here>  
  6. Look for the listener messages in the log
  7. goto 5



Monday Jul 27, 2009

I've been debugging GlassFish today.  I need to set the debugger to suspend=y or suspend=n depending on what I am doing.  Instead of constantly editing domain.xml I simply do this:

<java-config debug-options="-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=${SUSPEND},address=9009" system-classpath="" classpath-suffix="">

And then I do this in the OS:

 Windows:  set SUSPEND=y

UNIX: export SUSPEND=n

 ========================

Environmental variables are automatically searched when a token appears in domain.xml.  It also searches System Properties and other properties inside domain.xml.


Sunday May 31, 2009

Platform Services have just been rolled out for the first 2 platforms:

  • Solaris  Management Facility (SMF)
  • Windows

In the simplest case where you have one default domain and you want to run it as a service you run this command:

asadmin create-service

Here are all of the options:

[--passwordfile password-file] [--name service-name] [--serviceproperties (name=value)+] [--dry-run=false] [--domaindir domain_parent_directory] [domain_name]

 Once you have created the service it can be controlled in various ways by operating system and native tools. 

 Windows

We use Windows Service Wrapper as the tool for installing the service.  It can be used to start stop and uninstall the service.  It can be found in the bin subdirectory of the domain directory.  In the default case the name of the executable will be domain1Service.exe  The directory also contains the configuration file, domain1Service.xml.  Below are the available commands:

  • domain1Service start
  • domain1Service stop
  • domain1Service uninstall
  • domain1Service install
You can also manage the GlassFish service with Windows tools:  Services snap-in and the net command line program.

Solaris  Management Facility (SMF)

You create the service exactly the same as WIndows.  One big difference for most users is that on Windows most users have administration privileges.  I.e. everyone is super-user.  Not so on Solaris.  In order to create a service you must have SMF privileges.  How to set that up is beyond the scope of this blog, but root definitely has these privileges by default 

 Important: If root creates a service then only root can start that domain from then on.  The best way to set this up is to install and/or create the domain as root and then create the service as root.

Once you have created the service you need to start it yourself.  Here are the most typical Solaris commands of interest:

  • /usr/bin/svcs  -a | grep domain1  // status
  • /usr/sbin/svcadm enable domain1 // start
  • /usr/sbin/svcadm disable domain1 // stop
  • /usr/sbin/svccfg delete domain1 // uninstall

Future Directions

If there is interest, demand and time we will add support for controlling the service from CLI:

  • start
  • stop
  • uninstall
  • restart




Sunday Apr 26, 2009

GlassFish V3 is now sporting a brand new capability:  Remote Restart.

This feature is particularly handy for environments where the server machine is secured and difficult to get to.  With the right credentials you can now restart the server from anywhere in the world -- as well as from the same machine. 

It is very easy to use.  As of today there are two ways to call the restart-domain command with the third method coming online soon

(1) Use a URL in a browser: 

http://yourhost:4848/__asadmin/restart-domain 


(2) Use asadmin like so:
   asadmin --host yourhost restart-domain

(3) Coming soon:  Admin Console GUI support for the command

The asadmin command, restart-domain, is what I like to call a "hybrid" command.  It is both a local and a remote command.  The local portion of the command's job is to block until it verifies that the server has completed its restart and is online and ready to go.  The remote portion does the actual restarting.

Details

There are 3 main flavors of starting non-embedded V3.  Restart-domain works with all three:

  • Starting the server with the launcher (i.e. asadmin start-domain).  Restarting will stop the running server and once the JVM process is guaranteed to have exited the server will restart.  There are no special "watchdog" processes involved.  The server itself does the work itself in what I like to call "reincarnation".  This is easy to see by running jps during the restart.  You will see the process id change.  You can also watch the server log as the server restarts.
  • Starting the server with the launcher in verbose mode (i.e. asadmin start-domain --verbose).  The key point here is that we have to preserve the console that asadmin owns here.  So we do the restart a little differently.  Since the asadmin process is also running  on the server machine, we ask the already running asadmin process to restart the server for us.  asadmin does all the heavy lifting here.
  • Starting the server in implanted mode (e.g. java -jar glassfish.jar).  A new jvm will be started with exactly the same commandline arguments.  Note that if the server owns the console -- i.e. is running "in the foreground" and mirroring log messages -- the new server will lose control of the console.  We can not absolutely guarantee a clean shutdown without literally closing down the JVM itself.  Once that is done the console is out of reach.

Give it a try!

Monday Feb 02, 2009

Today's blog demonstrates how to create a very simple GFE (GlassFish Embedded) application.  The application requires no manual downloads.  GlassFish need not be installed and no GlassFish files of any kind need to be present.

The application uses a very simple web app named, appropriately, simple.war.  The simple.war file has been checked into Subversion for this project.  This breaks the usual rules of checking in only source code.  But I wanted to make this application as simple as possible for you to use.  You could replace simple.war with your own not-so-simple web app by renaming it to simple.war and overwriting the original.

Here is how to checkout and build the sample project:

  • svn co https://svn.dev.java.net/svn/glassfish-svn/branches/embedded_v3_prelude_release/embedded/samples/SimpleMaven
  • cd SimpleMaven
  • mvn

You can run the GFE application by executing r.sh(*NIX) or r.bat(Windows).  If you are on *NIX don't forget to make r.sh executable (chmod +x r.sh)

What Does this Sample GFE Do?

  1. Create a GFE server
  2. Create a HTTP listener at port 7777
  3. Start the GFE server
  4. Deploy simple.war to the GFE server
  5. Send a request to simple at port 7777 and print the results
  6. Wait for user to kill the server (^C) 

Details

  • Maven downloads the GFE jar to your local repository
  • The Maven  Dependency plugin is used to copy the GFE jar from your local repository to the target directory.  Why?  So the run script will work in all scenarios -- since I don't know where your local repository lives.  It isn't strictly necessary,  you could point the classpath to the location of the file in your local repository.
  • The pom.xml for this project is as simple as possible.  The copying over of the GFE jar is the messiest part of the pom.xml.  Take a moment to examine pom.xml
  • There is one java file for this project.  Take a look at it.  Change the port from 7777 to 12345 or your favorite port number.  Have it deploy 2 or 3 more web apps.  Play around with it.

Next Steps

It would be nice if we didn't have to use the run scripts.   It would be nice to have Maven run the app.  In the next installment in this series I will show you just how to do that with the GFE plugin!







 https://svn.dev.java.net/svn/glassfish-svn/branches/embedded_v3_prelude_release/embedded/samples/SimpleMaven

Thursday Jun 12, 2008

I just learned a lesson today the usual way.  I.e. the hard way!  

Conclusion -- never do this:

synchronized(getClass()) { ..... }

Why?

The intent is obviously to serialize the block against ALL instances.  About the only requirement is that the object be unique and global.

Oops!  The object is not unique!  What if the method is called from a derived class?  Then the lock object is totally different.  That is what happened to me.

This is a much better way to do such things:

class Foo {

private final static Object myLock = new Object();

public void someMethod() {

    synchronized(myLock) { ....... }

myLock is global, unique and is self-documenting.

Tuesday Sep 11, 2007


[Read More]

Wednesday Jun 13, 2007

This chapter can be downloaded here.

This zip file has the entire Chapter1 NetBeans project in it. I highly recommend using NetBeans 5.51 for this tutorial. And of course you are going to need GlassFish

The first thing that we need to get working is the automatic downloading of the Dean Edell mp3 files. We're going to make a simple stand-alone Java SE application to do the downloading. We will then create a simple script to run the java application. After testing it to make sure all is well we'll get the operating system to call it every Monday through Friday night at 11:30 PM PDT.

The Java Technology Portion

The source consists of two files:
  • HTTPDownloader.javaA simple class that takes a URL string and a filename string. It fetches the file that the URL is pointing to and writes it to the filename. This is where Jaca Technology really pays off. It's ridiculously easy to do.
  • DeanEdellDownloader.javaThis class is also pretty simple. The most difficult part is assembling a distinctive filename based on the date.
DeanEdellDownloader uses HTTPDownloader to fetch the current Dean Edell mp3 file. It refuses to run on weekends. The URL and the location to write the mp3 files is hard-coded here. That's OK in this scenario because we are going to build it once and forget about it.

You will need to change the value of one variable in DeanEdellDownloader. The last line of the file contains the target directory from my GlassFish installation. Replace it with your path:

private final static String DEFAULT_DIR_HTTP = "C:/as/domains/domain1/docroot/DeanEdellFiles";

The Script

NetBeans automatically put a manifest file pointing to the correct main in the jar file. On my Windows system I put a script in DeanEdell.bat in a scripts directory. The command in the script is:

java -jar path-of-jar-file

Run the script. A 10.5 MB mp3 file should appear in [domain]/docroot/DeanEdellFiles (unless it is the weekend!)

Calling the Script Automatically Forever

If you are on UNIX or Linux you are on your own here. You need to create a chron job that runs the script Monday through Friday around 11:30 PM PDT. It's OK to run it on weekends too -- it won't do anything.

On Windows this is super easy to do: Go to Control Panel and then run Scheduled Tasks. It will take you by the hand and guide you in making a chron job. Just have it call the batch file every Monday through Friday around 11:30 PM PDT. Make sure you enter your account password.

And that's all there is to Chapter 1. We now have DeanEdell mp3's appearing automatically in a folder under docroot inour domain.

Next Installment: Chapter 2 - Create a Web Application to serve up the files

Monday Jun 11, 2007

This is the first chapter in a n-chapter tutorial on how to exploit Glassfish capabilities. I learned long ago that the only way I can really cement into my head a hunk of technology is to just do it. I came up with a useful application for web technology. In this series we will be building an application that will slowly but surely use these areas of javaee. They are in the approximate order that we will tackle in the project.
  • HTTP File downloading (HyperText Transfer Protocol)
  • Servlets
  • JSPs (Java Server Pages)
  • User Authentication - Basic, then File Realms, then JDBC Realms
  • Derby Database
  • JNI (Java Naming Interface)
  • EJB 3.0 (Enterprise Java Beans)
  • JPA (Java Persistence API)
  • EJB Timer Service
  • Struts
  • JSP Tag Libraries
  • MDB (Message Driven Beans)

Chapter 0: The Application Description

Dr. Dean Edell has an interesting radio talk show on KGO radio in San Francisco. His show is from 1 to 2 PM Monday through Friday. KGO posts an mp3 file for the show once a day. KGO takes it down, forever, after 24 hours. KGO does not maintain an archive of old shows. I like to burn the shows onto CDs and listen to them in my car. What this application will do is:
  • Automatically download the mp3 at 11:38 PM every night, Monday through Friday and save them to a subdirectory of docroot on my Glassfish Application Server.
  • Maintain user accounts for people that wish to download the files. New accounts will be accepted and added to the list on demand.
  • The application will persist which files have been downloaded for each user. When a user is authenticated he will see his own custom list of programs he has yet to download.
  • A list of all available programs will also be available in case of trouble (like the dog eating the Dean Edell CDs)

This sounds like a lot of overkill for such modest sounding requirements. But making it 100% automatic is a bit challenging. Besides, the whole point of this is to create an application - any application -- in order to learn how to do all this stuff. We will start simple but thorough and correct. We will constantly change and modify it to use the cutting edge Java EE technology as the tutorial progresses.

Stay Tuned for the next installment, Chapter 1:

Write a stand alone Java application that will download the mp3 file. The OS will be in charge of running this application via a chron/at job.

Tuesday May 29, 2007

A little known fact: there are scripts for starting and stopping the 3 different kinds of Glassfish servers. The three kinds of servers are:

  • Domain Administration Server (the only server available in a development profile)
  • Node Agent Server
  • Instance Server

These scripts have always been there but were never officially supported.  They were difficult to use.  E.g. you had to know to type in username, password and master password into the void at the command window for strtserv to work.  The scripts were used internally in pre-V2 versions.  They are not used at all in V2.  They are there for your use exclusively now.

Where Are These Scripts?

They are named: 

   Start Script
 Stop Script
 Windows  startserv.bat  stopserv.bat
 Not Windows
 startserv  stopserv

 

In my own personal default environment, they are here:

 Domain Administration Server
c:/as/domains/domain1/bin
Node Agent Server
c:/as/nodeagents/na/agent/bin
Instance Server
c:/as/nodeagents/na/i1/bin
 

How Do I Use Them?

To start a server run the appropriate startserv script.  It will ask you for the administrator's username, pssword and the master password.  If you don't know what a master password is -- just enter changeit.  This is not really needed for the Domain Administration Server in a developer profile, but the script does not yet have the smarts to know whether or not the server is secure.  A future release may fix this problem. 

To stop a server simply run the stopserv script.  No authentiction information is needed or asked for.

 Features

  •  The scripts are relocatable.  I.e., if you use asadmin backup-domain and asadmin restore-domain to clone a domain to a different location -- the scripts will still work.
  • Shutdown is very fast and efficient.
  • This is the only way you can start an instance with no running Domain Administration Server and no running Node Agent Server.
  • You can take over the lifecycle management of one or more Instance Servers.  If you start the Instance Server with the script then the Node Agent Server will not automatically stop it when the Node Agent Server is stopped.


Tuesday May 01, 2007

Fish for a Flat Screen TV
Blog about GlassFish for a chance to win a 52" LCD HD TV.

I'm a developer for Glassfish.  My area is Administration.  I am also a glassfish user.  I have a real-world web site that's been running continuously for 2 years

Now when I try to do something in a different area of the Appserver like Web Applications, I'm just as much of a helpless newbie as anyone else.

I developed a semi-cool way to publish lots and lots of pictures on my website with little manual intervention.  It works great.  One day I downloaded a ton of pictures  from my camera to the website.  I put the "magic URL" that causes a servlet to layout the pictures in a URL which worked fine.  When you click on any of these small pictures it displays  a large version of the picture.  But, wait!  I''d click and instead of seeing a picture, I'd get a download dialog from Firefox!  After looking around on the filesystem I located the problem.  The camera saves the pictures with an extension of JPG while all of my other pictures had an extension of jpg.

I posted a comment about it. Jan Luehe (super web-server guru) saw it, figured out the problem right away and filed a bug.  the bug was fixed in the very next build of glassfish.  Now that's service!

So -- Glassfish is fast, reliable, free, it has great clustering capability, it's open-source and there are very smart knowledgeable people listening in on all the posts and ready to jump into action to help you.  What else do you need?!?

This is why Glassfish gets my vote as World's Greatest Appserver.

 


Tuesday Apr 24, 2007

There used to be a big problem in trying to attach a debugger to a clustered server instance in Glassfish.  As of today (build 45), it is a snap to do it!

The problem was that a cluster config could only specify one debugging port.  This would work if you started one and only one server instance.  As soon as you tried to start a second instance it would try to use the same jdwp port and it would fail to launch.  It was (almost) impossible to debug 2 instances on the same machine at the same time.

The solution is to defer the actual port number selection.  I.e. the instance needs to choose its own port.  Each instance specifies a different port and, voila, problem solved.

Here is how to do it:

 1. Enable debugging support for the cluster
We are using a cluster named c1.  First make sure that debugging is enabled for the cluster:

asadmin set c1-config.java-config.debug-enabled=true

 

2. Set a variable debugging port

The syntax is ugly.  Don't bother memorizing just do a get to see it, edit it and then do a set on the result like so: 

asadmin get c1-config.java-config.debug-options
c1-config.java-config.debug-options = -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=9009
asadmin set c1-config.java-config.debug-options="-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=${DEBUG_PORT}"
Don't forget the double quotes, and no spaces around the equals sign!
 

3. Set the instances' debugging ports

 In this case we have 2 instances, i1 and i2.  We will make the debugging ports 11111 and 22222 respectively:

asadmin set i1.system-property.DEBUG_PORT=11111
i1.system-property.DEBUG_PORT = 11111
asadmin set i2.system-property.DEBUG_PORT=22222
i2.system-property.DEBUG_PORT = 22222



That's it.  You're ready to debug multiple instances.



Monday Apr 23, 2007

We developers do this all the time:

  • start DAS and/or NodeAgent
  • tail -f on the 2 server.logs

There is an easier way!  Use the --verbose option.  This will start the server but it will not return control to asadmin.  Instead it will take over the command window and all logging output will go to the window as well as the server logfile.  As a bonus, you can press Ctrl-Break (on Windows) to trigger a thread dump

You can Ctrl-C out of the command window at any time without disturbing the server. 

asadmin start-domain --verbose
asadmin start-node-agent --verbose


Friday Apr 20, 2007

We have totally changed the way that Thread Dumps are collected in Glassfish. Forget everything about how it used to be done.
  • You need not run the servers in native mode. The same procedure works in native and non-native mode
  • Thread dumps are available for all 3 kinds of servers -- Domain Administration Servers, Node Agents and Server Instances
  • The new behavior is totally automatic, you don't need to do anything other than send a signal to the JVM to trigger it.

How to Trigger a Thread Dump in Windows

  • Get the PID of the server with jps.
  • Run sendsignal giving it the PID of the server.

How to Trigger a Thread Dump in UNIX and Linux

  • Get the PID of the server with jps.
  • Run kill -3 PID

Where did my Thread Dump Go?

The Thread Dump is appended to a file named jvm.log in the same directory as the normal server logfile. E.g. /gf/domains/domain1/logs/jvm.log

Important: the jvm.log file is deleted every time the server is restarted. If you want to keep the contents you will need to copy the file.

Monday Nov 20, 2006

Appserver launching has changed significantly as of build 26. It is now far easier to understand and debug.

In the beginning...

Before build 26 of 9.1 all server launches involved running shell scripts in external processes. There were a number of reasons for doing this which aren't worth getting into. 4-7 processes were involved in both starting and stopping servers. Here is a simple diagram of how that worked

Legend:

  • pX == process #x
  • ss is the startserv script
  • cli is asadmin
  • PL is ProcessLauncher class running in its own JVM
  • AS is a DAS, NodeAgent or Instance
  • ASL is appservLauncher, a "C" program
  • ASX is appserv, appservDAS, or appservAgent -- all "C" programs
Non-Native Start or Stop:
P1-cli ---> p2-ss ---> P3-PL ---> P4-AS

Native Start or Stop:
P1-cli ---> p2-ss ---> P3-ASL ---> P4-ASX ---> P5-ss --->P6-PL ---> P7-AS

Imagine how difficult this was to debug! One had to echo messages from the scripts to a file, add java debug arguments to the java invocations in the scripts, change the C-code to force it to break so a debugger could be attached, etc., etc. I.e. it was virtually impossible to debug the startup or shutdown end to end!

9.1

Non-Native Start or Stop:
P1-cli ---> P2-AS

Native Start or Stop:
P1-cli ---> P2-ASL ---> P3-ASX ---> P4-AS

  • asadmin no longer uses any scripts (i.e. startserv) to start and stop servers
  • the startserv scripts are now fully functional and supported for use from a commandline
  • the startserv scripts can get the username and passwords directly from the user
  • Any server can be started from arbitrary java code directly (look in the startserv script to see how)
  • The domains are completely relocatable to a different location on the same machine or to a different machine altogether. This automatically makes Appserver Backup and Restore more useful as well.
  • Native launching is temporarily broken (set native launching to false in install-dir/config/asenv.bat or asenv.conf). It works fine on Windows though.
  • Shutdown has been dramatically improved. It used to require between 2 and 6 external processes (for non-native and native respectively) to be started. Now it doesn't start any external processes so it is much faster.
  • To compare new with old, set OLD_LAUNCHER=true in your OS environment. In this case, the scripts will run in multiple processes as before but the scripts are pointing at new code instead of old code. This only works for startup -- shutdown always uses new code.

Performance Checking

Procedure

I used ancient technology -- a stopwatch -- which is exactly the kind of time we want to measure. I.e. how long is the user sitting there looking at a blank screen. In the case of stopping a node agent it was so fast that I added code to do the timing internally in the java code.

Notes:

  • The table appears at the very end of this blog, I don't know why.
  • All times are the average of at least 3 separate trials.
  • The tests were performed on Solaris10-Sparc
  • The domain startup became slower from build 19 to build 26 because of other modules in AS. Look at the times between Build 26 and Build 26 with scripts. This compares the all-java startups with java and script startups in the same build.

Observations and Conclusions

  • stop commands are dramatically faster
  • The new startup shaves 1-2 seconds off the total time. This is much more obvious when you look at start-node-agent which is much more lightweight than DAS.
  • The new code is much easier to understand and debug.

This blog copyright 2009 by codeplumber

Build 19Build 26Build 26 with Script
start-domain26.231.232.2
stop-domain11.87.1NA
start-node-agent7.76.1NotDoneYet
stop-node-agent5.90.82NotDoneYet