Friday, February 5, 2010

Integrating GraniteDS and BlazeDS with a Spring WebMVC Application

Both GraniteDS and BlazeDS provide support for remote calls and messaging using Adobe's AMF protocol. However, when it comes to integrating them with a Spring application that already uses Spring's DispatchServlet, the projects start to show some differences.

In a previous post, I outlined the steps to getting GraniteDS 2.0 setup with Spring. However, this approach results in two separate Spring contexts, so my Spring Service with the 'singleton' scope was being loaded twice. Not good.

I found that GraniteDS 2.1 did support better Spring integration. You can see a blog post here that describes the process, or their updated documentation.  Note that the blog post seems to be somewhat out of date.  One issue is the schema URL: 
http://www.graniteds.org/config/granite-config-2.1.xsd in the blog instead of http://www.graniteds.org/public/dtd/2.1.0/granite-config-2.1.xsd.

The BlazeDS approach has a good overview here, and the documentation is pretty good too.  In my case, I used the @RemotingDestination annotation on my service beans instead of adding:
<flex:remoting-destination />
to the Spring config as I'm using auto-wiring for most of my beans.

There are a couple of things that bothered me about the GraniteDS approach as opposed to the BlazeDS approach.

First, the BlazeDS approach retains a (simplified) services-config.xml file, so the traditional configuration options are still available, and the integration with Flex/Flash Builder works as well.  Not a big deal, but it stays closer to the existing conventions.

Secondly, I was able to get BlazeDS working much faster. The project simply seems to be more mature, and the documentation and examples are clearer. The Granite documentation notes that they are working to achieve parity with the BlazeDS Spring integration, so it is likely that they will be able to close this gap. But for now, it seems to be a work in progress.  It is only available in the 2.1 version, which is currently at RC2.  I also had to use the 2.x version of spring-security-core instead of the 3.0 version, as Spring seems to have refactored the location of the BadCredentialsException class.

All that said, GraniteDS does provide more features than BlazeDS, so the comparison may not be entirely fair. I found the Granite ActionScript code generator (gas3) to work well, although it seemed to miss some import statements before it would compile in Flex 4.  However, the community around BlazeDS seems larger at this point, with the expected increase in polish.  However, competition is good, so hopefully the future versions of GraniteDS continue to improve.

Either way, it is good to see both of these projects working to provide easy integration with an existing SpringWebMVC project. Adding new Flex functionality to existing Flex applications should be very painless.

Posted at - 0 Comments - Links to this post

Wednesday, February 3, 2010

Migrating from Google Blogger FTP to a Custom Domain

Up until today, my blog was hosted at http://www.ericdaugherty.com/blog using Blogger's FTP publishing service. This service uploaded html files to my GoDaddy hosting account whenever a new post was created. While it worked reasonably well, and I liked the control it provided (since I had a backup copy of my entire blog on my hosting site), it did have a few issues. While I was not excited about moving my blog, I understood Google's reasoning.

Google provides a 'Custom Domain' publishing option, allowing Google to host the blog using a DNS name that you own. In my case, I chose http://blog.ericdaugherty.com as my new custom domain name. I could not keep my current address because Custom Domain publishing does not support publishing to subdirectories.

My first step was to create the blog.ericdaugherty.com CNAME and point it to Google's hosting DNS name, ghs.google.com. I use GoDaddy as my registrar and DNS Server and the changes took effect almost immediately. To test, I opened the new address in the browser, and was greeted with a Google hosted page that stated 'Not Found'. Good so far.



Step two was to update my blogger configuration to use Custom Domain publishing with the blog.ericdaugherty.com CNAME. I also used the 'missing files' host option to host all of the pictures I'd uploaded previously. I used my existing host at www.ericdaugherty.com to host the missing files. I hit save and reloaded the site. It immediately loaded, but was missing all of the formatting and images. My template assumed it was being loaded from www.ericdaugherty.com, so the links to my images and style sheets were broken.

