Thursday, May 26, 2011

Yourkit & Tomcat webapp on Fedora

Yourkit is a great tool for profiling Java applications.  I'm using it to do some profiling on our webapp that is deployed in a Tomcat on a remote server (virtual machine on Rackspace).  I've found that Yourkit is really simple and intuitive to use and set up, for the most part.

The only issue I've had was getting it set up on the remote server to hook my local GUI to.  Theoretically, it is a very simple process.  Download yourkit to the remote server, start up tomcat, and type the following at the command prompt:

/bin/yjp.sh -integrate

I've downloaded & installed the linux version into my /opt/ folder on my remote server.  My remote server is Fedora 14 64bit.  When I run the above command, I get the following prompts:




And here is where I run into a problem. Where is the tomcat startup.sh?? I do a search on the remote machine for the file and come up empty handed. I sift around online and come up empty handed.  Finally after trial and error, I find that the file that is used on Fedora for starting up tomcat is called:

/usr/sbin/tomcat6

I would have thought this would be the end of it.  Unfortunately, it looks the -integrate command munges the startup.sh to add an additional JAVA_OPTS to create the hooks for Yourkit.  And of course /usr/sbin/tomcat6 is not formatted how Yourkit is expecting the startup.sh to be formatted.  So no go.

The next option is to manually add the JAVA_OPTS to the file.  What I've done is add the following:

-agentpath:/opt/yjp-9.5.6/bin/linux-x86-64/libyjpagent.so=port=10001

after the {JAVA_OPTS} in the start block of the /usr/sbin/tomcat6 script (around line 30):
if [ "$1" = "start" ]; then
  ${JAVACMD} $JAVA_OPTS -agentpath:/opt/yjp-9.5.6/bin/linux-x86-64/libyjpagent.so=port=10001 $CATALINA_OPTS \
    -classpath "$CLASSPATH" \
    -Dcatalina.base="$CATALINA_BASE" \
    -Dcatalina.home="$CATALINA_HOME" \
    -Djava.endorsed.dirs="$JAVA_ENDORSED_DIRS" \
    -Djava.io.tmpdir="$CATALINA_TMPDIR" \
    -Djava.util.logging.config.file="${CATALINA_BASE}/conf/logging.properties" \
    -Djava.util.logging.manager="org.apache.juli.ClassLoaderLogManager" \
    org.apache.catalina.startup.Bootstrap start \
    >> ${CATALINA_BASE}/logs/catalina.out 2>&1 &
    if [ ! -z "$CATALINA_PID" ]; then
      echo $! > $CATALINA_PID
    fi

I have added an additional startup option to this, specifying the port to use.  Pay close attention when inserting this option and be sure that is a space between $JAVA_OPTS and [agentpath] as well as a space between [agentpath] and $CATALINA_OPTS.  Because I will not always want the agent attached (overhead and performance reasons), I created two copies of the tomcat6, a tomcat6_yourkit & tomcat6_orig (original tomcat6 file) that I copy to tomcat6 as needed to swap the configurations.

Finally, the last thing that needs to be done is to open up the port in the iptables file on the remote server to allow the connection to be made.

Summary:
  1. Download the correct distribution for the remote server's platform to /opt/.
    (In my case I need the Linux distribution)
    [root@bakeYourkit opt]# wget http://www.yourkit.com/download/yjp-9.5.6-linux.tar.bz2
  2. Extract the file.
    (In my case it is a tar.bz2, which I always forget how to do).
  3. Make a copy of /usr/sbin/tomcat6 as /usr/sbin/tomcat6_orig
    [root@bakeYourkit ~]# cp /usr/sbin/tomcat6 /usr/sbin/tomcat6_orig
  4. Edit /usr/sbin/tomcat6, save, and make a copy as /usr/sbin/tomcat6_yourkit
    [root@bakeYourkit ~]# vim /usr/sbin/tomcat6
    [root@bakeYourkit ~]# cp /usr/sbin/tomcat6 /usr/sbin/tomcat6_yourkit
    
  5. Edit the iptables to listen to the port specified in the startup option above (in my example here, port number 10001).  See this post for information about editing the iptables file.
  6. Restart tomcat to pick up the options.
  7. On your local machine, start up yourkit and connect to the remote server:
