May 22, 2009

Building a c++ dynamic library on 64-bit Intel OSX

It seems like every JNI example for OSX depends on XCode. So here is a simple example of how to build a dynamic library, for OSX, from the command line:

g++ -m64 -c -I/System/Library/Frameworks/JavaVM.framework/Headers Foo.cpp
g++ -m64 -dynamiclib -o libfoojni.jnilib Foo.o -framework JavaVM

Without the -m64 argument you will receive the unintuitive error:

Exception in thread "main" java.lang.UnsatisfiedLinkError: /development/sandbox/libfoojni.jnilib:
at java.lang.ClassLoader$NativeLibrary.load(Native Method)
at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1822)
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1739)
at java.lang.Runtime.loadLibrary0(Runtime.java:823)
at java.lang.System.loadLibrary(System.java:1030)
at Foo.(Foo.java:7)

January 21, 2008

Waffle 1.0 released

I am very happy to announce that after many months of hard work the Waffle team has released version 1.0 of Waffle.

Some of Waffle's features include:

  • Zero XML configuration

  • Minimal annotations

  • Convention over configuration

  • Easy to develop and test with (simple POJOs)

  • Built in support for Dependency Injection

  • Easily extensible architecture


If you haven't tried Waffle I urge you to take a look and see what you've been missing. As always any comments or suggestion are appreciated.

Waffle: Java based web development doesn't have to suck.

January 08, 2008

Maven release:prepare not prompting for version

I ran into a particular annoying bug the other day when trying to use the Maven release plugin. The goal release:prepare is suppose to prompt you for the version you wish to give the release (the version in the poms from x-SNAPSHOT to a new version). However, on my machine I was never prompted by the plugin.

After spending more time than I care to admit trying to resolve this issue I was finally able to trace it to my ~/.m2/settings.xml file. My settings.xml file included a few empty nodes, after removing these my issue went away.

December 28, 2007

Java SE 6 developer preview released for OSX Leopard

It looks like Apple has quietly released Java SE 6 for Leopard through their Apple Developer Connection. The release is only for Leopard (10.5.1) and requires 64-bit Intel Macs (sorry PowerPC and 32-bit Intel based machines).

September 17, 2007

Waffle and JRuby: Accessing parameters and attributes from request, session and servlet context

In the last post I quickly explained how easy it is to access a component registered with Waffle from your JRuby based controllers. Now we need to understand how to access GET and POST parameters in order service a visitor's request. This is easily done through the parameters variable (also aliased as params) on your Ruby based Controllers. This variable is a simple Hash, so looking up parameter values from your Actions as easy as:
def example_one
foo = params['foo'] # request parameter
return "<h1>FOO: #{foo}</h1>"
end

Accessing Request, Session and ServletContext attributes

It might also be useful to access attribute values from either javax.servlet.ServletRequest, javax.servlet.http.HttpSession or javax.servlet.ServletContext. This is, as you should expect, very easy to do. But Waffle automatically wraps each of these as a Ruby Hash. This provides the correct Ruby "feel" when writing your Actions. The following code snippet give an example of how you can access attribute values from each of the 3 contexts:
def example_two
foo = params['foo'] # request parameter
fuu = request['fuu'] # request attribute
bar = session['bar'] # session attribute
baz = application['baz'] # servlet context attribute
return "<h1>FOO: #{foo} FUU: #{fuu} BAR: #{bar} BAZ: #{baz}</h1>"
end
Additionally, you can also call any of the Java methods these instances provide (you are NOT limited to methods exposed by Hash).

Auto-resolve values

Now those of you familiar with Waffle realize that Waffle provides a built-in means to auto-resolve a variables value. Waffle will search each of the following (in order) until the value is found, otherwise null (or in the case of JRuby nil) will be returned:
  1. HttpServletRequest Parameter (HttpServletRequest.getParameter("foo"))
  2. HttpServletRequest Attribute (HttpServletRequest.getAttribute("foo"))
  3. HttpSession Attribute (HttpSession.getAttribute("foo"))
  4. ServletContext Attribute (ServletContext.getAttribute("foo"))
  5. return nil

