Friday, December 19, 2008

Easy dependency management with m2eclipse

If you've ever used Maven, or are currently using it, you know that most of the time, it can be a pain to add a new dependency.

So you know how it goes. You need a new JAR; you fire up your browser of choice, go to the central repository and hunt for the jar that you need. You finally find it after digging through all the folders, then open up pom.xml and add the group id, artifact id, optional version number, etc., and finally, run maven to get the new jar.
Easy huh? ;)

With the m2eclipse plugin, (available at http://m2eclipse.sonatype.org/update/), you no longer have to go through that multi-step process.

If you haven't added the update site before, you'll have to add it manually.
1. Go to Help -> Software Updates -> Find and install
2. Choose the "Search for new features to install" option and click Next
3. Click "New Remote Site..."
4. Enter "m2eclipse" for the name and enter the URL http://m2eclipse.sonatype.org/update/

Now you add dependencies automatically when:
Right clicking on the project and going to Maven -> Add dependency.
and
During coding: code as you normally do, and when Eclipse complains that the class can't be found, you can click on the red "x" and find the dependency by going through the central repository!


In the example below, I added the @RequestMapping annotation to my Spring 2.5 Controller, and since I didn't have the jar in my local repository, Eclipse notified me of the error. (Figure 1)


Clicking on "Search dependency for RequestMapping" then searched the repository, and provided a listing of potential matching jars. Select the one you want and the rest is automatically taken care of! (Figure 2)









Figure 1: Clicking on the red "x" brings up a context menu where you can search the Maven central repository







Figure 2: The class name is automatically entered, and a list of jars that contain that class is shown.

m2eclipse will take care of downloading the required jars and adding them to your classpath. That's it!

Friday, December 12, 2008

SpringOne 2008

I missed The Spring Experience 2007, but was able to return in 2008, and it has been renamed to springOne. During Adrian Colyer's keynote, he posted this hilarious photo:
Yes, that's the Rod Johnson bobblehead doll! I'm so jealous of everyone who was able to attend in 2007. Hopefully they give out something like this in 2009.

On a more serious note, some of the highlights of the conference:

Managing the war on complexity: This was the theme of Rod Johnson's keynote, and I'm glad he explicitly said this, as Spring is truly one of the best solutions to making Java EE web apps simple to maintain and develop.

OSGi: Becoming very popular, and something worth looking into.

Spring MVC: The old Controller hierarchy is going away, and moving towards the annotation based Controllers found in 2.5. Also, Spring 3.0 will have native REST support!

Grails: If you follow the Grails scene, then you know that G2One, the company behind Grails, has been acquired by SpringOne. Rod just reiterated this to let the community know that Grails will have even better Spring support now that they are the same company.

Thursday, July 10, 2008

Grails Eclipse plugin

So I was messing around with Grails the other day, and heard about the wonderful Eclipse plugin. Like the documentation says, grails generates all the necessary files for Eclipse to recognize your project.

This is great and all, but a lot of people I spoke to encountered the same problem I did.
There's a file for your Spring DSL code, called resources.groovy located in
<your-app>/grails-app/conf/spring.

Many people will then receive the following error:

Invalid Package declaration in script: <path-to-your-project>/grails-app/conf/spring/resources.groovy is not in a source folder matching the package declaration: DonutStore/grails-app/conf/spring resources.groovy


I don't know enough Grails at the moment, but a quick fix is to add:

package spring;

to the top of the file.

Update:I've been coding Grails apps for several months now, and realize that this is just an error with the Eclipse plugin. Since I develop on the Mac, I prefer TextMate anyway. However, if you're an Eclipse fan, be glad that the SpringSource guys are working on a new and improved plugin and it should be available later this year.

Tuesday, July 08, 2008

Spring method injection

I recently inherited some legacy code and it's been extremely difficult to refactor. It's a catch-22: you can't refactor without unit tests in place, but it's difficult to unit test since it wasn't written to be testable. [TDD can cure this. :)]

So after much hair-pulling and thought, I was able to extract a few interfaces and configure some of the business logic classes as Spring managed beans. The problem was that some of the dependencies were still being acquired via the "new" keyword, and it had to remain that way.

In other words, I had a singleton bean which required a non-singleton, or prototype. Not just once, at bean creation time, but a new instance every time. How could this be done, without mucking up my code with the Spring API? We definitely do not want a reference to a BeanFactory or ApplicationContext in our bean.

Enter one of the rarer forms of dependency injection: Method Injection (see section 3.3.8).

The recipe is:
  1. Create a method for the dependency and either make it protected abstract, or public.
  2. In your applicationContext.xml, instead of specifying <property name="someProperty">, you use
    <lookup-method name="theMethodWhichReturnsYourPrototype" bean="idOfPrototypeBean"/>


Let's look at an example:

We have a class Homer, which wants a new instance of another bean, a Donut, every time, instead of reusing the same Donut over and over again.


Now, for the applicationContext.xml:

<!-- a stateful bean deployed as a prototype (non-singleton) -->
<bean id="donut" class="demo.DonutImpl" scope="prototype">
<!-- inject dependencies here as required -->
</bean>

<!-- homer (singleton) uses donut (prototype) -->
<bean id="homer" class="demo.Homer">
<lookup-method name="getDonut" bean="donut"/>
</bean>



So what's going on here? To quote the Spring docs:
The Spring Framework implements this method injection by dynamically generating a subclass overriding the method, using bytecode generation via the CGLIB library.


So when Homer asks for a donut via getDonut(), the subclassed Homer, generated via CGLIB, will return a new instance of Donut, which has its dependencies injected by Spring.

Pros of this approach: we are decoupled from BeanFactory and the Spring API
Cons: making the bean abstract makes testing a little difficult, since you have to subclass the class, however, making it concrete and implementing the getter method, you avoid this.

Thursday, February 28, 2008

Multiline /newline Button label in Flex 3

I was having the hardest time getting a newline to appear in my Button component. I followed the documentation in the Adobe Flex 3 docs to use &13; but that still did not work.

I got some e-mails from Matt Horn of Adobe Flex Docs, and he gave me several things to try, including using the standard "\n" character escape sequence, and the HTML "<br/>". Finally, he gave me a link to a blog entry by Alex Harui titled "Multiline Buttons".

The code needed a little tweaking for Flex 3, but all I did was extend the Button class, and use the same exact code Alex used in his MultilineRadioButton.

That being said, here's my MultilineButton.
You can use this component like a regular button; the difference now is that if you include "&13;" in your label, it will render a newline!

Enjoy.


package
{
import flash.display.DisplayObject;
import flash.text.TextLineMetrics;

import mx.controls.Button;
import mx.core.IFlexDisplayObject;
import mx.core.mx_internal;
use namespace mx_internal;


public class MultilineButton extends Button
{
public function MultilineButton()
{
//TODO: implement function
super();
}

override protected function createChildren():void
{
if (!textField)
{
textField = new NoTruncationUITextField();
textField.styleName = this;
addChild(DisplayObject(textField)); //cast required for Flex 3; if in Flex 2; remove
}

super.createChildren();

textField.multiline = true;
textField.wordWrap = true;
}

override protected function measure():void
{
if (!isNaN(explicitWidth))
{
var tempIcon:IFlexDisplayObject = getCurrentIcon();
var w:Number = explicitWidth;
if (tempIcon)
w -= tempIcon.width + getStyle("horizontalGap") + getStyle("paddingLeft") + getStyle("paddingRight");
textField.width = w;
}
super.measure();

}

override public function measureText(s:String):TextLineMetrics
{
textField.text = s;
var lineMetrics:TextLineMetrics = textField.getLineMetrics(0);
lineMetrics.width = textField.textWidth + 4;
lineMetrics.height = textField.textHeight + 4;
return lineMetrics;
}
}
}

Tuesday, February 26, 2008

Flex Day 2 (or 3, if you count Sunday)




The nightly parties at 360|Flex have been awesome, as well as the sessions.
Here's a review of some sessions I attended.

QTIndexSwapper and more Flash H.264 Fun - Renaun Erickson
  • Renaun showed his custom code which reindexes QuickTime movies so that the movie plays while downloading, AND the metadata is available sooner, rather than waiting for the entire movie to download
  • Check out his blog and link to his Google code: http://www.renaun.com/blog/

Future of Flex - Deepa Subramaniam
  • Flex for Mobile
  • Thermo - RIA Design tool; easy for designers and developers to create revolutionary and interactive interfaces that can be taken directly into production
    • Feels like an Adobe Creative Suite product
  • MXML-G, a new graphics library
  • Flex 4 components - has a new MVC model, where the skin (defined via CSS) is considered the view
    • Deepa showed a demo where a button changed its look dynamically

Sunday, February 24, 2008

360 Flex Atlanta

I'm here in Atlanta for the 360 Flex Conference. It's a little cold here in ATL, but I'm in the comfort of the Omni Hotel, taking the Flex 101 course. We're building a photo application. I'll post more later!