Ta-da!  That's all.  Now if you want to switch off the agent, copy the original /usr/sbin/tomcat6_orig over the /usr/sbin/tomcat6 file.  There is definitely a nicer way to this, possibly by adding some environment variable and setting it to.  But this works for me.

Monday, May 23, 2011

Perl script to "copy" a Rackspace image


I recently found myself putting together a perl script that performs an rsync of one server in the Rackspace cloud to another server on another account.  Why?  See my next post about restrictions found with Rackspace for details.  Long story short, I needed a way to copy an image from one account to another and Rackspace recommends using rsync.

Since I will be needing to do this at least once a month for my testing, I thought it best to write up a script using perl that does the rsync.  The first thing was to figure out to successfully do this rsync before putting things together in a script.  I followed the instructions and when I rebooted my new server with the files rsync'ed over, it failed to accept ssh anymore.  On a whim, I decided to go through the basic exclude file from the instructions to see if those directories/files really lived where the file says they would be.

Ah-ha! That was my problem. I'm not sure which distro was used to create the exclude file, but some of the recommended files/directories to be excluded were located in different places.

#Suggested by Rackspace
/etc/hostname

#Actual location on Fedora 14 64bit
/bin/hostname
 

#Suggested by Rackspace
/etc/modules 

#Actual location on Fedora 14 64bit
/etc/sysconfig/modules

What I did was to do a
find / -name [sometext]

Where [sometext] I started from the end of the path and worked my way in to find the location. It was definitely trial and error.  Here is what I have for my final exclude file for Fedora 14 64bit:

#exclude.txt
/proc
/sys
/tmp
/dev
/root/copyImage.log
/root/.ssh/
/var/lock
/etc/fstab
/etc/mtab
/etc/resolv.conf
/usr/share/dbus-1/interfaces
/etc/networks
/etc/sysconfig/network
/etc/sysconfig/network-scripts
/etc/sysconfig/iptables-config
/lib/modules/
/usr/share/selinux/devel/include/kernel
/bin/hostname
/usr/lib64/gettext/hostname
/etc/hosts
/etc/modprobe*
/etc/selinux/targeted/modules
/etc/selinux/targeted/modules/active/modules
/etc/sysconfig/modules
/etc/selinux/targeted/modules
/etc/selinux/targeted/modules/active/modules
/usr/lib64/gio/modules
/lib/udev/devices/net
/usr/lib/ruby/1.8/net
/etc/init/

So now that I have a working exclude file, the next thing was to code up a perl script to do this for me.  In order to automate this through the script I needed to be able to:
  • Create an ssh tunnel from the "sending" server to the "receiving" server and be able to generate an ssh key on the "receiving" server.
  • Add the "sending" server's public key to the "receiving" server's authorized_key file
    • In my case, as part of the image, there is an authorized_key file with some public keys in it, which I want available to all servers generated with the image. I added the "sending" server's public key to this file and rsync'ed this file over first
  • Rsync the "sending" server data to the "receiving" server.
Two of the largest hurdle is:
  1. Open the ssh connection to the "receiving" server
  2. Know when the "receiving" server is asking for the password and supply it
There are many many perl modules available that do just this in various ways. I didn't think to make a note of which ones I did try, unfortunately.  I ended up using Net::OpenSSH, it had the best documentation and did everything I needed.  I used this in conjunction with Expect module.


Neither of these modules are included with the Perl package that comes with Fedora 14 64 bit.  In trying to add these modules, I learned some more things.  For example, I learned about CPAN.  This is a little piece of software that manages installation and dependency resolution for perl modules.  Other benefits I found are:
  • Access to modules that may not be in repos yet, i.e. Net::OpenSSH is not available via yum on Fedora 14
  • Type in instmodsh at the command prompt and you can see a list of all installed modules and get information about the modules
    • If module is installed via yum install , will not show up in instmodsh
Here is a link describing how to install CPAN.  After you follow the instructions at that link, you should also check to see if gcc is installed.  In my case, it was also not included in my default Fedora 14 64bit installation.  It is needed to compile some of the modules (in this case, one of the dependencies for Expect).  The error I got before I installed it is:

