Category: Hiberailooving

Jun 27 2008

Deploying Railo WAR on JBoss 4.2.2

Beta 2 of Railo 3.0 is available, and one of its download options is as a WAR suitable for any JEE server. In the Hiberailooving series, I'm building up a Hibernate + Railo + Groovy + Spring platform, and JBoss will be its intended deployment platform.

When you download the WAR, all you get is (literally) the WAR itself. To get it up and running in JBoss, you'll want to:

  1. Unzip the WAR and deploy to your /deploy directory. I used a new Dynamic Web Project in Eclipse to make this easier to manage, calling my project Railo and running in the context-root of Railo.
  2. Write a web.xml that configures the proper servlets/filters to start serving up CFML. I ripped and modified the one from the Railo Express distribution, modifying the Jetty-style filters to suit JBoss. For your convenience, it follows.

<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
   <display-name>Railo</display-name>
      
   <servlet>
      <servlet-name>CFMLServlet</servlet-name>
      <servlet-class>railo.loader.servlet.CFMLServlet</servlet-class>
      <load-on-startup>1</load-on-startup>
   </servlet>   
   
   <servlet>
      <servlet-name>AMFServlet</servlet-name>
      <servlet-class>railo.loader.servlet.AMFServlet</servlet-class>
      <load-on-startup>2</load-on-startup>
   </servlet>
         
   <servlet-mapping>
      <servlet-name>CFMLServlet</servlet-name>
      <url-pattern>*.cfm</url-pattern>
   </servlet-mapping>
   <servlet-mapping>
      <servlet-name>CFMLServlet</servlet-name>
      <url-pattern>*.cfml</url-pattern>
   </servlet-mapping>
   <servlet-mapping>
      <servlet-name>CFMLServlet</servlet-name>
      <url-pattern>*.cfc</url-pattern>
   </servlet-mapping>

   <welcome-file-list>
      <welcome-file>index.cfm</welcome-file>
      <welcome-file>index.cfml</welcome-file>
   </welcome-file-list>
</web-app>

Conclusion

Deploy the unzipped WAR, drop the XML above into WEB-INF/web.xml, and you should have a running CFML server. No admin, though, so I'm not too sure how to add a datasource....

3 comments - Posted by Joe Rinehart at 3:22 PM - Categories: Hiberailooving | Railo

Jun 26 2008

Hiberailooving, Part 3: Adding (and Testing!) Relationships and Rules

The Hiberailooving series chronicles the construction of a development environment and server configuration for creating redistributable JEE+CFML applications using Groovy, Spring, Hibernate, and Railo.

Last time, we set up a simple Groovy-based model of a Bike and a TestNG test case for verifying its behavior and state. This time, we're not going to break much new ground on the framework front. We'll still only be using Groovy and TestNG, but we're going to add a bit of complexity to our Model in order to learn a touch more about Groovy and to put Hibernate to a bit more of a test when we're ready to persist.

Bikes have Wheels

To write my bike shop application, I need to keep track of what Wheels are on what Bikes. I've got a simple business rule to follow as well: a Bike can't have more than two Wheels.

I guess that means I need to model a Wheel. I'll give it an id, name, and bike property, letting us know to which Bike the Wheel belongs. While I'm add it, I've added "Name" to Bike as well.

Wheel.groovy

package com.firemoss.bikeshop.model

class Wheel {

int id
private Bike bike
String name
}

Collecting Wheels

A Bike has a Collection of Wheels. (Ok, so I could and probably should create props of frontWheel and backWheel, but it's the one-to-many I'm really after here). In the Java world, and according to Java Persistence With Hibernate, I now need to know and choose from the Java collections API an appropriate collection for this relationship.

Sure, that's all available in Groovy, but I'd rather just use its Maps and Lists semantics.

In Groovy, much like CFML, you've basically got a choice between an Array (a "List") or a Struct (a "Map"). We've all done this before: a List is what we're after here.

Creating a List in Groovy is pretty simple:

def list = []

Yep, it's a lot like those ColdFusion 8 operators. Except this time they work (nested, for function calls, etc.). Also, note that a List is zero-indexed. It's really a java.util.List implementation.

For laughs, here's a Map:

def map = [id:1, name:"John"]

Yep, they used colons. Like the rest of the known world.

