Showing posts with label coldfusion. Show all posts
Showing posts with label coldfusion. Show all posts

Wednesday, August 31, 2011

ColdSpring Setter Injection versus Constructor Arguments Snafu

I was troubleshooting an issue a colleague of mine was having the other day, where to his credit he was following best practices but it shot him in the foot. Wanted to mention it here quickly.

Most times when you are injecting a bean into another bean in ColdSpring you will use setter injections. They look like:

<bean id="bean1" class="com.nictunney.Bean1"/>

<bean id="bean2" class="com.nictunney.Bean2">
  <property name="Bean1">
    <ref bean="Bean1"/>
  </property>
</bean>

Bean2 defines a mutator (setter) method, setBean1(). ColdSpring will inject the Bean1 into Bean2 when Bean2 is created by explicitly calling Bean2.setBean1(bean1). This is a best practice when performing dependency injection to prevent circular dependencies.

So the problem we were encountering in code was that the Bean2 constructor was calling a method that relied on the Bean1 property, which was of course undefined during the instantiation. It took a little while to track this down as this was a Model-Glue subapplication with lots of other stuff that could have been creating the error.

So, the lesson learned is to remember how ColdSpring and DI works. ColdSpring is going to create an instance of a bean, call the bean's constructor and then perform any necessary setter injections. It all makes perfect sense, except when you least expect it ;)

The answer in this case was to determine if a circular dependency would occur, which in our case it wouldn't, and instead inject the dependent bean via a constructor argument like this:

<bean id="bean1" class="com.nictunney.Bean1"/>

<bean id="bean2" class="com.nictunney.Bean2">
  <constructor-arg name="bean1">
    <ref bean="Bean1" />
  </constructor-arg>
</bean>

In the constructor call setBean1(arguments.bean1).

Wednesday, August 24, 2011

Are you ColdFusion Curious?

There is always lots of buzz about Adobe ColdFusion across social networking channels from developers. Most of it is positive, but ColdFusion also takes some abuse from programmers who have not used it. This criticism then gets met with some pushback from well-meaning CF developers, which in turn makes the bulk of us look like rabid loyalists.

Unfortunately for those scouring for information on language pros or cons, many of the negative statements are misinformed, heresy, and some of it is just good-natured ribbing (which I encourage as I do the same). I'd like to challenge all of you who use a web development language like Ruby, PHP, C# and ASP to take a single hour and attend one of the Adobe ColdFusion Developer Week sessions and challenge yourself to check out CF and see just how productive it can be. Don't worry, I won't tell any of your friends you were there ;)

Wednesday, August 10, 2011

Dear ColdFusion Team: Please fix this stuff in Zeus

I love ColdFusion. I've built a 13 year career out of it (so far). I want to see CF continue to be a great language. Here are a few things I see that need to be addressed:

1. Shorthand for creating structures
This is one of those things that I'm not sure how it got put into the language, but lets fix it now before it becomes one of those embedded issues we just have to accept for version after version like 1 based array indices (more on that later). Fix it now!

// current
myStruct = {key="value"};

// suggested
myStruct = {key:"value"};

2. Arrays should be zero-indexed
This is one I've mentioned on for years. The standard across every other language is to use zero based indices. Why CF didn't do this from the get-go is an enigma to me. It is a PITA and requires a different sort of looping criteria as well as a different sort of index allocation during creation (unless you are using arrayAppend()). I would like to suggest making this backwards compatible by offering an application level variable that will permit you to enable the old 1 based indices while you are converting apps or maintaining legacy apps.

3. Looping over Arrays (item versus index)
This is a biggie that was discussed on other blogs recently. When I loop over an array in tags I do this:
<cfloop array="#myArray#" index="item">

This makes no sense. An index is just that, the current array index you are looking at. In CF this actually returns the item specified by the current index. I cannot get the current index without searching my array. The correct way to implement this would be to allow the user to specify either attribute. This would also prevent the user from having to track the index via an incrementer. I have had to do this frequently when trying to match up the current array with another array with related data.

<cfloop aray="#myArray#" index="i" item="item">

In this loop index would refer to the current index, and item would refer to the current item - makes sense right?

4. Looping over queries in CFScript
The way to do this currently is to loop from 1 to qry.recordCount. This isn't terrible, however I'd like to see this updated as such:
for ( row in myQuery ) {
}