I also used some PHP includes to generate the common navigation blocks on my site, so I had to copy that code into my template as they were no longer hosted within the same server. After I made the appropriate changes to the template, the blog displayed correctly. However, the Blogger NavBar now appeared at the top of the blog. I followed the instructions I found at here, which boil down to adding this to my css file:
#navbar-iframe {
display: none !important;
}
I also noticed that my favicon was no longer showing. I added the following to my Blogger template to direct requests back to my main site:
<link href='http://www.ericdaugherty.com/favicon.ico' rel='shortcut icon'/>
<link href='http://www.ericdaugherty.com/favicon.ico' rel='icon'/<
I use FeedBurner to track my RSS subscribers, so I updated my FeedBurner settings to point to the new URL. If I had not used FeedBurner, I would have needed to add a redirect to my .htaccess file (see below).

Finally, I needed to add redirects from the existing site to the new location. I already had an .htaccess file for my existing site, so I edited the file to include new redirects. I already had my RewriteEngine turned on with:
RewriteEngine on
So I just needed to add the new rewrite rules using a 301 (permanent) redirect to notify any requesting agents (including search engines) that the content has been permanently moved. I also included a redirect for my old rss.xml file to the FeedBurner URL, to make sure anyone who had directly subscribed to the feed was instead using the FeedBurner version. Finally, I excluded the uploaded_images directory, as the hosted blogger site will still reference those images for the old blog posts.
RewriteCond %{REQUEST_URI} /blog/rss.xml [nc]
RewriteRule ^(.*) http://feeds.feedburner.com/EricDaugherty [r=301,nc]

RewriteCond %{REQUEST_URI} !^/blog/uploaded_images/.*$
RewriteRule ^blog/(.*) http://blog.ericdaugherty.com/$1 [r=301,NC]
That's it. It took a bit of effort but wasn't too bad. If you are reading this post you, then the new settings are working. Let me know if you see any errors!

Posted at - 0 Comments - Links to this post

Monday, February 1, 2010

Excluding Content from url-pattern in Java web.xml