For more on Groovy collections (they're very, very cool, and take the Java Collections API to a new level), check out the User Guide.

Back to our Bike

Our bike needs a collection of wheels, and we're using a List. We want to have a bidirectional relationship, so we'll add a method "addWheel" that adds to a given Bike's collection of Wheels, assigning its "bike" property. While we're add it, we'll throw an error if some tricyclist tries to build a 3-wheeled bike. I wish I could ban recumbents and 650cc triathlon setups as well, but this is a simple example.

Sound complicated? It's not. Check out how clear the Groovy code is:

Bike.groovy, managing wheel collection.

package com.firemoss.bikeshop.model

class Bike {

int id
boolean sold = false
Date dateSold;
String name
List wheels = []

void sell()
{
sold = true
dateSold = new Date()
}

Bike addWheel(wheel)
{
// business rule: 2 wheels per bike. if (wheels.size >= 2)
throw new Exception("You can only have two wheels!");

wheels.add(wheel)

// add reflexive relationship if necessary if (wheel.bike != this)
wheel.bike = this;

// allow method chaining return this;
}

Bike removeWheel(wheel)
{
if (wheels.contains(wheel))
{
wheels.remove(wheel)
wheel.bike = null
}

return this;
}
}

Notice that I set up addWheel() to return the Bike itself. No real reason....I was just playing around with things like bike.addWheel(new Wheel()).addWheel(new Wheel()) to show that it works as you'd expect.

Wheel.bike needs a setter!

We've built addWheel() to change the passed wheel's "bike" property, but now we could end up in a bad place: what if the Wheel was already assigned to another Bike? It'd be in both of the Bike's "wheels" collections, which should be an impossibility! We need to add some behavior to the assignment of a Bike to a Wheel.

By default, Groovy will create (and invoke) getters and setters for public properties (the default access type). We're free to override those. We'll just set up Wheel with a setBike() method that overrides the generated to clean up the relationships, checking to make sure we don't enter a nasty bit of recursion:

Wheel.groovy

package com.firemoss.bikeshop.model

class Wheel {

int id
String name
public Bike bike


public Bike getBike()
{
return this.bike
}

public void setBike(Bike bike)
{
// remove from parent if assigned if (this.bike && this.bike != bike && this.bike.wheels.contains(this))
this.bike.removeWheel(this)

this.bike = bike

// add to parent if not in parent and not nulling the relationship if (bike && !bike.wheels.contains(this))
bike.wheels.add(this)
}
}

Whoa, what about tests?

Ok, I promise, I wrote the tests first. Really. I just wanted to get to the meat of what we were up to. I've updated the test to account for both the "two wheels per bike" rule and to give the association methods a pretty solid workout. Here it is:

BikeTest.groovy

package com.firemoss.bikeshop.test


import com.firemoss.bikeshop.model.*;
import org.testng.annotations.*
import org.testng.TestNG
import org.testng.TestListenerAdapter
import static org.testng.AssertJUnit.*;

public class BikeTest {

public static void main(String[] args){
def testng = new TestNG()
testng.setTestClasses(BikeTest)
testng.addListener(new TestListenerAdapter())
testng.run()
}


@Test
final void testSellBike(){
def bike = new Bike();

assertFalse(bike.sold && bike.dateSold)

bike.sell();

assertTrue(bike.sold && bike.dateSold);
}

@Test
final void testTooManyWheels(){
def bike = new Bike();
def ex = false;

try
{
bike.addWheel(new Wheel()).addWheel(new Wheel());
}
catch (e)
{
ex = true;
}

assertFalse("Shouldn't error on two wheels.", ex);

bike = new Bike();

try
{
bike.addWheel(new Wheel()).addWheel(new Wheel()).addWheel(new Wheel());
}
catch (e)
{
ex = true;
}

assertTrue("This ain't a tricycle.", ex);
}

@Test
final void testBikeWheelAssociation()
{
def bike1 = new Bike();
def bike2 = new Bike();
def wheel = new Wheel();

bike1.addWheel(wheel);
assertTrue(wheel.bike == bike1);

wheel.bike = bike2;
assertTrue(bike2.wheels.contains(wheel))
assertFalse(bike1.wheels.contains(wheel))

bike1.addWheel(wheel);
assertTrue(bike1.wheels.contains(wheel))
assertFalse(bike2.wheels.contains(wheel))


}

}

Conclusion

Ok, we've got a good sized Model now. It's got a one-to-many relationship (Many-to-many is overrated. I always get a ticket that requires turning the relationship into a model.) and a business rule, and we're testing the whole shebang.

Now if we could only save it to a database...

3 comments - Posted by Joe Rinehart at 12:30 PM - Categories: Hiberailooving

Jun 25 2008

Hiberailooving, Part 2: Modeling and Testing

The Hiberailooving series chronicles the construction of a development environment and server configuration for creating redistributable JEE+CFML applications using Groovy, Spring, Hibernate, and Railo.

To get up and running with Hiberailooving, we're going to start with a basic task: creating an entity and unit testing it. For a lack of better examples (I've burned through Contacts and Widgets all too often), we're going to work with Bicycles. My task for this part of the Hiberailoovy series is to create a Bicycle model and unit test it from within Eclipse.

First, I'm going to need to add some Eclipse plug-ins. We're just going to add what we need now - we'll add more later.

  1. The Web Tools Platform (WTP) - Extends Eclipse to provide editing for Java EE Web applications.
  2. Groovy Eclipse Plugin - Code editor for Groovy. Go ahead and get the TestNG plug-in now, too.

Next, we'll need the TestNG library to do unit tests. While Groovy has JUnit support, it doesn't "just work" with Eclipse. TestNG does.

  1. TestNG - Download the latest version (not the Eclipse plug-in) and unzip it.

Allrighty. After some downloading and installing, we're ready to go. As I'm going to be building out a Web application, I need to create a suitable project.

Creating a Dynamic Web Project

