Tuesday, 15 January 2008

Installing Glassfish 2 on ubuntu 7.10

Today I decided to install Glassfish on my Ubuntu 7.10 box. It had come to my attention that Glassfish was a standard package for Ubuntu, so I started the package manager and checked Glassfish for installation. All went well until I found out Glassfish 1 was just installed.
Bummer. I had assumed version 2 was packaged. I undid the installation together with the dependencies.
I don't really like installing Linux software without the standard package manager, but I decided to make an exception for Glassfish. Below I describe my findings.

I started looking for a blog/tutorial that describes the installation process and I found a decent one. I followed the instructions and it worked as intended. Thank you Andrew Spooner. It even contained a init.d script for starting and stopping with the rest of the system. However I didn't like all of it, most importantly the fact that Glassfish ran with root privileges (that is not a very good idea).

My requirements for the Glassfish installation are:
  • it must run as a non privileged system user
  • it must start before Apache and after MySQL. Apache links to Glassfish and Glassfish uses MySQL. Shutdown must be the exact opposite.
Here is how I achieved those requirements:

1. Preparation
  • Download the binary most recent stable binary build for linux from the Glassfish site. I downloaded version 2 UR 1.
  • Make sure you have installed a java jdk. I use the sun jdk 6. You can install it like this:
sudo apt-get install sun-java6-jdk
  • Create a system user called glassfish:
sudo adduser --system glassfish

2. Installation
  • The unpack and installation must be run as the newly created glassfish user. First copy the installation file (in my case glassfish-installer-v2ur1-b09d-linux.jar) to /tmp. After that unpack the installation file as the glassfish user. I use /tmp, because the glassfish user has write permissions there. You could use any directory that the glassfish user has write permissions to.
sudo -u glassfish java -Xmx256M -jar glassfish-installer-v2ur1-b09d-linux.jar
  • Move the glassfish directory to opt:
sudo mv glassfish /opt
  • To be able to traverse the glassfish directory without root privileges, you must change the group of all files in the glassfish directory from nogroup to admin.:
sudo chgrp -R admin /opt/glassfish/
3. Configuration
Glassfish comes with a configuration script, which creates a server instance. Next are the steps to run that script.
  • Go to the glassfish directory with the installation:
cd /opt/glassfish/
  • Glassfish comes with a custom version of ant. Make the ant scripts executable:
sudo chmod -R +x lib/ant/bin/
  • Run the configuration script:
sudo -u glassfish lib/ant/bin/ant -f setup.xml
This should end with the message: "BUILD SUCCESSFUL"
After this, Glassfish is installed. You can test your installation by starting Glassfish in the console window:
sudo -u glassfish bin/asadmin start-domain domain1
You can open a browser and go to the admin-console at http://localhost:4848/. Login as user "admin" and password "adminadmin".
If this all works: congratulations. You have successfully installed Glashfish!

Now we need to make sure Glassfish starts when the computer boots up and that it shuts down when the computer shuts down.
  • With an editor, create the file /etc/init.d/glassfish (e.g. by sudo gedit /etc/init.d/glassfish) with the following contents:
#! /bin/sh


case "$1" in
echo "starting glassfish from $GLASSFISHPATH"
sudo -u glassfish $GLASSFISHPATH/asadmin start-domain domain1
$0 stop
$0 start
echo "stopping glassfish from $GLASSFISHPATH"
sudo -u glassfish $GLASSFISHPATH/asadmin stop-domain domain1
echo $”usage: $0 {start|stop|restart}”
exit 3
  • Make the init script executable:
sudo chmod a+x /etc/init.d/glassfish
  • Test the script by stopping the currently running server:
sudo /etc/init.d/glassfish stop
  • After that, try starting it with the init script:
sudo /etc/init.d/glassfish start
  • If all goes well you can set the init script up for automatic startup and shutdown:
sudo update-rc.d glassfish defaults 90 10
When you start the computer the next time, Glassfish will be running with the privileges of the glassfish user.

Have fun with Glassfish!

4. Optional components
Below are some things you probably need, depending on your requirements.