ERROR: cannot run the configured compiler 'gcc'
(see conf/compilerok.log). Suggestions:
1) The complier 'gcc' is not in your PATH. Add it
   to the PATH and try again. OR
2) The compiler isn't installed on your system. Install it. OR
3) You only have a different compiler installed (e.g. 'gcc').
   Either fix the compiler config in the perl Config.pm
   or install a perl that was built with the right compiler
   (you could build perl yourself with the available compiler).

Note: this is a system-administration issue, please ask your local
admin for help. Thank you.

Warning: No success on command[/usr/bin/perl Makefile.PL]
'YAML' not installed, will not store persistent state
  TODDR/IO-Tty-1.10.tar.gz
  /usr/bin/perl Makefile.PL -- NOT OK
Could not read metadata file. Falling back to other methods to determine prerequisites
Failed during this command:
 TODDR/IO-Tty-1.10.tar.gz                     : writemakefile NO '/usr/bin/perl Makefile.PL' returned status 6400

Finally, my last hurdle for putting together this script is trouble using the open function in perl.

#DOES *NOT* WORK
open(CAT_FILE,"cat /root/test.txt >>/root/test2.txt ") || die "Failed: $!\n";

#DOES WORK
open(CAT_FILE,"| cat /root/test.txt >>/root/test2.txt ") || die "Failed: $!\n";

Can you spot the difference?
So apparently that "|" is required ... oops...guess the documentation was right. *insert chagrin here*.

So without further ado, please find below my full script to do the rsync step of copying an image to another server on Rackspace:

Tuesday, February 15, 2011

Tomcat 6 & Fedora 14 frustrations

More woes trying to set up a server image.  Current pothole (as opposed to speed bump) is being brought to you by Tomcat 6 and Fedora 14. Having just gone through a whole lot of hoop-la getting java installed, I installed Tomcat with this simple command:

root@spin-1-16r tomcat6]# yum install tomcat6


First woe:
My woes began when I tried to start up tomcat how I started it up on Rhel:

[root@spin-1-16r tomcat6]# tomcat6 start
/usr/sbin/tomcat6: line 30: /logs/catalina.out: No such file or directory


What? How is an error happening when I haven't done anything but use the package installer yum to install tomcat? This time, I read my error carefully and decided to look in the file /usr/sbin/tomcat6, line 30 for the offending code which was:

    org.apache.catalina.startup.Bootstrap start >> ${CATALINA_BASE}/logs/catalina.out


Looking through the file, I don't see CATALINA_BASE defined. And then going back to the command prompt, I discover the environment variable CATALINA_BASE isn't defined anywhere:

[root@spin-1-16r webapps]# echo $CATALINA_BASE


More searching and I find that it is defined in /etc/tomcat6/tomcat6.conf and going back to the /usr/sbin/tomcat6 file, I see that the following is commented out:

# Get the tomcat config (use this for environment specific settings)
#if [ -z "${TOMCAT_CFG}" ]; then
#  TOMCAT_CFG="/etc/tomcat6/tomcat6.conf"
#fi
#
#if [ -r "$TOMCAT_CFG" ]; then
#  . $TOMCAT_CFG
#fi


Removing the comments from in front of lines 2-8 and saving solved this first issue.

*EDIT*
Avoid first woe sub-part one:
Remember earlier we went through some troubles to set up Sun's java and even set up some environment variables? We probably want to keep using Sun's java for tomcat. Open up the tomcat config file:
[frog@caffiend ~]# less ~tomcat/conf/tomcat6.conf

At the top of the file, after the comments about what file is for, you should see these lines:
# Where your java installation lives
JAVA_HOME="/usr/lib/jvm/java"

Now I'm not 100% that this will over-write the environment variable previously set, nor do I know whether or not that link will end up at the same location or not....so to be safe, I've commented it out on my server:
# Where your java installation lives
#JAVA_HOME="/usr/lib/jvm/java"