So with that in mind we can simplify the previous example down to one line. Waffle will attempt to resolve the value of any unknown variable through this means. The following shows the previous method simplified because it relies on Waffle auto resolving each value:
def example_three
return "<h1>FOO: #{foo} FUU: #{fuu} BAR: #{bar} BAZ: #{baz}</h1>"
end
In my next blog post I'll begin discussing how you can integrate JSPs or even RHTML with your applications.

September 14, 2007

Waffle: How to access your Java components from your Ruby Actions.

In my last post I gave an overview of how you can easily integrate JRuby with Waffle. Now we will examine Ruby based controller in a bit more depth. Lets assume we have the following Waffle Registrar for our application:
public class MyRegistrar extends AbstractRubyAwareRegistrar {

public MyRegistrar(Registrar delegate) {
super(delegate);
}

@Override
public void application() {
register("the_dao", PersonDAOImpl.class);

registerRubyScript("person", "PersonController");
}
}

A DAO, PersonDAOImpl, is registered under the name "the_dao" and we have one Ruby based controller available. Now its probably safe to assume that this Ruby PersonController will need access to the DAO. Gaining access to this DAO from the controller is easy in Waffle, just call the locate method:
class PersonController

def index
@person_dao = locate(example.PersonDAO)

@people = @person_dao.findAll
render 'person.rhtml'
end

end

Notice that we were able to retrieve the DAO by its interface. Additionally, since this DAO was registered with a key you can use a convention to retrieve the component. The convention is "locate_<component key>", here is the same controller using the locate_ convention:
class PersonController

def index
@person_dao = locate_the_dao

@people = @person_dao.findAll
render 'person.rhtml'
end

end

As you can see this makes writing Ruby based Controllers/Actions with Waffle really easy. In my next post I'll detail how to access request parameter and context attributes with ease.

September 12, 2007

Ever wish you could utilize Ruby from your Java based web applications?

Waffle, a Java based Web Framework, now provides built in support for JRuby. This will allow you to easily write your Controllers in Ruby. The integration is simple and straightforward, taking advantage of functionality Waffle provides (without being a Rails clone).

A key feature of Waffle has always been its pluggable architecture. From the beginning we believed that the default behavior defined by the Waffle team might not be suitable for every situation. Therefor Waffle was built following an Interface driven approach. Practically all of Waffle's built-in functionality can easily be extended or replaced. This design made integrating JRuby support quite easy. The next 3 steps give a brief overview of how to integrate JRuby support into your Waffle based applications.

Step 1 - configure Waffle to be "Ruby Aware"

Waffle avoids XML like the plague but we still need to have a web.xml for our applications. This web.xml is where we can take advantage of Waffle's pluggability. The following three context-param nodes need to be added to your applications web.xml. This alerts Waffle that a few of its foundational components should be replaced with alternate implementations.
<context-param>
<param-name>org.codehaus.waffle.context.ContextContainerFactory</param-name>
<param-value>org.codehaus.waffle.context.pico.RubyAwarePicoContextContainerFactory</param-value>
</context-param>
<context-param>
<param-name>org.codehaus.waffle.bind.DataBinder</param-name>
<param-value>org.codehaus.waffle.bind.RubyDataBinder</param-value>
</context-param>
<context-param>
<param-name>org.codehaus.waffle.controller.ControllerDefinitionFactory</param-name>
<param-value>org.codehaus.waffle.controller.RubyControllerDefinitionFactory</param-value>
</context-param>

Step 2 - Your application's Registrar should extended AbstractRubyAwareRegistrar. This exposes a new registration method to use within your Registrar ... registerRubyScript(String key, String className). See the example below:
public class MyRegistrar extends AbstractRubyAwareRegistrar {

public MyRegistrar(Registrar delegate) {
super(delegate);
}

@Override
public void application() {
registerRubyScript("foobar", "FooBar");
}
...
}

In this example the Ruby class named 'FooBar' will be exposed as a Controller under the name 'foobar' (e.g. http://localhost:8080/jruby/foobar.waffle).

Step 3
- Write your Ruby Controller class. Notice in the following example that your class does not need to extend or include anything.
class FooBar

def index # This is the default action
"<h1>Hello World</h1>"
end

end

And that is all the steps required to integrate JRuby within your Waffle Applications. In my next post I will uncover details on how to access registered components from your Ruby based controllers as well as explain the built in conventions that make writing Ruby controllers so easy.