4.1. MySQL
I will not discuss a complete MySQL installation here, but only the installation of the MySQL jdbc driver. Install the jdbc driver as follows:
sudo apt-get install libmysql-java
Next, create a symbolic link in the lib directory of Glassfish to an existing symbolic link to the most recent MySQL jdbc driver:
sudo -u glassfish ln -s /usr/share/java/mysql-connector-java.jar /opt/glassfish/lib/

4.2. Using awt classes
I have a web application that manipulates some pictures with the use of some awt classes. Unfortunately, that resulted in some nasty exceptions on my linux box. After some research, I found out that it was caused by the fact that the linux version of java uses X11 for the awt classes. A fix for the exceptions is using a certain jvm option:
You can add this option for Glassfish in the admin console under Application Server->JVM Settings->JVM Options.


Joni said...

One point on the "glassfish" user; it seems mandatory for the user glassfish to have home directory -- for the keystore.

E.g. 'useradd glassfish' won't work...?

Jasper Kalkers said...

Thank you for your comment. You are correct. I failed to include the creation of the glassfish user. I used the adduser command. I added the step to the "Preparation" part of the tutorial.

Jasper Kalkers said...

I added a step to "Installation". The default group of all files created by the glassfish user, is the nogroup group.
That means that only the glassfish user and root can access the files under /opt/glassfish.
The new step fixes this by changing the group of all files under /opt/glassfish to admin.
This way you enable you to look at the logs of glassfish for example.
However, this does not change the fact that new files created by the glassfish user have the group nogroup. That means that when the server logs rotate, the new log will not be directly readable. The group will have to be changed again.

Does anyone have a permanent solution for that?

klein und grün said...

I run 7.10 as a server isntall. and installing as glassfish user wont work. stopping with java errors.
But no problems when i install it as root :/

Jasper Kalkers said...

Could you post the command you issued which resulted in the errors. Could you include the error messages? Maybe I can help.

Bojan said...

great tutorial, thanks!

one minor glitch, I had to run:
'xhost +'
in order to be able to unpack the glassfish jar as the glassfish user (xprotocol errors).
thanks again.

Joshi said...

Excellent post at right time. You made my life easier, Thx.

Drew said...

If you get java.FileNotFound, you tried to unpack glassfish in a directory it doesn't have access too. That is why he says to copy to /tmp first.

Jasper Kalkers said...

Thanks for your tip drew. You are exactely right. I have adde clarification of my decision to use /tmp in the blog.

Mónico said...

Hi, Jasper. First, thank you for this excellent tutorial. Second, When I ran the following command: sudo -u glassfish lib/ant/bin/ant -f setup.xml

An error appeear at the final of the procedure:

/opt/glassfish/setup.xml:172: The following error occurred while executing this line:
/opt/glassfish/setup.xml:561: exec returned: 1

Any Idea ?

Thanks in advance


Jasper said...

Monico, sorry I have no ideau what causes your problem. Maybe if you could post more details.

Mónico said...

Hi, Jasper. Thank you for your reply. I Attached more info related with the problem to run Glassfish.

Running the Script, appeared the folliwing error:


[exec] Port 8080 is in use.
[exec] CLI130 Could not create domain, domain1

/opt/glassfish/setup.xml:172: The following error occurred while executing this line:
/opt/glassfish/setup.xml:561: exec returned: 1

I hope this helps.


Jasper said...

Mónico; that is just the information I need. Apparently, you have another server running that uses port 8080 (Tomcat typically uses that port). You must either stop using that server or configure glassfish to use a different port (e.g. 8090). If I recall correctly, the ports are configured in the setup.xml file that is used by the step that failed in your case.

I hope this helps.


Mónico said...

Hi, Jasper. I decided to stop the Tomcat process. After that, I can run without problems the setup.xml routine. Everything was ok. However, when I type the following script, an message appeared on the Computer screen.

sudo -u glassfish bin/asadmin start-domain domain1


Domain domain1 failed to startup. Please check the server log for more details.
CLI156 Could not start the domain domain1.

Can you point me out, where I can find info about how to solve this.

Thanks in Advance

Jasper said...

You can find the glassfish logs somewhere under the installation directory (if you followed the tutorial exactely, that should be /opt/glassfish). There is a directory structure for each domain, so you should look for a directory called domain1. The log-file should contain more information.
I don't have an ubuntu installation, so I can't look up the exact location.


toGGi said...

Hi!¡! Thks 4ur comment. But i have a problem with this environment:

$ lsb_release -a
Distributor ID: Ubuntu
Description: Ubuntu 8.04
Release: 8.04
Codename: hardy

$ uname -a
Linux toggilx 2.6.24-19-generic #1 SMP Wed Jun 4 16:35:01 UTC 2008 i686 GNU/Linux

$ uname -r

$ java -version
java version "1.6.0_06"
Java(TM) SE Runtime Environment (build 1.6.0_06-b02)
Java HotSpot(TM) Client VM (build 10.0-b22, mixed mode, sharing)

/home/glassfish$ ll -h
total 82M
-rwxr-xr-x 1 glassfish root 82M 2008-06-18 19:49 glassfish-installer-v2ur2-b04-linux-ml.jar

$ sudo -u glassfish java -Xmx256M -jar glassfish-installer-v2ur2-b04-linux-ml.jar
No protocol specified
Exception in thread "main" java.lang.NoClassDefFoundError: Could not initialize class sun.awt.X11GraphicsEnvironment
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:169)
at java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment(GraphicsEnvironment.java:68)
at sun.awt.X11.XToolkit.< clinit >(XToolkit.java:89)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:169)
at java.awt.Toolkit$2.run(Toolkit.java:836)
at java.security.AccessController.doPrivileged(Native Method)
at java.awt.Toolkit.getDefaultToolkit(Toolkit.java:828)
at sun.swing.SwingUtilities2$AATextInfo.getAATextInfo(SwingUtilities2.java:120)
at javax.swing.plaf.metal.MetalLookAndFeel.initComponentDefaults(MetalLookAndFeel.java:1556)
at javax.swing.plaf.basic.BasicLookAndFeel.getDefaults(BasicLookAndFeel.java:130)
at javax.swing.plaf.metal.MetalLookAndFeel.getDefaults(MetalLookAndFeel.java:1591)
at javax.swing.UIManager.setLookAndFeel(UIManager.java:537)
at javax.swing.UIManager.setLookAndFeel(UIManager.java:577)
at org.jvnet.poormans_installer.Main.setUILookAndFeel(Main.java:95)
at org.jvnet.poormans_installer.Main.main(Main.java:50)

I hope you can help me!

Jasper said...

Hi toggi. This can have something to do with your environment variables. Maybe adding the option -Djava.awt.headless=true will help.

Like sudo -u glassfish java -Xmx256M -Djava.awt.headless=true -jar glassfish-installer-v2ur2-b04-linux-ml.jar

Gabriel said...

If the first solution doesn't works, you can use a fake X-Server: Xvfb

# apt-get install xvfb
# mkdir /home/glassfish/Desktop

Xvfb :2 -screen 0 800x600x24 -ac -fbdir /home/glassfish/Desktop/ &
export DISPLAY=:2

/home/glassfish/bin/asadmin start-domain

Simstim said...

Hi, I had the same issue as Toggi : "Exception in thread "main" java.lang.NoClassDefFoundError: Could not initialize class sun.awt.X11GraphicsEnvironment"

What worked for me was to use the -console option: " sudo -u glassfish java -Xmx256M -jar glassfish-installer-v2.1-b60e-linux.jar -console "

Gabriel Ramírez P. said...

why use a --system user? I understand that system users are for package installation purposes when you need a user to install the package and the user is removed when the package is drop. But are not needed for the daemon. Please correct me if I am wrong! I'm noob. :)

Jasper Kalkers said...

Gabriel; a system user has less privileges than a normal user. A process running as a deamon should have the least number of privileges as possible. That is to make security breaches less likely.

golan said...

Works in Debian Lenny too... with some changes in your instructions:
1. I have to run:
# usermod --shell /bin/bash glassfish
after adduser line. I am working with su command instead of sudo command. I have to set up the 'shell' for the user before using su command.
2. Change line:
sudo chgrp -R admin /opt/glassfish/
# chgrp -R root /opt/glassfish/
because i don't have any 'admin' group.
3. I prefer manually start the server so i don't needed the init script :).

Some interfaces problems when starting glassfish fixed with http://mcc-java.blogspot.com/2008/01/osx-leopard-glassfish-read-this.html. I am running debian in a vmware virtual machine and some weird things happens with the virtual interface and the shared internet connection with the host (a better description of the error in: http://www.2nrds.com/problems-with-glassfish-and-leopard).