Second woe:
Now the next woe began.  For the purposes of work, the webapp war is dropped into the /usr/share/tomcat6 folder and a symbolic link is created in the webapp folder pointing to the war.  This is done because for our testing purposes, we swap various versions of the war, including snapshots, in and out and our deployment code to push out and configure multiple nodes have a hard link to the URL.  We could always just change the name of the war to match what we have in the URL in our code, but then we would lose the quick at a glance sanity check of which version we are running.  So that is what I did.  And I started up tomcat, but EGADS, the war would NOT inflate and deploy.  Why, oh why?  After much googling on keywords like symbolic link not deploying war tomcat6 fedora14, so on and so forth...and bringing in a second pair of eyes...it hits me like a ton of bricks:

[root@spin-1-16r tomcat6]# ls -l webapps/
total 0
lrwxrwxrwx 1 root root     39 Feb 15 22:10 node-server -> /usr/share/tomcat6/node-server-1.16.war


Do you see it now? It sure took me a while...my sym link did NOT end in .war. And that...is all it took. Changing the sym link and restarting tomcat my directory now looks like:

[root@spin-1-16r webapps]# ls -l
total 8
drwxr-xr-x 2 root root 4096 Feb 15 23:52 logs
drwxr-xr-x 4 root root 4096 Feb 15 23:52 node-server
lrwxrwxrwx 1 root root   39 Feb 15 23:52 node-server.war -> /usr/share/tomcat6/node-server-1.16.war


And thus ends my woes. It looks so simple and duh all summed up here, but man, was it hard to see for me.

Ubuntu (v10.04) update frustrations

*EDIT*
I wrote this a few months back and I'm not quite sure why I never published it...might have been one of those days...hopefully it's correct, if it's not, please let me know.
 

Finally decided to do the updates that my Ubuntu has been asking me about for a week or so now.  And of course, my Eclipse breaks because Ubuntu keeps trying to change my java to OpenJDK, which does not play together happily with Eclipse (v3.3). I'm sure others must also have this problem, so here is my step by step troubleshooting:
  1. Did  the update change the environment variables?
    • Check the bashrc file:
      frog@caffiend:~$ vi ~/.bashrc
      

      Where vi is your console editor. You can use any editor you like. The file should contain the following, most likely at the end:
      export JAVA_HOME=/usr/lib/jvm/java-6-sun-1.6.0.20/
      
  2. Did the update change the symbolic link?
    • First find your Sun Java directory. I think it usually gets installed in /usr/lib/jvm. One way is to do a search from the FileSystem using the File Browser for "sun".  You're looking for a folder with a name like: java-x-sun-n.n.nn, where x is the version of java (nowadays, most likely 6...possibly 5) and n.n.nn is the release. 
    • Now check to make sure the java folder is pointing correctly to the alternatives folder:
      frog@caffiend~:$ ls -l /usr/bin/java
      lrwxrwxrwx 1 root root 22 2010-11-02 12:26 /usr/bin/java -> /etc/alternatives/java
      
    • Now check where the alternatives folder is pointing to:
      frog@caffiend~:$ ls -l /etc/alternatives/java
      lrwxrwxrwx 1 root root 36 2010-11-02 12:26 /etc/alternatives/java -> /usr/lib/jvm/java-6-sun/jre/bin/java
      
    • If one or both of these symbolic links are not pointing to the correct location:
      frog@caffiend~:$ cd /usr/bin/
      frog@caffiend~:$ sudo ln -f -s /etc/alternatives/java java
      frog@caffiend~:$ cd /etc/alternatives/
      frog@caffiend~:$ sudo ln -f -s /usr/lib/jvm/java-6-sun/jre/bin/java java
      
  3. Did the update change which Java is being used?
    • frog@caffiend~:$ udo update-alternatives --config java
      [sudo] password for frog: 
      There are 2 choices for the alternative java (providing /usr/bin/java).
      
        Selection    Path                                      Priority   Status
      ------------------------------------------------------------
        0            /usr/lib/jvm/java-6-openjdk/jre/bin/java   1061      auto mode
        1            /usr/lib/jvm/java-6-openjdk/jre/bin/java   1061      manual mode
      * 2            /usr/lib/jvm/java-6-sun/jre/bin/java       63        manual mode
      
      Press enter to keep the current choice[*], or type selection number: 2
      
  4. Confirm that the correct Java is being used:
    • frog@caffiend~:$ which java
      /usr/bin/java
      frog@caffiend:/usr/bin$ java -version
      java version "1.6.0_22"
      Java(TM) SE Runtime Environment (build 1.6.0_22-b04)
      Java HotSpot(TM) Server VM (build 17.1-b03, mixed mode)
      