We'll use a WTP wizard to create our Web project. From the Java EE perspective, that's File -> New -> Project -> Other -> Web -> Dynamic Web Project. I'll name it "BikeShop". I'm going to leave "Target Runtime" blank - we'll address that later. Click "Finish," and we're good to go.

Adding TestNG

To annotate our tests, we'll need the TestNG .jar. From the TestNG .zip you downloaded, drop testng-5.8-jdk15.jar file into your project's /lib directory. Right click your project and add it to your build path, adding this .jar under "Libraries"

Adding Groovy Support...

...couldn't be simpler. Right-click the project and choose "Add Groovy Nature." I like the sound of that. "Groovy Libraries" should now show up as an entry under the src folder ("Java Resources: src").

Creating our Groovy class and its test.

I'm going to create a class called Bike, giving two properties: id and sold. I'll then add a method called sell() that updates sold to "false." Because I'm a TDD kind of guy, tho, I'll first write the unit test.

First, I'll add a package by right-clicking src and choosing New -> Package. I'll add com.firemoss.bikeshop.test.

Creating the Test

Again, easy as can be. Right click in the package and do "New..." From the Groovy options, selected TestNG test. We'll add a line to import our (to be created) model package, and overwrite the stubbed-in "testSomething" function as follows:

BikeTest.groovy

package com.firemoss.bikeshop.test


import com.firemoss.bikeshop.model.*;

import org.testng.annotations.*
import org.testng.TestNG
import org.testng.TestListenerAdapter
import static org.testng.AssertJUnit.*;

public class BikeTest {

public static void main(String[] args){
def testng = new TestNG()
testng.setTestClasses(BikeTest)
testng.addListener(new TestListenerAdapter())
testng.run()
}


@Test
final void testSellBike(){
def bike = new Bike();

assertFalse(bike.sold);

bike.sell();

assertTrue(bike.sold);
}

}

Creating the Model

Here's where we'll see just how nice and terse Groovy can be. No getters, no setters (except those generated at compile-time for Java-friendliness).

We create another package (com.firemoss.bikeshop.model), and again do "New...," this time selecting that we'd like to create a new Groovy class. We'll name it "Bike".

Here's its code:

Bike.groovy

package com.firemoss.bikeshop.model

class Bike {

int id
boolean sold = false;

void sell()
{
sold = true;
}
}

Running our Test

We can right-click our test case, choose "Run As...", and run it as a TestNG class. You'll see the TestNG view pop up, and you'll hopefully see it pass its test.

Conclusion and "Next Time"

Next time on Hiberailooving, we'll add a Wheel class (because a bike has-many, but no more than two, Wheels). It'll set up a more complex test (including testing a business rule that'll throw an exception), and create the infamous one-to-many relationship that we'll eventually want Hibernate to persist.

3 comments - Posted by Joe Rinehart at 12:30 PM - Categories: Hiberailooving

Jun 24 2008

Project "Hiberailooving," Part 1

Project "Hiberailoovy," Part 1

"Hiberailooving" - Combining Spring, Hibernate, Groovy, and Railo

ColdFusion 9 looks to be building in some measure of Hibernate support. Unfortunately, I'm impatient: I want to play with new toys *now*. I'm also looking to develop a small system based on a redistributable WAR, meaning that I'm open to just about any JEE technology. I'm still a huge fan of using ColdFusion for Service, Control, and View portions of an application, but I've gotten to the point where I'm pretty agnostic when it comes to the Model itself.

I've decided that I'm going to use Hibernate for my persisting my Model, which means CFC's are pretty much out for the language of my domain objects.

While I'm opening the door to moving away from CFCs for my model, I may as well make myself as happy as possible. I'm not a huge fan of writing getters and setters and other repetitive tasks, ColdFusion has made me love dynamic languages, and Actionscript 3 has made me used to being terse. To keep myself happy here, I won't be using Java: instead, I'll be using Groovy.

To sort out using Hibernate and make services and dependencies easily definable but loosely coupled, I'll be using the ubiquitous Spring framework.

Last, I need to be able to distribute what I'll be building as a WAR without requiring users to purchase into a license. That means Adobe ColdFusion 8 can't form the service/control/view tiers, and leaves me with OpenBD or Railo. OpenBD would require me to open source my project, and this is for commercial purposes. Hello, Railo.

Next Steps

To get this all working will require a good-sized change in my development environment and process. I'll need to change what I've got in Eclipse, get used to using Spring to manage my dependencies, move off of JRun, configure and use Hibernate's from within both tests and my Web application, and produce unit tests in both Java (for the Model) and ColdFusion (for the Service tier).

This Blog Series

This series of blog entries is going to chronicle my setup and use of this development and deployment environment. I'll be writing as I learn, so I may make mistakes that get corrected in a later entry. I won't be building my "application" at first. Instead, I'm going to build a small application (not sure what yet) that's large enough in scope to handle some complex cases (relating entities, etc.) but small enough to allow me to focus on the platform instead of features.

Next Up....

In my next entry, I'll document starting to develop the model. I'll get Groovy and JUnit (or TestNG) set up in Eclipse and try to build out a test for a Groovy-based entity.

5 comments - Posted by Joe Rinehart at 9:18 AM - Categories: Hiberailooving