Some years ago XML configuration was considered as a great way to configure applications. Take for example Struts' struts-config.xml, in the beginning it was like heaven how you could define all your action mappings etc. But as applications grow it gets harder and harder to maintain this bunch of XML.
The point is applications and application frameworks evolve. In modern application frameworks code by convention is becoming an important feature which reduces repetition and increases uniformity and productivity.
Take for example Grails and Ruby on Rails which are build from the ground up with code by convention in mind. For example in Grails a *Controller.groovy class is a automatically a controller and a *Service.groovy class is automatically a service. You do not need any XML configuration.
Back in my holidays in December I tried Adobe's BlazeDS. From Adobe Labs: BlazeDS is the server-based Java remoting and web messaging technology that enables developers to easily connect to back-end distributed data and push data in real-time to Adobe Flex and Adobe AIR applications for more responsive rich Internet application (RIA) experiences.
What this means is that Flex clients can communicate with Java objects deployed on the server. BlazeDS contains a Java Adapter which forms the infrastructure to make this possible. With Jeff Vroom's Spring Integration you can even use Spring beans to communicate with.
The only drawback with the standard Java Adapter (and so also the Spring Integation) is that each Java object you want to call on the server, you need to configure in remoting-config.xml. Guess what? I don't like that! So what I did is I created a JDK5 annotation to autowire Spring beans directly into BlazeDS. It means when you use Spring and JDK5 you can annotate your service classes with a @RemotingDestination annotation, and they get automatically registered in BlazeDS. Some sort of code by convention I would say!
How it works:
- Download the @RemotingDestination annotation for Spring supporting files at http://www.adobe.com/cfusion/exchange/index.cfm?event=extensionDetail&loc=en_us&extid=1398018. It also includes Jeff Vroom's Spring Factory.
- Expand remotingdestination-annotation.zip
- Copy dist\remotingdestination-annotation.jar in the WEB-INF\lib directory of your web application. Instead you could also include the Java sources (located in src) in your project.
- Download the Spring framework at http://www.springframework.org/download
- Locate spring.jar in the dist directory and copy it in the WEB-INF\lib directory of your web application
- In your Flex services-config.xml configure the SpringAutowiringBootstrapService:
The SpringAutowiringBootstrapService checks all @RemotingDestination annotated classes and registers them within BlazeDS at runtime. It also dynamically creates the Spring Factory.
<?xml version="1.0" encoding="UTF-8"?>
<services-config>
<services>
<service-include file-path="remoting-config.xml" />
<service-include file-path="proxy-config.xml" />
<service-include file-path="messaging-config.xml" />
<service id="spring-autowiring-bootstrap-service" class="flex.contrib.services.SpringAutowiringBootstrapService"/>
<default-channels>
<channel ref="my-amf"/>
</default-channels>
</services>
....
Note that the default channel is required when using runtime registration of remoting destinations.
- Finally annotate your service classes with the @RemotingDestination annotation:
package flex.contrib.samples.mortgage;
import org.springframework.beans.factory.annotation.Autowired;
import flex.contrib.stereotypes.RemotingDestination;
@RemotingDestination(destination="mortgageService")
public class Mortgage {
@Autowired
RateFinder rateFinder;
public void setRateFinder(RateFinder rateFinder) {
this.rateFinder = rateFinder;
}
public double calculate(double amount) {
int term = 360; // 30 years
double rate = rateFinder.findRate();
return (amount*(rate/12)) / (1 - 1 /Math.pow((1 + rate/12), term));
}
}
By default the Spring bean name is used to register the remoting destination. The name can be overridden using the destination attribute of the annotation. The example class uses Spring annotation-based configuration using the @Autowired annotation. In this case the Spring application context would look like:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd">
<context:annotation-config/>
<context:component-scan base-package="flex.contrib.samples"/>
</beans>
That's it! The Mortgage service will be automatically registered without any XML configuration. The @RemotingDestination annotation allows you to easily expose services within BlazeDS. Together with Spring's annotation-based configuration this provides a productive code by convention experience for writing Flex applications with Spring on the server-side.
For more info about the @RemotingDestination annotation, SpringAutowiringBootstrapService see the Javadocs in docs\api.