The same could be said for an array loop.
for ( item in myArray ) {
}

5. Clean up object functions
Let's catch up with other languages on this one. len(), arrayLen() etc. Instead, I should be able to use a variable.length function regardless of the type (string or array). Also arrayAppend() (myArray.push()), arrayGetAt() (myArray.getAt(), myArray.pop()), listAppend() (myList.addItem()), etc. There are tons of them that should be addressed. You don't need to do anything but deprecate these existing functions for a few versions.

6. Query() object
Well, this one is tricky, as I've been trying to come up with a better way of handling this myself. Going back to the early days of ColdFusion (back when we called it Cold Fusion ;) ) the initial selling point of the language was the ability to interact easily with databases. This was so much the case that IIRC the tag was actually prefaced db and not cf! is a very simple way to access queries, and I continue to use it as opposed to its script counterpart. In fact, this is so much the case that I have to write my DAOs in tag based syntax instead of using script, which would be preferred.

I'm not going to go into all the reasons I dislike the current script based query syntax, but my biggest issue currently is with how query params are assigned. I'd recommend this approach:

var myQuery = new Query({
sql: "SELECT col from table where id = new queryParam({value: arguments.id, cfsqltype: 'CF_SQL_VARCHAR'})",
datasource: application.dsn
});

Having to use a Query object is also a bit frustrating although I think I can just tack execute().getResult() onto the statement above, but I'd have to check. It would be much easier to wrap the query object and have it call a query function, which in turn would function just like cfquery:

var myQuery = query(sql="SELECT col from table where id = new queryParam({value: arguments.id, cfsqltype: 'CF_SQL_VARCHAR'})", datasource: application.dsn);

Those are some initial thoughts for ColdFusion syntax changes. Please feel free to post your own in the comments below.

Wednesday, April 27, 2011

CF Builder Express Edition - Yeah, It's free!

Some big news from Adobe was released today: ColdFusion Builder will now have an express edition. What this means is that after your CFB trial expires, you will be able to continue using Builder save a few features that will be disabled. It is up to you to determine if those features are worth the $300 price tag.

Here are some of the features that will not be available in the free edition:

  • Code Assist for Extensions
  • Code Insight
  • Extension Callbacks
  • Connections to remote CF Servers
  • Quick Fix
  • Remote Project Debugging
  • Refactoring
  • ColdFusion Search
  • Code Formatting
  • FTP Support
  • Log Viewer
  • Local File Browser
  • Code Hyperlinks
  • Hover Help

For me, I use some of those features and the time savings is worth the $109 upgrade price. You'll have to make that decision for yourself, but regardless, CFB Express is still full featured.

Here is a link to all ColdFusion Builder 2 Features for comparison.

Tuesday, October 19, 2010

Using ColdFusion ORM with Flash Remoting in Flex via DTOs and Assemblers

ColdFusion 9 brought us a native implementation of Hibernate. ColdFusion has always been a wicked service tier, and extending CF ORM objects to Flex via remoting makes it even easier to connect CF and Flex.

NOTE: This information was originally explained to me over a bunch of conversations by Brian Kotek. Everything correct in this post can be attributed to Brian, and everything incorrect can be blamed on me ;).

There are a few reasons why utilizing data transfer objects (DTO) are a good idea:
  1. Reduce network overhead by only returning the data you need (BlazeDS - under the hood of remoting - has some issues with remotingfetch and lazy loading)
  2. Massage data to match the needs of the flex application's architecture (ordering arrays of children, concatenating strings, etc)
  3. Smaller footprint for serialization
A DTO is an an object that stores data. It is limited in that it knows how to do nothing else, but store data. DTOs are loaded up by an assembler (read about the dto assembler pattern). An object might have more than one assembler class depending on the method of access (such as remoting) or even the amount of data that needs loaded into an object for the present flex call. For example, one flex call might need a parent object with all related children, whereas another call might just need the parent object itself. In the latter case we could be returning a hundred objects when all we really need is a single string from the parent.

The following diagram shows a simplified workflow for reading data from a CF service tier from a Flex application:


The sample workflow shows a simple remoting call from the Flex application. The CF side receives the request in a singleton remoting proxy and uses CF ORM to load the requested object. The object is passed off to the assembler. The assembler knows how to assemble the DTO for this object. The proxy doesn't know anything about how to load the object or DTO. That functionality is injected into the proxy at runtime. When the DTO is passed back from the assembler it is returned to Flex. On the Flex side the AS3 DTO equivalent is populated and an assembler disassembles the AS3 DTO into the appropriate AS3 class.