Now try starting Eclipse.  There is a chance you may still get an error if you use Maven, subclipse.  A solution can be found here.

Errors Installing Java JDK on Linux.

Several hours that I will never get back have just been lost due to errors received trying to install Sun's Java (specifically the JDK) on a virtual machine.  I had previously been able to install the JDK without much of a hiccup last fall on the virtual machine at this particular vendor, and was quite puzzled as to why this was no longer working.  Googling the error and various keywords didn't point out any obvious issues, everything seemed to say that Fedora 14 and Sun Java played well together, with the exception of having to configure the alternatives to point to the correct java (which I knew).

[root@spin-1 opt]# sh ./jdk-6u22-linux-i586.bin 
Unpacking...
Checksumming...
Extracting...
./jdk-6u22-linux-i586.bin: ./install.sfx.20270: /lib/ld-linux.so.2: bad ELF interpreter: No such file or directory

Fine, let's try the self extracting rpm version:
[root@spin-1 opt]# sh ./jdk-6u22-linux-i586-rpm.bin 
Unpacking...
Checksumming...
Extracting...
./jdk-6u22-linux-i586-rpm.bin: ./install.sfx.20566: /lib/ld-linux.so.2: bad ELF interpreter: No such file or directory
Installing JavaDB
error: open of sun-javadb-common-10.5.3-0.2.i386.rpm failed: No such file or directory
error: open of sun-javadb-core-10.5.3-0.2.i386.rpm failed: No such file or directory
error: open of sun-javadb-client-10.5.3-0.2.i386.rpm failed: No such file or directory
error: open of sun-javadb-demo-10.5.3-0.2.i386.rpm failed: No such file or directory
error: open of sun-javadb-docs-10.5.3-0.2.i386.rpm failed: No such file or directory
error: open of sun-javadb-javadoc-10.5.3-0.2.i386.rpm failed: No such file or directory
 
Done.

After much googling, I kept coming back to this one forum post. In the middle of it, there is the following information from a poster:

"The library you are missing is comes from the 32bit version of the glibc. You can try installing the i386 version of glibc using yum. That would install /lib/ld-linux.so.2 for you."

Great, so let's try installing the glibc ... (some of you may be seeing where this is going, but sadly I did not yet).

[root@spin-1 opt]# yum install glibc*

Alright, so now that's installed, I tried installing java again...to no avail. Scrolling back up the console to at the yum output from installing the glibc* I see:
=============================================================================
 Package                       Arch     Version             Repository Size
=============================================================================
Installing:
 gcc                           x86_64   4.5.1-4.fc14        fedora     14 M
Installing for dependencies:
 cloog-ppl                     x86_64   0.15.7-2.fc14       fedora     93 k
 cpp                           x86_64   4.5.1-4.fc14        fedora     4.0 M
 glibc-devel                   x86_64   2.13-1              updates    968 k
 glibc-headers                 x86_64   2.13-1              updates    599 k
 kernel-headers                x86_64   2.6.35.11-83.fc14   updates    742 k
 libmpc                        x86_64   0.8.1-1.fc13        fedora     44 k
 mpfr                          x86_64   2.4.2-1.fc13        fedora     158 k
 ppl                           x86_64   0.10.2-10.fc12      fedora     1.1 M

Transaction Summary
=============================================================================
Now wait just a hot minute, why is it installing the x86_64 and not the i386 32bit ones....^Insert light bulb.

That's right folks, the virtual machine is 64 bit and I was trying to install a 32bit version of Java.  Some time between when I last tried this particular exercise out on the vendor and now, the vendor moved from 32bit OS's to 64bit OS's.  To verify:

[root@spin-1 opt]# uname -m
x86_64

Well would you look at that, my vm's architecture is x86_64. :: sigh :: downloading the 64 bit version of Java JDK resolved the issues.