A while ago I blogged about my frustration with my inability to exclude certain URLs from a url-pattern mapping. In short, I wanted to map everything except /static/* to a dispatch servlet.

There is a way to do this, in some servlet servers. Many (most, all?) servlet containers define a default servlet to handle static content. Be default, any unmapped URLs will be handled by the default servlet. However, you can explicitly map certain URLs to this default servlet, achieving a de-facto url-exclude pattern.

Here is an example:
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>/static/*</url-pattern>
</servlet-mapping>

<servlet-mapping>
<servlet-name>SpringMVCServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
Where in this case, you have SpringMVCServlet defined in your web.xml, but not default. The default servlet definition is inherited from the servlet container.

The order shouldn't matter, as long as your mapping for the default servlet is more specific.

This is known to work in at least Jetty and Tomcat.

Posted at - 0 Comments - Links to this post

Friday, January 29, 2010

What is the iPad?

Inventing a new device category is hard. If it wasn't, the category would probably already exist. So there should be no surprise that Apple's iPad announcement has yielded wildly different responses. Here is my take.

First, as the happy owner of a Kindle 2, buying a $499 media pad is something I can contemplate. The Kindle DX at $489 with the same sized screen becomes a very tough sell versus the entry level $499 iPad. I love my 6" Kindle, and while it is in a different league at $259, I would have to stop and think about whether I'd buy it again today. Now, about that iPad...

The iPad is not a mobile device in the same sense as your phone. You will not carry the device around in your pocket. It is not a big phone. Instead, it is something new. I see three usage scenarios for it.

1. It is a device you use at home to access media, and play games. Videos, Pictures, Books, and the web. It is a couch device, a bed device, a kitchen table device. When you get home from work, you can leave your laptop in your bag, and just use the iPad.

2. It is a laptop replacement on trips. Headed on a short business trip, or on vacation? Don't want to take your laptop, but don't want to be stuck reading your iPhone for a few days? The iPad is a great alternative. You can take a keyboard with and catch up on emails from your hotel, but have a small device to carry in your bag during the day to spend 15-30 minutes checking in throughout the day.

3. Business/Education - Developing specialized applications and using the iPad as a computing platform. Whether it is kids in schools reading their textbooks and doing homework or sales associates at the local retail outlet showing you color alternatives, there are tons of special purpose applications that can leverage a device in this category. And the rate of development of iPhone applications to date certainly makes this seem reasonable.

Personally, I think the non-3G versions are great alternatives, as I don't envision myself using a device like this out of Wi-Fi range. So the base model is actually very appealing, and at $499 is still somewhat reasonable. That said, I'm not going to run out and buy one on day one. But I can see the second version as a great replacement for my Kindle.

Posted at - 0 Comments - Links to this post

No Flash on the iPad is the Right Choice for Apple

Apple finally announced the Jesus Tablet iPad, launching what they believe to be a new device category. It remains to be seen whether they are correct (although I have my guesses), but the launch of the iPad has rekindled an existing fight between Apple and Adobe.

Apple refused to implement (or allow others to implement) Flash on the iPhone. John Gruber has written about this topic extensively over the past two years. He correctly (though not surprisingly) predicted that the iPad would not support Flash. I say not surprisingly, because all the reasons they had for not supporting Flash on the iPhone still exist for the iPad. OK, one reason: CONTROL. I won't rehash John's arguments, but the summary is, Apple wants to control the experience (and commerce) on the iPhone (iTouch, iPad, etc.), and Flash bypasses that control.

As a newer Apple 'fanboy' (I apprecited Gruber's take: 'There’s a whole class of recent switchers who define “Apple fanboy” as “anyone who’s been an enthusiastic Mac user since before I switched to the Mac”.'), I long avoided Apple because of their demand for control. But after dipping my toe in with iTunes and an Airport Express, I finally gave in and switched to a MacBook Pro and iPhone 3GS (and love them).

I've seen two very different points of view in the past 24 hours regarding Flash on the iPad. When my wife and I were talking about the iPad, I suggested that it could be an alternative to her 13" MacBook, as it does nearly everything she needs. She quickly pointed out that without Flash, it was unappealing to her. (The keyboard is also an issue, but that's a topic for another post).

The second point of view was a post on the Adobe blog by Adrian Ludwig. He pointed out the iPad's lack of Flash, some of the sites that will be unavailable to the iPad users, and that "50 of our partners in the Open Screen Project are working to enable developers and content publishers to deliver to any device". I thought it was a pretty good post from Adobe, pointing out their frustration in a reasonably neutral tone (given their obvious interests). I was a bit surprised by the comments. I didn't do a full tally, but I'd say 90% of the comments were anti-Flash. They complained about the state of Flash on the Mac, and already run Flash blockers on their desktop.

So I see two camps, the general users, who just want the websites to work, and the super users (blog readers) who have a negative perception of Flash and just want it to die. As someone who has built Flash applications, and enjoyed the process and results, I have a biased viewpoint. However, I also have the debug version of the Flash Player installed, so I see first hand how many uncaught exceptions there are in nearly every Flash application I see. There are tons of poorly written Flash applications deployed on the web.

In the end, Apple made the right choice for Apple. I have yet to see a major group of users who are likely iPad buyers in the next 12 months that are upset by the exclusion of Flash. The broader population who may eventually adopt the devices are simply not likely buyers in the short term anyway.

Apple is in a race against Flash. They are gaining huge marketshare in the mobile space, and pushing HTML 5 and the iPhone SDK as the chosen mobile development platforms. As the marketshare continues to grow, the 'Flash Only' sites will be forced to provide mobile or iPhone optimized versions to gain access to growing mobile user base.

We've seen this before. There was a point when web developers optimized their sites for IE 6 exclusively. Now there are websites that actively reject IE6 users, and focus their primary support on Firefox, Safari, and Chrome. This shift occurred because the users demanded it. They were fed up with IE and switched to alternative browsers, and the websites had to adjust or lose the traffic. Apple is attempting to do the same thing with Flash. If they can successfully build a mobile audience without Flash support, websites must respond.

I think HTML 5 and rich applications via plugins (Java FX, Silverlight, Flex) both have their place. Consumer facing high traffic sites should be HTML. The accessibility and SEO trade-offs are simply to great to justify using a plug-in RIA. For applications, whether they are corporate applications, games, or utilities, Flex, Java FX and Silverlight are great alternatives. They provide the benefits of the web deployment model with the power and speed of development of traditional languages.

Looking forward, high level rich languages (Java FX, Silverlight, and Flex) will merge with the increasing functionality of the underlying platform (JavaScript and HTML 5) to create high level languages that 'compile to the browser'. Google's GWT is a first generation example of this, but I believe there is much more to come. Eventually the debate over plug-in architectures will become moot.

The only question is, will it happen fast enough for Apple to avoid a user backlash?

Update: Gruber and Scoble appear to be making the same analogy to the changes Firefox forced on web developers.

Posted at - 6 Comments - Links to this post

Monday, January 25, 2010

The Complete Software Developer

The Software Development profession is still a relatively immature profession. There are few real certifications and no real licensing processes that provide any realistic guide to an individual's competency. The landscape evolves quickly and covers a very broad spectrum of skills. These reasons make it difficult to map out a career path that will lead to the development of a complete Software Developer. In this article, I intend to lay out what I feel is a solid career outline for a Software Developer, and why each step is important.

It is important to note that this is not the path to be a competent developer, but to be an outstanding developer. The tools and resources available today make it possible for someone to achieve reasonable levels of successes with minimal levels of skill and education. Instead, this is a roadmap to become what I consider to be a complete developer. This includes more than just pure technical skills, but someone who can work with others to solve problems.

Education

A favorite movie quote of mine is from 'Die Hard':
"'And when Alexander saw the breadth of his domain, he wept, for there were no more worlds to conquer.' Benefits of a classical education." - Hans Gruber
While a Computer Science or Computer Engineering degree is not required to develop software, it can provide an understanding of the foundational elements on which everything else is built. Understanding both how a computer actually works, and the fundamentals of algorithms, data structures, and operating system design will provide a solid theoretical foundation for an entire career. I also believe it is important that the degree focuses on theory more than practice. A Computer Science degree that spends time teaching how to use Visual Studio or Eclipse may produce students who can be more effective in year 1, but does them a disservice in years 2-n.

The only other degree I've seen with some regularity provide individuals with a solid understanding is Physics. Even so, they have had to learn the fundamentals along the way. I guess with the Physics background, they probably understand everything at a much deeper level anyway.

Consulting

I believe that every new college graduate's first job should be with a consulting company. Not just any consulting company, but one large enough and experienced enough that it provides real training on how to be a Consultant, in addition to how to develop software. Consulting is a skill, and it is one that will pay dividends through an entire career.

Working at a consulting company will expose new Software Developers to a variety of technologies, business domains, and cultures. Ideally, the consulting company works in a variety of technologies and new consultants get an opportunity to work on projects across multiple languages/technologies/platforms.

Travel is not a requirement, but can provide some added benefits. From the simple worldly benefits of seeing different parts of the country, to business dinners with clients, where new developers can gain a real insight into how business gets done. You may also get to eat some great meals along the way as well.

Consulting also helps new developers learn to market themselves. Since consulting companies really sell the competency of their staff, and their 'unique process', developers will learn how to position their skills and experiences to demonstrate competence and credibility. After consulting for a while, every future job interviews will be much less stressful.

Ideally, spend 2-3 years broken up into six month projects across at least two different platforms (Java, .Net, etc.), and with at least one project in a different city.

This experience will do several things. First, it will teach new developers how to be a consultant. This includes everything from dressing professionally, to presenting ideas and concepts to non-technical customers, to understanding the business of selling services. Second, it provides a broad experience base while new developers are still young and impressionable. There are many different technologies and platforms out there, all taking different paths to solve problems. Seeing this diversity early insures that new developers do not become assimilated into the group think of a single platform or pattern. It is hard to work in different platforms like .Net and Ruby on Rails without developing a knowledge about how the underlying technologies work. Finally, new developers will also see the rich diversity of business and cultures across companies. It is an opportunity to learn the trade-offs of different business models and cultures, and how they impact the ability for software development teams to be effective.

Support

After spending some time in Consulting, it is time to move into a role where you can own and support a product. This can either be within an internal IT department, or for a Software as a Service company. A packaged software vendor provides many of these benefits but I believe that a critical part of this experience is 'carrying the pager', which packaged software usually avoids.

The key learning here is to own and support a system across several major releases. Building version 1.0 of an application as a consultant is very different from enhancing and maintaining an application across several minor and major releases. Being responsible (indirectly, if not directly) for the support and success of a production application is a critical learning experience.

Ownership is an important concept. This experience provides the ability for a new developer to really work on something over a long period and 'own' it. A developer can see the payoff of a bit of foresight or extra effort they put in 12 months ago. They can also feel the pain of taking shortcuts that were ill-advised. They can learn how those trade-offs work and begin to get a sense of when they are worthwhile.

In the end, working in IT or Engineering provides a different set of goals and drivers for Software Developers than Consulting can provide. These different goals force new developers to see software development through a different lens.

Performance and Scaling

The opportunities within most consulting and traditional IT/Engineering roles to really focus on high performance code and application scaling are limited. Within consulting, it is often a non-factor, as performance and scaling issues often do not appear until long after the initial deployment. Within IT/Engineering roles, there is often an opportunity to address issues, but only within the context of a single application and infrastructure.

Therefore, the next stop on the career path is Professional Services or other specialized consulting. Professional Service organizations often focus on providing extremely skilled resources for short periods to address critical issues. These can often focus on performance or scaling issues, and provide a great opportunity to gain exposure to a broad set of problems, architectures, technologies, and infrastructures. To be successful in this role, an individual needs both a deep understanding of the product they are supporting but also an understanding of how it fits into the greater ecosystem.

In a Professional Service or specialized consulting role, individuals often interact with very senior members of the customer's staff, allowing developers to gain experience and exposure to a individuals they may not traditionally interact with.

This type of experience provides an opportunity to solve a large number of very intense problems over a relatively short period of time. This provides a breadth of knowledge about how the different types of major systems in production, and the problems that they face. It also allows developers to build an impressive network of contacts across a broad range of companies.

What's Missing?

As a career outline, I believe this is a great start, but it is probably incomplete. There are many other valuable experiences that an aspiring Software Developer should experience. Some of these can be done in parallel with the above outline, others may be additional steps.
Go Forth and Create

Now, focus on your passion. You have the background necessary to learn any new technology, solve any problem, and effectively communicate with others. It is time to focus on what you are passionate about, and become a leader in your chosen field.

Posted at - 5 Comments - Links to this post

Friday, January 22, 2010

Getting Started with GraniteDS, Spring, and Maven

This is a quick tutorial to get you up and running using GraniteDS, Spring, and Maven. My initial assumptions are that you already have a Spring project up and running using Spring WebMVC, and you want to add GraniteDS to the project to enable a Flex client. This just covers using GraniteDS for a basic RPC call using AMF. GraniteDS does much more, but this should at least get you started.

First, you need to add the GraniteDS dependencies to your pom. GraniteDS does not appear to be in the default Maven repository, so first you need to add a references to the Java.net Maven Repository:
<repositories>
<repository>
<id>Java.net</id>
<name>Java.net Repository</name>
<url>http://download.java.net/maven/2/</url>
</repository>
</repositories>

Next, you'll need to add the dependencies:
<dependency>
<groupId>org.graniteds</groupId>
<artifactId>granite-core</artifactId>
<version>2.0.0.GA</version>
</dependency>
<dependency>
<groupId>org.graniteds</groupId>
<artifactId>granite-spring</artifactId>
<version>2.0.0.GA</version>
</dependency>

You may also want to add additional GraniteDS artifacts, such as granite-hibernate, etc. You can see the entire list here.

You will need two additional configuration files, services-config.xml and granite-config.xml. The services-config.xml should be familiar to anyone who has used BlazeDS before.

WEB-INF/flex/services-config.xml - This file contains the core of the mapping config. The first block specifies the destination, including the beanName of the backing Spring Bean. You will need to replace [beanName] with the name of the Spring Bean you are exposing. You can tweak the URL and destination names, but otherwise this should be good for your simple RPC call as is.
<?xml version="1.0" encoding="UTF-8"?>

<services-config>

<services>
<service
id="granite-service"
class="flex.messaging.services.RemotingService"
messageTypes="flex.messaging.messages.RemotingMessage">
<destination id="test">
<channels>
<channel ref="my-graniteamf"/>
</channels>
<properties>
<factory>springFactory</factory>
<source>[beanName]</source>
</properties>
</destination>
</service>
</services>

<factories>
<factory id="springFactory"
class="org.granite.spring.SpringServiceFactory"/>
</factories>

<channels>
<channel-definition id="my-graniteamf" class="mx.messaging.channels.AMFChannel">
<endpoint
uri="http://{server.name}:{server.port}/{context.root}/graniteamf/amf"
class="flex.messaging.endpoints.AMFEndpoint"/>
</channel-definition>
</channels>

</services-config>

Note: If you are using AutoWiring in Spring, the beanName will just be the unqualified class name. So the class com.ericdaugherty.TestService would have a beanName: testService.

WEB-INF/granite/granite-config.xml - In this simple example, there is no configuration of real value in this file yet. As you delve deeper into GraniteDS's features, you can add configuration here.
<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE granite-config PUBLIC
"-//Granite Data Services//DTD granite-config internal//EN"
"http://www.graniteds.org/public/dtd/1.2.0/granite-config.dtd">

<granite-config scan="true">
</granite-config>

You will need to add some additional configuration to your web.xml. In addition to your SpringMVCServlet configuration, you will need the GraniteDS Filter and Servlet:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/config/web-application-config.xml
</param-value>
</context-param>

<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>

<filter>
<filter-name>AMFMessageFilter</filter-name>
<filter-class>
org.granite.messaging.webapp.AMFMessageFilter
</filter-class>
</filter>
<filter-mapping>
<filter-name>AMFMessageFilter</filter-name>
<url-pattern>/graniteamf/*</url-pattern>
</filter-mapping>

<servlet>
<servlet-name>AMFMessageServlet</servlet-name>
<servlet-class>
org.granite.messaging.webapp.AMFMessageServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>AMFMessageServlet</servlet-name>
<url-pattern>/graniteamf/*</url-pattern>
</servlet-mapping>

I had to add the ContextLoadListener and specify the location of my web-application-config.xml file for GraniteDS to work, even though I didn't need it for Spring.

Note: if your SpringMVCServlet is mapped to your root (/), make sure the AMFMessageServlet mapping is first in your XML file.

Now, you simply need to create a Flex project and use RemoteObject to call your service. In Flash Builder 4, I was able to set it up as a BlazeDS project, point it at the src/main/webapp directory in my Maven tree, and it was able to auto-configure RemoteObject.

That's it. This is a very simple version of what you can do with GraniteDS, but it should be enough to get you started.

Posted at - 1 Comments - Links to this post