The sample code below handles the ColdFusion side of the equation (the Flex side is the the same, but opposite). For our example we are requesting a Parent object with the specified ID via Flash Remoting. The call is received by our remoting proxy. Note that the proxy does not know how to create the Parent object or Parent DTO, but it knows where to get them via dependency injection. Take note that all of this would be even easier using if you allow ColdSpring to handle your objects ;)

RemotingProxy.cfc

1:  <cfcomponent displayname="RemotingProxy" hint="I am the RemotingProxy class.">  
2:      
3:    <!--- remote methods --->  
4:    <cffunction name="getParent" access="remote" returntype="parentDTO" output="false" displayname="getParent" hint="">    
5:      <cfargument name="parentID" type="string" required="true" />  
6:        
7:      <cfscript>  
8:        var parent = application.parentService.get(arguments.parentID);  
9:          
10:        return application.parentAssembler.assemble(parent);  
11:      </cfscript>  
12:        
13:    </cffunction>  
14:      
15:  </cfcomponent>  
The parent assembler's assemble() method takes the Parent object from ORM and maps it to the Parent DTO. The assembler then loads the children objects into the composition. It doesn't know how to assemble the ChildDTOs, but it has an instance of ChildAssembler injected into it at runtime that provides this functionality. Also note that there is a reference to the ProjectService. This is used when dissassembling. This would occur during a write operation triggered from the Flex application.

ParentAssembler.cfc

1:  component accessors="true" {  
2:    property ParentService parentService;  
3:    property ChildAssembler childAssembler;  
4:      
5:    public any function init (ParentService parentService, ChildAssembler childAssembler) {  
6:      setParentService(parentService);  
7:      setChildAssembler(childAssembler);  
8:        
9:      return this;  
10:    }  
11:      
12:    public ParentDTO function assemble (Parent parent) {  
13:      var dto = createObject('component', 'ParentDTO').init();  
14:        
15:      dto.id = parent.getID();  
16:      dto.title = parent.getTitle();  
17:        
18:      // add the children  
19:      aChildren = parent.getChildren();  
20:      for ( var i=1;i<=arrayLen(aChildren);i++ ) {  
21:        arrayAppend(dto.children, getChildAssembler().assemble(aChildren[i]));  
22:      }  
23:        
24:      return dto;  
25:    }  
26:      
27:    public Parent function disassemble (ParentDTO parentDTO) {  
28:        
29:      return ;  
30:    }  
31:  }  
The DTO stores all properties of the Parent class in public variables. You may choose to keep these variables private and provide accessors and mutators for access. The use of cfproperty here is for the purpose of self-documentation.

ParentDTO.cfc

1:  component alias="com.nictunney.dto.ParentDTO" {  
2:    
3:    property string id;  
4:    property string title;  
5:    property array children;  
6:      
7:    public any function init () {  
8:      this.id = '';  
9:      this.title = '';  
10:    
11:      this.children = [];  
12:        
13:      return this;  
14:    }  
15:  }  

The full code is available here. Hope this gets you started utilizing ColdFusion 9 ORM with your Flex applications.

Monday, August 23, 2010

More ORM Weirdness

NOTE: the first part here addresses CF 9.0.0.  9.0.1 does not fix this, but expands the weirdness.  9.0.1 behavior is the second half of this post.

In my last post I learned via @brian428 that the behavior was correct since the collections need to be loaded or else ORM doesn't know if they should be deleted from the collection or not.  EntityMerge() did not work, but loading based on length of the passed ID did (again, thanks Brian).