For completeness of this post, some links to get started with Sun JDK Java and Tomcat 6 on Fedora 14, in order of things to do.
  1. Configuring yum repositories on fedora
    • On the remote machine, as root user, do the following:
      yum --nogpgcheck install http://rpm.livna.org/livna-release.rpm http://download1.rpmfusion.org/free/fedora/rpmfusion-free-release-stable.noarch.rpm http://download1.rpmfusion.org/nonfree/fedora/rpmfusion-nonfree-release-stable.noarch.rpm
  2. On the remote machine, as root user, do the following:
    yum update 

  3. Download the 64 bit version of Java JDK desired onto local machine and then scp the file to the /opt directory of the remote machine

  4. On the remote machine, possibly need to be remote user, do the following:
    [root@spin-1 opt]# sh ./opt/jdk-6u22-linux-x64.bin 

  5. *EDIT*
    (realized I also did the following and it is not included in the link at step 6, not entirely sure of the necessity, but I did this anyways just to make sure and everything is working)
  6. Add the following environment variables (not included as part of the directions in 6, may not be 100% necessary, but I did this and everything work) to the end of ~/.bashrc:
    export JAVA_HOME=/opt/jdk1.6.0_22
    export JRE_HOME=${JAVA_HOME}/jre
    export PATH=${JAVA_HOME}/bin:${PATH}
    export CLASSPATH=${JAVA_HOME}/jre/lib:${CLASSPATH}
    

    This is what my ~/.bashrc looks like:
    # .bashrc
    
    # User specific aliases and functions
    
    alias rm='rm -i'
    alias cp='cp -i'
    alias mv='mv -i'
    
    # Source global definitions
    if [ -f /etc/bashrc ]; then
            . /etc/bashrc
    fi
    
    export JAVA_HOME=/opt/jdk1.6.0_22
    export JRE_HOME=${JAVA_HOME}/jre
    export PATH=${JAVA_HOME}/bin:${PATH}
    export CLASSPATH=${JAVA_HOME}/jre/lib:${CLASSPATH}
    

    Save the file and from the command prompt, source the file:
    [root@newImage ~]# source ~/.bashrc 
    

    Now do an echo to make sure the environment variable exists and points to the correct location:
    [root@newImage ~]# echo $JAVA_HOME
    /opt/jdk1.6.0_22

    You should see the location your jdk is installed, my jdk is installed in /opt/.
    N.B.For the testing that we're doing here at work, we're always either logged in as root or tomcat is logged in as tomcat. I'm not familiar enough with environment variables and bash scripts to know where they need to be or what needs to be done to ensure the variable persists through all users.

  7. Follow the directions found here for setting up the alternatives in Fedora to point to the correct java distro

  8. Install tomcat:
    yum install tomcat6*.*

Tuesday, January 4, 2011

Remote debugging webapp in Tomcat (Rhel) through Eclipse (Ubuntu)

Background to my current issue:
There appears to be something odd going on the server side of our network code. Our server is a virtual machine hosted on GoGrid and the oddness is only occurring in release 1.14 and later of our network code.  The current trunk of our code is 1.16-SNAPSHOT and the network code on the vm is 1.15 (release).

I've spent the better of today getting right set of convocations together for my particular set of system set ups.  Specifically:
Locally
* Ubuntu 10.04 (Lucid Lynx)
* Eclipse 3.5

Server Side
* Rhel 5.4
* Tomcat 6

