AddThis

Wednesday, August 31, 2011

Easy SSH and Cygwin

SSH-ing into a remote machine (that's running an SSH server) is super easy, but can be a major pain having to input the password over and over.  This is especially true on a Windows machine.  You can use putty, but I prefer using Cygwin because I get all my favorite linux utilities :)  Here's how to make all that work:

Setup
  1. Download and install cygwin with the openssh and the keychain package
  2. Run cygwin
  3. Enter in the terminal:
    1. ssh-keygen -t rsa
    2. choose some password, and enter it again to confirm
  4. vi ~/.bashrc and put this at the button of the file:
keychain ~/.ssh/id_rsa.pub
source ~/.keychain/${HOSTNAME}-sh

Usage
To get be able to log in to the remote machine, simply append the contents of your local ~/.ssh/id_rsa.pub to ~/.ssh/authorized_keys on the remote machine (create the file on the remote machine if it does not exist). *If the authorized_keys file doesn't exist, create it and make sure that the permission is at least 700!

Config
If you typically ssh using another user, or want to setup an alias to be able to quickly ssh somewhere, you can configure ssh to do this.  Simply vi ~/.ssh/config (create the file if it doesn't exist) and model your entries after the following:

Host server
  Hostname server.fully.qualified.name
  User admin

Now to be able to ssh into server.fully.qualified.name as the admin user, simply type in:
ssh server
whereas before you had to type in
ssh admin@server.fully.qualified.name

Friday, August 26, 2011

Run Jetty Externally and Connect Remotely With Eclipse

There's another alternative to embedding Jetty inside Eclipse.  We can also use Eclipse to use Maven to start Jetty for us.  Then we can remotely connect and debug/manage it.  It's your choice as to which option you prefer.


Configure Maven to run Jetty

<plugin>
        <groupId>org.mortbay.jetty</groupId>
<artifactId>maven-jetty-plugin</artifactId>
<version>6.1.24</version>
<configuration>
 <connectors>
<connector implementation="org.mortbay.jetty.nio.SelectChannelConnector">
                  <!-- Use whatever you want the http port to be -->
 <port>8080</port>  
</connector>
 </connectors>
 <userRealms>
<userRealm implementation="org.mortbay.jetty.security.HashUserRealm">
 <name>default</name>
 <config>src/main/resources/jetty-realm.properties</config>
</userRealm>
 </userRealms>
          <!-- If you plan on changing this file during execution, turn the scan interval higher than 0 -->
 <scanIntervalSeconds>0</scanIntervalSeconds>
 <webDefaultXml>src/main/resources/webdefault.xml</webDefaultXml>
</configuration>
</plugin>

You will need a jetty-realm.properties file and a webdefault.xml file.

jetty-realm.properties:
user1: pass1,role1
user2: pass2,role2

webdefault.xml:
Mine looks like the "JSP configuration" section



Setup Start Server Command
  1. Run -> External Tools -> External Tools Configuration 
  2. Right Click Program -> New
    1. Name: Whatever
    2. Location: Browse to your mvn executable
    3. Working Directory: click Browse Workspace button and select ${YOUR_WEB_PROJECT}
    4. Arguments: jetty:run
  3. Click Environment
    1. Click New
    2. Enter a variable names MAVEN_OPTS and set it to "-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=n"


Setup Remote Debugging
  1. Run -> Debug Configurations
  2. Right Click Remote Java Application -> New
    1. Name: Whatever
    2. Project: ${YOUR_WEB_PROJECT}
    3. Connection Type: Standard (Socket Attach)
    4. Host: localhost
    5. Port: 8787
  3. Also click "Allow termination of remote VM".  It's going to be the only way to elegantly kill your Jetty server without opening the task manager.


Usage
  1. Start the server using the external tools 
  2. Start the remote debugging once the server is up
  3. Open up the debug perspective -> Right click the VM and click terminate to kill the server

Setting up Jetty to run inside of Eclipse

Jetty is a great lightweight server that I'm using to do both my frontend and backend development.  For the focus of this tutorial, we will have a frontend slant.  This tutorial in particular will cover how to setup Eclipse (Helios) to deploy my webapp to Jetty so that I can quickly see my UI tweaks and changes.

Install Jetty
  1. Help -> Install New Software
  2. Work with: http://download.eclipse.org/jetty/updates/jetty-wtp
  3. Click Add
  4. Install Jetty and restart Eclipse

Prepare Your Web Project
  1. cd ${YOUR_WEB_PROJECT}
  2. mvn eclipse:eclipse -DdownloadSources=true -DdownloadJavadocs=true
  3. Import your project into eclipse as an existing project
  4. Right click your web project and go to Project Facets
  5. Click Dynamic Web Module
  6. Select Deployment Assembly
  7. Make sure your Deploy Path: / is the directory one above where WEB-INF lives.
    1. If not, go to Add... -> Folder and select WEB-INF's parent folder (It'll be something like webapp, or WebContent).
  8. Now click Add.. -> Java Build Path Entries
  9. Select them all using shift for multiselect and click ok


Prepare Jetty and Eclipse
  1. Click Window -> Show view -> Servers
  2. Right click the servers view -> New -> Server
  3. Select Jetty 8 or whatever you fancy
    1. Server's host name: localhost
    2. Server's name: Whatever you want
    3. Server runtime environment: click the add button on the right
      1. Name: Whatever
      2. Jetty installation directory: click the Download and Install button to the right -> Accept agreement -> select a location to download
      3. This is important....Wait a bit for the download to complete (look at the eclipse progress in the lower right and wait for it to complete.  
      4. When done, set the Jetty installation directory to the directory you just downloaded and installed jetty to
    4. JRE: Don't let this fool you, configure it to point to a jdk, not a jre.  
      1. If you don't have one, dl it and configure it using the Installed JREs... button
  4. Click Next
  5. Select your ${YOUR_WEB_PROJECT} to add as a deployment
  6. Click Finish


Setup Realms for Login
  1. Open up etc/realm.properties and add in your favorite user and passwords (USER1: password,role1,role2)
  2. Save and close
    1. If you edit this file later to add more users, remember to clean and publish for the changes to be picked up.  You do this by right clicking the server in the servers view and selecting clean.  After its finished, right click it again and select republish/publish.


Setup Ports
  1. Double click the server you just created to open up its configuration
  2. Select the Overview tab
  3. Look for the Ports section
  4. Click HTTP and change to whatever port you want


Usage
Right Click the server in the Servers view to manage the server.  You'll be able to start, stop, restart, and debug from here.


And thats's pretty much it.  Super easy and straightforward.

Thursday, August 18, 2011

No Time for SQL Date

We have a stored proc (ugh) that is called from within Hibernate.  We pass in values to this stored proc using the type, java.sql.Date.  The stored proc then does comparisons against some date column against the date object we passed in, but we were noticing that the time portion was being ignored!  The answer was simple and frustrating, java.sql.Date ignores time (should have read the javadocs sooner) :( We had to instead use java.sql.Time.  I would have much rather preferred we NOT use stored procs.  A few quick benchmarks and noticed that the stored proc to get a count versus a Hibernate projection was on average four times slower.  What can you do when the client loves stored procs?

http://download.oracle.com/javase/6/docs/api/java/sql/Date.html

Tee Off!

I love the tee command.  It's simple and beautiful and allows you to echo your output to both the console and to a file.

./run.sh | tee run.out

Here, my run.sh output will be nicely shown on the screen for me, but if the contents exceed my console's buffer, have no fear!  The output is also echoed to run.out.  Yay!

Java Integration Tests

You have unit tests and integration tests, but how do you manage the two?  Can you easily partion them so that you only run unit tests at one time and integration tests at another?  Then have them both run before building your artifact?  Yea, maven makes it real easy.  You might already know about the surefire plugin, the plugin used to run unit tests.  It looks for classes ending or starting with Test (**/Test*.java, **/*Test.java, and **/*TestCase.java) and runs them in the "test" phase.  But there is another plugin, failsafe, which is used to run integration tests and is run during the "integration-test" phase.  The failsafe plugin looks for classes ending or starting with IT (**/IT*.java, **/*IT.java, and **/*ITCase.java) and runs those.

The failsafe plugin has four phases that it uses:
  1. pre-integration-test - the setup phase.  use it to start a webserver or configure data in a database.
  2. integration-test - runs the tests.
  3. post-integration-test - the teardown phase.  use it to stop your webserver or clean your database.
  4. verify - used to help intepret results of the tests.  if any tests failed, the build will exit.

Configuration:
Surefire
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <version>2.7.2</version>
        <configuration>
          <testFailureIgnore>true</testFailureIgnore>
        </configuration>
      </plugin>

Failsafe
      <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>failsafe-maven-plugin</artifactId>
        <version>2.4.3-alpha-1</version>
        <executions>
          <execution>
            <goals>
              <goal>integration-test</goal>
              <goal>verify</goal>
            </goals>
          </execution>
        </executions>
      </plugin>

Another approach that I have done on previous projects is to leave all my unit tests in their appropriate projects and package all of my integration tests into a separate project that I run every few hours everyday in an integration test environment.

Wednesday, August 17, 2011

Spring and JBoss Integration

Oh Spring and JBoss, can't you two just play nice? What is this "java.util.zip.ZipException" nonsense? Well turns out that JBoss attempts to standardize all of its resource access, regardless of where the actual resource is located, be it a jar or some directory. This is accomplished by abstracting away this access using a VFS, or Virtual File System.
This is where Spring and JBoss collide. When Spring performs its resource scanning, it assumes direct access from either a jar or directory, and consequently uses corresponding URLs, which clashes with VFS. JBoss has a fix for this however and replaces Spring's ClassPathXmlApplicationContext with its own VFSClassPathXmlApplicationContext.

All you have to do is include the snowdrop-vfs.jar and one or both of the following:

If you load spring using the ContextLoaderListener say for services, then you would do the following:


<context-param>
  <param-name>contextConfigLocation</param-name>
  <param-value>classpath*:spring-contexts/*.xml</param-value>
</context-param>
<context-param>
  <param-name>contextClass</param-name>
  <param-value>org.jboss.spring.vfs.context.VFSXmlWebApplicationContext</param-value>
</context-param>
<listener>
  <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>


If you also have a servlet for web requests, then you would do the following:

<servlet>
  <servlet-name>spring-mvc-servlet</servlet-name>
  <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  <init-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/mvc-config.xml</param-value>
  </init-param>
  <init-param>
    <param-name>contextClass</param-name>
    <param-value>org.jboss.spring.vfs.context.VFSXmlWebApplicationContext</param-value>
  </init-param>
</servlet>


*JBoss EAP 5.1
*Spring 2.2
*snowdrop-vfs.zip (version 1.0)