Thanks again.

bolebole said...

Excellent....very useful.

Purohit D said...

I appreciate the information. Java is one of the consistent player from the development industry which has been providing the wider scope for developers to come out with different solutions.

Purohit D said...

I appreciate the information. Java is one of the consistent player from the development industry which has been providing the wider scope for developers to come out with different solutions.

Garry said...

Hi Jasper

Thanks for the great tutorial. With the release of the new LTS Ubuntu I've worked with these instructions to put together Ubuntu, Glassfish, MySQL, Java stack on Ubuntu 10.04 Lucid Lynx Server. Still doing some testing to make sure it all works well but the advice to use a non-privileged system users is much appreciated.

dIESEL said...

Thanku for a wonderful tutorial

everything went fine for me except for the startup script

Plz help i am posting my error when i

"sudo /etc/init.d/glassfish start"

Starting Glassfish domain1 from /opt/glassfish/glassfish-v2-1-1-b31g
Starting Domain domain1, please wait.
Default Log location is /opt/glassfish/glassfish-v2-1-1-b31g/domains/domain1/logs/server.log.
java.io.FileNotFoundException: /opt/glassfish/glassfish-v2-1-1-b31g/domains/domain1/config/domain-registry (Permission denied)
java.io.FileNotFoundException: /opt/glassfish/glassfish-v2-1-1-b31g/domains/domain1/logs/server.log (Permission denied)
at java.io.FileOutputStream.openAppend(Native Method)
at java.io.FileOutputStream.(FileOutputStream.java:177)
at java.io.FileOutputStream.(FileOutputStream.java:102)
at java.util.logging.FileHandler.open(FileHandler.java:156)
at java.util.logging.FileHandler.openFiles(FileHandler.java:421)
at java.util.logging.FileHandler.(FileHandler.java:270)
at com.sun.enterprise.admin.servermgmt.launch.ASLauncher.addLogFileToLogger(ASLauncher.java:1668)
at com.sun.enterprise.admin.servermgmt.launch.ASLauncher.buildInternalCommand(ASLauncher.java:818)
at com.sun.enterprise.admin.servermgmt.launch.ASLauncher.buildCommand(ASLauncher.java:746)
at com.sun.enterprise.admin.servermgmt.launch.ASLauncher.process(ASLauncher.java:433)
at com.sun.enterprise.admin.servermgmt.pe.PEInstancesManager.startInstanceAllJava(PEInstancesManager.java:287)
at com.sun.enterprise.admin.servermgmt.pe.PEInstancesManager.startInstance(PEInstancesManager.java:162)
at com.sun.enterprise.ee.admin.servermgmt.EEDomainsManager.startDomain(EEDomainsManager.java:476)
at com.sun.enterprise.cli.commands.StartDomainCommand.startDomain(StartDomainCommand.java:148)
at com.sun.enterprise.cli.commands.StartDomainCommand.runCommand(StartDomainCommand.java:215)
at com.sun.enterprise.cli.framework.CLIMain.invokeCommand(CLIMain.java:171)
at com.sun.enterprise.cli.framework.CLIMain.main(CLIMain.java:79)
Redirecting output to /opt/glassfish/glassfish-v2-1-1-b31g/domains/domain1/logs/server.log
Warning: Cannot open log file: /opt/glassfish/glassfish-v2-1-1-b31g/domains/domain1/logs/jvm.log
Warning: Forcing option -XX:LogFile=/tmp//hs_pid1188.log
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at com.sun.enterprise.server.PELaunch.main(PELaunch.java:415)
Caused by: java.lang.RuntimeException: Serious Error Couldn't open Log Filejava.io.FileNotFoundException: /opt/glassfish/glassfish-v2-1-1-b31g/domains/domain1/logs/server.log (Permission denied)
at com.sun.enterprise.server.logging.FileandSyslogHandler.publish(FileandSyslogHandler.java:508)
at java.util.logging.Logger.log(Logger.java:458)
at java.util.logging.Logger.doLog(Logger.java:480)
at java.util.logging.Logger.log(Logger.java:524)
at com.sun.enterprise.server.PEMain.main(PEMain.java:352)
... 5 more

dIESEL said...

i would also like to know how to run it on port 80