The new weirdness is when I return the loaded object back via JSON.  There are two child collections: Entities and FocusAreas.  Entities are null and lazy loaded.  FocusAreas contains one record, and is also lazy loaded.  Note the JSON:
{"obj":{"entities":[],"id":"8ab2932d2a8529d6012a856916c40002","focusareas":,"errors":[]}
See that focusareas returns nothing, whereas entities returns an empty array. The error comes on the client since when I eval() in JavaScript it tries to set focusarea to ',"errors":[]}' and then sees no proper closing for the JSON string. Setting lazy="false" on the focusareas relation fixes the issue, but then I have to return the focusareas, which I do not need. What I would expect to see is:
{"obj":{"entities":[],"id":"8ab2932d2a8529d6012a856916c40002","focusareas":[],"errors":[]}
The error would be fixed by setting the value of getFocusAreas() to an empty array upon initialization.

So here is where Brian suggested I install the CF 9.0.1 updater.  At first I was pleased.  When I returned the value after an entitySave(), it did not return entities or focusareas.  w00t!  To be sure, I then loaded the focusareas with getFocusAreas().  They still were not returned!  Setting lazy="false" also had no bearing.  There was nothing I could do to get them to return.  For a sanity check I dumped the parent object right before the return and got this:


I've cleared my cache and restarted CF.  The returned JSON is still:
{"obj":{"id":"8ab2932d2a8529d6012a856916c40002","title":"Test Project"},"errors":[]}

Sunday, July 12, 2009

My Adobe ColdFusion 9 and ColdFusion Builder Article is Live

I had the pleasure of writing an article to be released with the Public Beta of CF9 (Centaur) and CF Builder (Bolt). I decided to write about SOA and how CF9 and ColdFusion Builder change the way you currently develop your service tier. Hope you enjoy it!

Reinventing SOA in Adobe ColdFusion 9 beta and ColdFusion Builder Beta

Other great CF9 and CF Builder articles:

Introducing Adobe ColdFusion 9 Beta (by Ben Forta)
Introducing Adobe ColdFusion Builder Beta (by Ben Forta)
Introducing ORM in Adobe ColdFusion 9 Beta (by Mark Mandel)
Getting started with ColdFusion Builder Beta (by Simon Free)

Thank you Adobe

I've been an Adobe fan for years, first got started with Photoshop back in version 6 and I've seen it through CS4. I was pretty stoked a few years ago when another product I've been with forever was purchased by Adobe: ColdFusion. Being a CF Junkie since the Allaire days, seeing it through Macromedia and the Adobe acquisition, living through the yearly '<insert company here> is going to discontinue ColdFusion' threads and generally enjoying being a Team Macromedia member and now an Adobe Community Expert for ColdFusion, I'm happy to announce that public betas of both ColdFusion 9 and ColdFusion Builder are being launched right at this very minute.

There have been quite a few announcements of new features coming out in ColdFusion 9 (codenamed Centaur) so I'll just hit a few of the most exciting to me:
  1. CFaaS (ColdFusion as a Service) - ColdFusion core services are available via web services such as PDF document management, email, charting and image manipulation.
  2. Enhanced CFSCRIPT support - that's right! The tag functionality we have been been breaking out of script for is now available in cfscript! No more switching back and forth... use script when it makes sense for the entire process, not just bits and pieces.
  3. Implicit getters and setters - I just cannot say enough about this feature. Thanks Adobe!
  4. Lots of changes to CFCs - too many to list, just go check the docs.
  5. Caching improvements - granular control of objects and page fragments to disk or memory cache.
  6. Portlets - Government shops will love this one. You can now expose ColdFusion applications as portlets in leading JEE portals.
  7. Desktop server manager - AIR app lets you manage multiple servers from the same console (even supports clusters).
There are a few other features that are cool as well, go check them out (links at the bottom of the post).

Now to the second release of the night - I've seen quite a few ColdFusion IDEs - having worked in ColdFusion Studio, Homesite+, instructing in Dreamweaver and rocking the house in CF Eclipse, and now I'm proud to have gotten to take a sneak peek at ColdFusion Builder, the first code centric IDE for ColdFusion put out by the parent company since Homesite! I have to say, it's very cool and very handy. It is built on Eclipse, so one IDE to rule them all. Code generation has been moved out of Flex Builder (now Flash Builder) and integrated into CF Builder. You can connect to CF exposed services right from the IDE, generate AS3 code, start and stop servers and <drumroll>STEP DEBUG</drumroll>. CF Builder also provides code hinting and insight the likes of Flash Builder :). It even supports code refactoring, meaning updating a function name in a CFC will update all references to that function within your project!

I'm pretty excited about this release. I was glad to see the release provides more under the hood performance and functionality than widget-type tags. Go see for yourself:




Now the fun bits:
ColdFusion 9 Public Beta
ColdFusion Builder Public Beta

Developing Applications with ColdFusion 9
ColdFusion 9 CFML Reference
Installation Guide for ColdFusion Builder
Using Adobe ColdFusion Builder