Hopefully the following represents an accurate list of steps to assist anyone else with setting up a remote debugging of a webapp running on a Tomcat elsewhere through Eclipse on your local machine.

  • Setting up tomcat to start up in debug mode:
    • Most of the websites I came across suggest adding a command after the script:

       [host]$ catalina.sh jpda start 
      (Mulesoft's blog)
    •  
    • For my particular set up, I did not have a catalina.sh script file to manipulate.  Instead, Rhel's installation of Tomcat6 creates a conf folder and a conf file where the options are set.  In my case, the specific file name is tomcat6.conf and was found in ~tomcat6/conf/
      • In this file, I added the following lines after setting where the installation lives (noting that this should be the first JAVA_OPTS set):
         # Java option to turn on debugger FIRST
        JAVA_OPTS="-Xdebug -Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=n" 

        NB: that there can not be any spaces around the initial "=". The above is NOT equivalent to:
        JAVA_OPTS = "-Xdebug -Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=n" 

    • Now it's time to restart (bounce) the tomcat for the tomcat to pick up the changes in the JVM arguements:
      [host]$ /etc/init.d/tomcat6 restart 

  •  Setting up the server to listen to the port that has been designated in the above step for the debugger (in this example, 8000, see the numbers after "address")
    • Now the appropriate ports need to be opened on the iptables:
      [host]$ vim /etc/sysconfig/iptables 

      And add this line into the file and save it:
      -A RH-Firewall-1-INPUT -p tcp -m state --state NEW -m tcp --dport 8000 -j ACCEPT
      

      This line should go along with the other similar statements in the file. Once the file has been saved, the iptables need to be restarted for the changes to take affect:
      [host]$ /etc/init.d/iptables restart

  • Since my server is hosted on GoGrid, I know that they have a firewall in place. The next step is to create an ssh tunnel to my server. For the sake of usability, I installed "Gnome SSH Tunnel Manager - a front-end to ssh tunneling" and added the information for my server and opened up the tunnel with the followinig for the properties:
    • Name: GoGrid 252 [This can be anything that is easy for you to recognize]
    • Login: me [This is the login you would use to login to the server]
    • Host: ###.##.###.252 [This is the IP address of the server]
    • Port: 22 [This is the port that you have designated on your server as your ssh port, default is 22]

  • Finally, on my local machine in Eclipse, I had to do the following:
    • I needed the specific version of the code base project opened that the server was running.  In this case, I had been working on 1.16 SNAPSHOT, which I needed to close and open up the 1.15 release that is running on the server.
    • Click on any file in the project that contains the webapp code
    • From the Eclipse menu, navigate: Run -> Debug Configurations
    • In the left handle panel, navigate up to Remote Java Applications, right click over it and select New from the pop-up menu.
    • In the right hand panel you should now see 3 tabs and a name field.  The name field is for your reference and will show up on the left hand panel for you to select later.  Under the Connect tab you should fill in the following:
      • Project: [The project containing the source code for the webapp you are trying to debug in the remote Tomcat]
      • Connection Type: Standard (Socket Attach)
      • Host: ###.##.###.252 [This is the IP address of the server]
      • Port: 8000 [This is the designated debugging port that was set up on the server]
    • Click Apply and then Debug

  • In the source code for the webapp, put a breakpoint somewhere that you know will be hit and then send a request to your tomcat.  You should see be able to now debug in Eclipse.

And that summarizes up what I did to get the debugging to work on my local machine for a remote webapp on Tomcat.

Here are some links to blogs which assisted me in getting to this point:

http://forums.alfresco.com/en/viewtopic.php?f=10&t=1914&start=15
http://wiki.apache.org/tomcat/FAQ/Developing?highlight=%28CategoryFAQ%29

Hope this helps :).

Monday, November 8, 2010

Scala & Eclipse...Just keep cleaning...

Today's aggravation is most likely brought to you by the Scala IDE (v1.0.0.201009232358) plugin for Eclipse (v3.5.2.R35).  A simplified version of the offending code is:
  def nestedDoesntWork(num: Int) = {
    if (true)
      for (x <- 0 until num)
        println(x)
  }

Where I have some condition that is checked and if true, proceeds into a for-loop.  The error that I repeatedly get is:
  • Exception in thread "main" java.lang.NoSuchMethodError: scala.collection.immutable.Range$ByOne.foreach$mVc$sp(Lscala/Function1;)V
        at org.spin.node.gogrid.Client$.doesntWork(Client.scala:62)
        at org.spin.node.gogrid.Client$.main(Client.scala:72)
        at org.spin.node.gogrid.Client.main(Client.scala)
However, this seems to work:
  def nestedWorks(num: Int) = {
    if (true)
      for (x <- (0 until num).toList)
        println(x)
  }

Very odd. Even odder is if I define either of these functions on the Scala interpreter in Eclipse, they work fine. It's only when the nestedDoesntWork is defined within a class and I try to run a main function calling that class. The same happens if I take out the if(true) line.

Solution? Clean project...and look, everything is fine and dandy. Make a change, get the error? Clean the project, and hurray.  Note that the nestedWorks always works...without cleaning.

Annoying to say the least, but today's lesson is if it doesn't work when it should the first time, clean the project.  If it still doesn't work, clean it again. and again. and again.