Wednesday, November 19, 2008

The end is here

Marcel Panse and I decided to begin separate personal blogs. The MAD Code Monkey blog will not be used from this day on.

Our new blogs are:
Marcel Panse
Daniel Rijkhof

The reason for this change is, the url of this blog is a joke, and so is the name 'MAD Code Monkeys'. 'Java aap' actually means Java Monkey.

I wish Marcel good luck with his new blog, and i know i'll be reading every post.

Wednesday, October 29, 2008

As3 compiler bug

written by Marcel Panse

I was refactoring some code today in my flex as3 project and ran into a very strange compiler bug. What i did was selecting a bunch of code from a switch statement en pasting it in some other method. When i came to the point the entire switch statement was empty i forgot to remove the statement. As i continued refactoring and came to the point that it actually compiled, but now flex builder was saying:
"An internal build error has occurred. Right-click for more information".

So i check the errors log in eclipse which stated the following error:
Uncaught exception in compiler:
java.lang.NullPointerException
at macromedia.asc.semantics.ConfigurationEvaluator.evaluate(Unknown Source)
at macromedia.asc.parser.SwitchStatementNode.evaluate(Unknown Source)
at macromedia.asc.semantics.ConfigurationEvaluator.evalAndFold(Unknown Source)
at macromedia.asc.semantics.ConfigurationEvaluator.evaluate(Unknown Source)
at macromedia.asc.parser.StatementListNode.evaluate(Unknown Source)...
The parser actually gives a nullpointer exception in the SwitchStatementNode. I removed the switch statements and the error was gone.
var value:int = 0;
switch(value){
}
If you put that code somewhere in some class in a project, the compiler will start throwing nullpointers and you will probably have a hard time figuring out where the malicious statement is..

I checked the adobe bug database and there already is a report on this issue: http://bugs.adobe.com/jira/browse/ASC-2839 stating it is fixed in the next version.

Wednesday, September 24, 2008

Bamboo Build Details Ant Task

Update
The code is now available as a google opensource project: http://code.google.com/p/bamboo-ant-tasks/

Any news about the ant task will be posted there, and/or on my personal blog: http://daniel-rijkhof.blogspot.com

What is it?
I build an ant task to get status information about bamboo builds. The task is build for and tested on bamboo 1.2.4. The current features include:
• Getting latest build number and latest build status (by build plan)
• Getting the status from any build (by build plan and build number)

Why is it useful
As a developer I want to have fully automated deployment on my environments. I can accomplish this with an Ant script. Our product is build on a bamboo build server. What stopped me?
• Our bamboo server cannot access our environments
• Bamboo does not provide direct links to the latest build artifacts (it does provide a redirect)
• Bamboo does not provide me with status information about the latest build

This ant task provides a way to fully automate deployment of the latest bamboo build, and add a sanity check to the automated deploy script (check if the build was successful).

Usage:
<property name="buildplan" value="your-buildplan-name-goes-here"/>
<property name="buildserver" value="http://bamboo.quintor.nl/"/>

<taskdef classpath="your-location-of/bamboo-ant-tasks.jar" classname="GetBambooBuildDetails" name="getBuildDetails"/>

<target name="shortExample">
<getBuildDetails server="${server}" buildplan="${buildplan}" buildnumberProperty="buildnumber"/>
<echo>buildnumber: ${buildnumber}</echo>
</target>

You'll have to change the red lines to make it work on your own bamboo server.

Don't forget to take a look at the example in the download package, where all parameters are used! In case there are any questions left, comment on this blog article.

Download:
You can download the task here: bamboo-ant-tasks.zip
The download contains the following:
• The source code of the ant task
• bamboo-ant-tasks.jar in the /target/dist dir, which includes only the compiled task
• Build script to build the jar
• 2 examples fullExample and shortExample, showing how to use this task (see build.xml)

The package is actually my eclipse project, so it will include .classpath and project files, and the ant.jar thats needed to compile.

Update
I fixed a bug found by Marcel; the ant task couldn't handle the status of an build that fixed previously failed build(s).

The download contains the newest code.

Please leave a comment :Daniel

Tuesday, September 09, 2008

Flex not working properly in Google Chrome

For some reason flex isn't working in google chrome when u use the history enabled methods. It seems like google chrome automatically redirects back to the previous page when you change the location url in the browser.

For example try www.parleys.com with your google chrome browser. Try navigation around and you will see you can't get away from the 'home' page of parleys..

Chrome is build upon Webkit, but i've never seen problems like this in Safari. So it seems like a Chrome bug..? Is there a workaround..?

written by Marcel Panse

Monday, September 08, 2008

Announcing project Scrumbox: Opensource Scrum project management tool.

At our company we do all our projects using Scrum. Scrum is an iterative incremental process of software development commonly used with agile software development. A lot of projects use for example JIRA for their issue tracking. JIRA just isn't the best tool when you work with Scrum. Don't get me wrong, JIRA is a great tool, just not the tool for the job. There are some JIRA plugins to generate burndown charts or scrumboards, they make life al little easyer. You can do lots of tricks like using versions for sprints or backlogs. But what about Epics or Themes?
There are some other great software products out there build entirely around scrum, but they all are way to expensive (500$ per user/per year whoa!).

So we decided to build are own tool, totally open source. This tool is going to be build in java and flex. The focus is to make the GUI as fast and intuitive as possible. Making use of flex's capabilities like dragging and dropping issues from the project backlog to a sprint backlog, or prioritizing the backlog by drag and drop. Also changing the state of an issue should be as simple as looking at the scrumboard and dragging and dropping it from the 'in progress' column to the 'resolved' column.

So definitly keep and eye on http://scrumbox.googlecode.com and this blog for updates about the project. Anybody interesting in committing to this project should contact me..

Project architecture:
The backend will be build in java. Using Spring as IoC container and hibernate as ORM layer. As database we will use MySQL. Everything will be programmed TDD style using JUnit4 and EasyMock. We add a security layer with Spring security and build our project with ant.

The frontend will be build in flex. Using Prana as IoC container. Later there might also be an AIR version (for offline work). We also built this project with ant.

written by Marcel Panse

Tuesday, July 15, 2008

Hibernate annotations: Reversing the bidirectional relationship

written by Marcel Panse

Making a bidirectional relationship in hibernate using annotations is easy. Just make a ManyToOne at one side and a OneToMany at the other. Use the mappedBy property to make the relationship bidirectional.
I thought this means when editing the Collection side and saving this collection side, that hibernate would update the foreign key automatically at the other table.

For example, when you have a User with multiple Products and you add a product to the user like user.products.addItem(product). And then saves the user like userDao.save(user). This does not update the foreign key in the product table. And next time when you retrieve the user.products from the database, the collection will be empty again. The same goes when you remove a product from the collection.

It all works fine when you do something like product.user = user; and save the product. Then when you retrieve the user the product collection will hold the added product.

The solution is to add a JoinColumn annotation to BOTH sides.

Here is an example:

@OneToMany(targetEntity=ProductImpl.class, cascade={CascadeType.ALL})
@JoinColumn(name = "product_id")
private Collection products;

@ManyToOne(targetEntity=UserImpl.class, cascade={CascadeType.ALL})
@JoinColumn(name = "user_id")
private User user;

Sunday, July 13, 2008

Flex: setting unicode ranges when using a TrueType Font saves over 300kb

written by Marcel Panse

There are a few ways of using fonts in a flex application. The default way of doing it in flex is using 'device fonts'. This means flex will not embed any fonts into you swf file, but it will use the font on the clients computer instead. Flex will try to find a font on his computer that is the closest to the font you configured in you css file.

The following example specifies the device font _sans to use if Flash Player cannot find either of the other fonts on the client machine:

.myClass {
fontFamily: Arial, Helvetica, "_sans";
color: Red;
fontSize: 22;
fontWeight: bold;
}

The drawback of this is that your flex application might not look precisely the same on every computer, which can result in slightly different layouts. Like too long labels resulting in unanticipated scrollbars (Arghh!).

Rather than rely on a client machine to have the fonts you specify, you can embed TrueType font families (.ttf or .otf) in your Flex application. This means that the font is always available to Flash Player when running the application, and you do not have to consider the implications of a missing font.

This has some major advantages; like rotating fonts, making fonts transparent, smoother fonts and anti-aliasing fonts which just means better readability especially with smaller fonts.

But with beauty comes pain: the one major drawback is your swf file will increase in size.. a lot.. Using a standard true type font like Myriad Pro Regular, an increase of about 900kb's is normal (which doubles the size of my entire flex application!). This is because the entire font with all unicode ranges will be embedded into you swf file. At least 50% of these unicode characters you will never use.

But there is hope! The proper way to embed a true type font into you swf file is by specifying the unicode ranges you want to include into you swf file. Only the characters inside these ranges will be embedded into your swf file. You can find the unicode tables on wikipedia: http://en.wikipedia.org/wiki/Latin_characters_in_Unicode

Here is an example which works for me. This example is optimized for the Dutch language. In the Dutch language we use a lot of ë's and é's and stuff, so i also included them, you have to figure out which characters you need for you own language.

@font-face {
src:url("../fonts/MyriadPro-Regular.otf");
fontFamily: myFontFamily;
fontAntiAliasType: advanced;
unicodeRange:
U+0021-U+002F, /* !"#$%&'()*+,-./ */
U+0030-U+0039, /* 0-9 */
U+003A-U+0040, /* :;<=>?@ */
U+0040-U+007E, /* @A-Z[\]^_`a-z{|}~ */
U+00E0-U+00EF, /* àáâãäåæçèéêëìíîï */
U+2022-U+2022; /* • */
}

For more information about fonts see the adobe live docs

Friday, July 11, 2008

Agile Development 'nadelen'

written by Daniel Rijkhof

This blog entry is a reply on an article that’s in Dutch, this is why the blog entry is in Dutch to.

Vandaag las ik een artikel over Agile Development op de site van computable.

In dit artikel worden een aantal nadelen van AD genoemd, waar ik het niet mee eens ben. De nadelen die ik op de schop doe zijn:

• In AD fungeren ontwikkelaars tegelijkertijd als informatie-analist, software-architect en tester
• AD is alleen geschikt voor senior ontwikkelaars
• Ontwikkelaars hebben te weinig skills
• Het werk van de bureaucraten, moet worden gedaan door de specialisten.
• Stakeholders worden niet tevoren gedwongen om hun eisen en verwachtingen te formuleren.
• Planning en budget zijn moeilijk te bepalen
• Belangrijke beslissingen op ad-hoc basis
• Slecht doordachte architectuur en modellen, risico op spaghetti-code
• Veel code weggegooid

De eerste drie
De eerste drie nadelen komen voort uit de gedachte dat een team alleen ontwikkelaars mag bevatten van het zelfde niveau:

• In AD fungeren ontwikkelaars tegelijkertijd als informatie-analist, software-architect en tester
• AD is alleen geschikt voor senior ontwikkelaars
• Ontwikkelaars hebben te weinig skills

Is dit werkelijk een eigenschap van AD?

Het Agile Manifesto is gebaseerd op een aantal principes. De toepasselijke principes voor deze nadelen zijn:

• The most efficient and effective method of conveying information to and within a development team is face-to-face conversation.
• The best architectures, requirements, and designs emerge from self-organizing teams.
• At regular intervals, the team reflects on how to become more effective, then tunes and adjusts its behavior accordingly.

De principes achter het Agile Manifesto zeggen niets over het samenstellen van een team! Mag je dan zelf bepalen wie er in je team komen? Zou het zo kunnen zijn dat het team zelf weet waar de gaten vallen binnen het team? Zouden de bovenstaande 3 principes, een basis vormen om daar achter te komen, en het probleem op te lossen? Ik denk het wel.

Er is geen verplichting om een team te nemen waarin elk persoon dezelfde hoge kwaliteiten heeft. Er is geen regel in AD die zegt dat dit niet mag. Kan je een team samenstellen met requirements specialisten, architect(s), developer(s) en tester(s)? AD laat je hier vrij in. Als het werkt voor jou, doe het dan.

De gedachte dat je alleen ontwikkelaars in je team hebt zitten, is niet correct, en daardoor vervallen deze drie nadelen.

Meer ‘nadelen’:
• Het werk van de bureaucraten, moet worden gedaan door de specialisten.
• Stakeholders worden niet tevoren gedwongen om hun eisen en verwachtingen te formuleren.

Deze nadelen komen voort uit het idee, dat AD alles beschrijft dat in een bedrijf moet gebeuren om succesvol software te ontwikkelen.

Het volgende agile principe geeft aan dat het de bedoeling is, zo snel en vaak mogelijk waardevolle software op te leveren:
• Our highest priority is to satisfy the customer through early and continuous delivery of valuable software.

Stel je voor dat stakeholders niet vertellen wat hun eisen en verwachtingen zijn. Wat moet er nu gedaan worden? Het is een AD noodzaak om te weten wat de stakeholders willen. Vervolgens willen we ook nog weten welke waarde de stakeholders aan hun eigen eisen toekennen, zodat ze zo snel mogelijk werkelijke waarde opgeleverd krijgen. Het nadeel dat ze niet gedwongen worden om hun eisen te formuleren, verwerp ik.

Wie er achter de stakeholders aan gaat om te zorgen dat hun eisen bekent worden, wordt niet gespecificeerd door AD. Zou het een bureaucraat mogen heten? Niets in AD verwerpt dit. Zou het iemand in het team kunnen zijn? Ook dit wordt niet verworpen door AD.

Zou deze ‘bureaucraat’ een specialist zijn op exact dit gebied? Zou dat toch eens mooi zijn!

Planning en budget zijn moeilijk te bepalen

Is dit nadelen toe te kennen aan AD?

Mijn ervaring met non-AD projecten, is dat de planning nooit klopte, en het budget niet te bepalen was. De bedoeling van AD is, om zo snel en vaak mogelijk waardevolle software op te leveren. We kunnen dus kortere planningen maken, en budget voor vrij maken. Het is dan ook makelijker om een correcte planning te maken in vergelijking met non-AD projecten. Het los krijgen van budget is vast makelijker als jou planningen kloppen. Dit kan geen nadeel van AD zijn.

Belangrijke beslissingen op ad-hoc basis

Belangrijke beslissingen, zullen altijd gebeuren, en vrijwel nooit aangekondigd. Ik heb nog nooit gehoord dat een bedrijf een geweldige kans op een vergroting van de winst, heeft uitgesteld omdat er nog een planning vast stond.
Flexibiliteit van het ontwikkel proces is dan ook gewenst, zodat er niet te veel waarde verloren gaat.

Het volgende agile principe is de basis voor flexibiliteit:
• Deliver working software frequently, from a couple of weeks to a couple of months, with a preference to the shorter timescale.

In non-AD projecten, komt het voor dat er nog geen waarde opgeleverd is, en ook niet zal gebeuren in een korte tijd. In AD projecten word er elke iteratie waarde opgeleverd. Het verlies van waarde wordt geminimaliseerd door een korte iteratie tijd. Er is ook nog de optie, om de iteratie af te maken, waardoor er geen waarde verloren gaat, natuurlijk ten koste van een beetje tijd.

Het volgende agile principe maakt mijn argument af:
• Welcome changing requirements, even late in development. Agile processes harness change for the customer's competitive advantage.

Omgaan met ad-hoc beslissingen, gaat beter met AD projecten vergeleken met non-AD. Dit nadeel is wordt door AD zelfs niet gezien als nadeel, maar als een eigenschap van de business.

Slecht doordachte architectuur en modellen, risico op spaghetti-code

Het volgende agile principe zegt voldoende:
• Continuous attention to technical excellence and good design enhances agility.

In het geval dat dit nadeel toch voorkomt, dient het team zichzelf aan te passen. Zie weer het volgende agile principe:
• At regular intervals, the team reflects on how to become more effective, then tunes and adjusts its behavior accordingly.

Veel code weggegooid

Het zou kunnen voorkomen dat er code is geschreven dat vervangen moet worden, of zelfs niet meer in gebruik is, en weg gehaald dient te worden. Als deze code is geschreven in een vorige AD iteratie, dan was deze code waardevol. Zie weer het volgende agile principe:
• Our highest priority is to satisfy the customer through early and continuous delivery of valuable software.

In dit geval was de code ooit waardevol, en is het nodig om deze code aan te passen om de software nog waardevoller te maken. Waar is het nadeel? Ik zie het niet.


Is AD perfect?

Niets is perfect. Wanneer ik AD vergelijk met de oudere manieren van software ontwikkeling, concludeer ik dat AD geweldig is, een stap richting perfectie.

Tuesday, April 22, 2008

Albelli photobucket launched!

written by Marcel Panse

The X-Editor is finally live! The X-Editor (pronounce cross-editor), is a multi-platfom photobook editor written in flex 3 using Adobe Air technology.

It is launched today under the brand albelli (www.albelli.com) and uses the new photobucket API.

You can read the official press release here: Albelli photobucket press release.

I'm very proud to be a part of this for the last year. The next few weeks are going to be very exciting.

For now, albelli only ships in the US, but europe is going to follow soon!

So check it out at: http://www.albelli.com/photobucket, download the editor, play around and offcourse buy a book ;-)

greetz,
marcel panse

Tuesday, April 15, 2008

Prana Jumpstart

For everyone who wants to start using prana here is a (very) short tutorial.

1. Join the mailing list for all your questions: http://www.pranaframework.org/?page_id=4
2. Download the latest prana release: http://www.pranaframework.org/?page_id=5
3. Copy the prana.swc file from the bin dir to your projects lib dir and add the swc to your project in flexbuilder.
4. Create a file named applicationContext.xml in your projects source directory.
5. Check some samples to see what the xml file should look like and check the API: http://www.pranaframework.org/?page_id=2
6. Use an XmlObjectDefinitionsLoader to load the applicationContext.xml file and start to retrieving objects from the context.

Thats it, i'll add some code samples:

I created a utility class to retrieve objects from prana:
private var _objectsLoader:IObjectDefinitionsLoader;

public function loadContext(context:String):void {
// an instance of XmlObjectDefinitionsLoader is able to load an XML
// file with object definitions and parse it to an object container
_objectsLoader = new XmlObjectDefinitionsLoader();

// listen for the object definitions loader to complete
// (loaded and parsed xml object definitions)
_objectsLoader.addEventListener(ObjectDefinitionsLoaderEvent.COMPLETE,
onLoadApplicationContextComplete);

// start the loading and specify the location of the object definitions
_objectsLoader.load(context);
}

private function onLoadApplicationContextComplete(event:Event):void {
dispatchEvent(new Event(LOADING_COMPLETE));
Logger.info("Prana application context loading complete.");
}

public function getObject(beanName:String) : Object {
return _objectsLoader.container.getObject(beanName);
}

You can define two objects that depend on each other like this:
<object id="userController" class="nl.quintor.university.user.controller.UserController">
<constructor-arg ref="userModel"/>
</object>

<object id="userModel" class="nl.quintor.university.user.model.UserModel">
</object>

written by Marcel Panse

Monday, December 24, 2007

Super scalable Java applications with terracotta and the Amazon elastic computing cloud (ec2).

written by Marcel Panse

I just got this idea, and i don't know if it works at all. I'm just playing with the idea and thought i might just as well write it down here immediately.

Amazon (S3 and EC2)

Amazons launched a couple of services, one of them is EC2 (Elastic Computing Cloud) and one of them is S3 (Simple Storage Service). S3 is a distributed storage solution where you can store an unlimited amount of data online. This storage is actually distributed over lots and lots of (virtual) servers around the globe.
Amazon S3 provides a simple web services interface that can be used to store and retrieve any amount of data, at any time, from anywhere on the web. It gives any developer access to the same highly scalable, reliable, fast, inexpensive data storage infrastructure that Amazon uses to run its own global network of web sites.
When using S3 you only have to pay about $0.18 per GB storage a month and $0.16 per GB data transfer a month.
EC2 stands for 'Elastic computing cloud' and makes it possible to launch an image of a server online. This virtual server will be launched somewhere in the computing cloud, which again is distributed over lots of servers.
Just as Amazon Simple Storage Service (Amazon S3) enables storage in the cloud, Amazon EC2 enables "compute" in the cloud. Amazon EC2's simple web service interface allows you to obtain and configure capacity with minimal friction. It provides you with complete control of your computing resources and lets you run on Amazon's proven computing environment. Amazon EC2 reduces the time required to obtain and boot new server instances to minutes, allowing you to quickly scale capacity, both up and down, as your computing requirements change. Amazon EC2 changes the economics of computing by allowing you to pay only for capacity that you actually use.
You pay about $0.10 per instance hour. I can imaging it saves a lot of money, since you only launch the amount of servers you need at the moment and you are able to scale it down or up when you like to.

Terracotta

Open Terracotta is Open Source JVM-level clustering software for Java. It delivers clustering as a runtime infrastructure service, which simplifies the task of clustering a Java application immensely, by effectively clustering the JVM underneath the application, instead of clustering the application itself.

Open Terracotta's JVM-level clustering can turn single-node, multi-threaded applications into distributed, multi-node applications, often with no code changes. Terracotta plugs into the Java Memory Model in order to maintain semantics of Java (Java Language Specification), such as pass-by-reference, thread coordination, and garbage collection across the cluster. Open Terracotta's JVM-level clustering is enabled through declarative configuration (XML), and provides fine-grained, field-level replication, which means that objects do not need to implement Java serialization.

With a simple load balancer it doesn't matter to which server the request is send, because all servers are on the grid and share the same memory and thus all user sessions are available on all servers. When adding a new server to the grid it takes automatically the state of the application and can receive requests immediately. This makes it very easy to scale up when needed.

Another idea is to use Amazons S3 Service (distributed online storage) for file storage, because this also is unlimited scalable. All data transfer between the EC2 cloud and S3 is free!

Winning combination?

The idea is to create a standard java backend application (the usual spring/hibernate/etc application). Then we take that application and launch it in a terracotta grid. That makes it scalable over multiple servers sharing the same resources through terracotta. Take it a step further by creating an image and launch it in Amazons EC2 cloud.

Possible challenges (problems do not exists, right?)

All images in the EC2 cloud are stateless, when the server images goes offline or restarts all state is gone. Every image starts from a blank image, so you can't write to disk. But that shouldn't be necessary if we write all files to S3. Another thing is databases, if we have like 5 images in the cloud all running terracotta and thus share the same memory/state. Then we don't have to do persist anything to the database, and just keep it in memory. Terracotta could drastically help to reduce the database load. But we can't keep everything in memory, you don't want to keep historic data that is practically not used anymore in memory. You only want to keep objects in memory that you are likely to query a lot. Where do we store the data that we don't want in memory? I heard about the Amazon Simple Database (SDB), which is going to get launched pretty soon (at the moment of writing this). I didn't look into it yet, but sounds promising.

I'm going to work this out and try this later, i you have any comments or suggestions let me know!

Thursday, November 01, 2007

EXIF Info Hell

Kevin Hoyt has written some nice examples in his blog (http://blog.kevinhoyt.org/) about using EXIF info in AIR applications.

I've been writing an application that is using EXIF info to get the jpg thumbnail from it without having to read the entire file.. Now this is working as a charm BUT..

There are multiple version of the EXIF standard and there are different manufacturers using it different. I have tested my application with the code from kevin hoyt, it worked on my Sony digital camera, but didn't work on another Sony camera and also failed on a Canon camera. Where the failing sony didnt succeed to retrieved jpeg bytes at all. I could retrieve bytes from the canon picture but these are not valid jpeg..

I read through some of the EXIF documentations of the official standard but it can't figure it out how to create a parser that always succeeds.

That plus the fact that most users make their landscape pictures portrait using the windows picture viewer, which just dumps all EXIF information from the JPG. Even when using photoshop to do this is deletes your EXIF.

This all makes it pretty useless for any application to depend on, until someone comes up with a superparser compatible with all manufacturers.

So back to reading the entire file just to show a quick thumbnail (which makes it impossible to create like a thumbnailbrowser).

written by Marcel Panse

Tuesday, September 04, 2007

Garbage Collection

written by Marcel Panse

I'm working on an AIR application that has to load up a lot of pictures from a users system. I have to be able to load about 120 photos (of 3MB each), open them, resize it and save it in memory and cache a resized photo to disk. So i created a manager which has an internal queueing system which loads the photos one by one and doing the operations before continueing on to the next photo. The most processor time goes into loading the photos from disk into memory, which is a asynchronous job, so the GUI has plenty of time to update and keep track with a simple loading bar.

Now the weird stuff, the calls to load the next photo uses 'Application.application.callLater(loadPhoto)', on a Windows machine this is no problem at all, and it loads 120photos easily (i've tested it with up to 500). Now if you change that sencentence to 'setTimeOut(loadPhoto, 500)', then it suddenly stops working. It loads up to 70photos and then sais 'Invalid bitmapdata'. This is probebly because the garbage collector is too slow and can't free the memory intime, resulting in memory allocation errors.
When i'm running the same thing on a MacBook Pro (which is faster then my window laptop, and has twice the RAM), then suddenly both scenarios don't work and i can only load up to 17 photos. RAM Climbing very fast up to 500megs and crashes...

Now thats sucks big time!

Then i came across the web and found a garbage collection hack, i didn't feel like that was going to be the solution but gave it a try anyway and the miracle happend and everything runs like a charm, no problems at all on windows or the mac.

The hack is as follows:


private function gcHack():void
{
// unsupported hack that seems to force a full GC
try
{
var lc1:LocalConnection = new LocalConnection();
var lc2:LocalConnection = new LocalConnection();

lc1.connect('name');
lc2.connect('name');
}
catch (e:Error)
{
}
}


This forces the garbage collector to do a full garbage collection.
This makes me wonder, why isn't there a feature in flex that does exactly do this?

Tuesday, July 31, 2007

Flex Image Repository (Application wide image cache)

written by Marcel Panse

Flex has some options for image caching on its own, but it leaves the image caching for the browser to handle. This creates differences between browsers (i have written applications that caches really well in IE but not so well in FF). This browser cache isn't very reliable, plus it takes a really small amount of time to retrieve (because it is http based and it needs a http call to retrieve) what causes the image to flicker. What i really want is some sort of application wide caching mechanism for images.

Another thing is that it works (offcourse) also for AIR applications, so it should work both with online and offline files. The thing that makes these files unique is the location of the file, what could be either 'http://...' or 'file://...'

The solution is really simple. Create a class that can store images in a map (like a java hash-map). This class should be a singleton and have a couple of methods like:
- lookup(location:String)
- cacheImage(location:String, image:Bitmap)

And everywhere in your application when you use an Image object just set the source to the bitmap from the repository (instead of a url).
How to load the bitmap from an online or offline file is a whole different story (and much more complicated). I will discuss that in my next blog entry.

Sunday, July 08, 2007

Refactoring your Templates

StringTemplate is a template engine written by Terence Parr, the author of the popular ANTLR parser generator. It is based upon the idea of Enforcing a strict Model-View separation in Template Engines. Its features allows you to restructure you templates to be more maintenance friendly: so therefore I chose the title "Refactoring your Templates".

What is a template?

Templates are textual files with "holes" in it that that can be filled with data. Besides these holes templates also need facilities for: looping through items, conditional formatting, template fragments and string formatting.

How does JSP handle this?

JSP uses scriptlets inside the template: small fragments of code. These code fragments give full access to the Java language. The danger of using java code for control flow is that templates are not fully separated from underlying data computations. For instance: programmers may choose to quickly embed a JDBC query inside a template. They also lack facilities for reuse: object-oriented features like inheritance and components are not available.

How does StringTemplate do better?

  • Templates contain no code fragments.
  • Templates can be named and may accept attributes.
  • Templates can be grouped in a single file.
  • Template groups can use inheritance to reduce template duplication.

Templates do not embed code fragments, that allows you to use the same template on different platforms. Naming templates allows you to call templates inside other templates and those calls can receive arguments. Grouping templates into a single file is convenient when you break up templates into smaller parts. Inheritance of templates allows you to override named templates in a group. This feature is nice if you need similar but slightly different results. For example when your program generates SQL and you want to support different SQL database dialects.

How do I use StringTemplate?

This article is a quick introduction to StringTemplate, for more information please see the documentation. The StringTemplate essentials in six bullets:

  • Holes inside the template are marked using dollars, for instance: $username$.
  • Every substitution argument must be calculated beforehand and assigned, using the setAttribute("username", "Foo Bar").
  • Properties of attributes syntax: $person.email$.
  • Conditional substitution syntax is: $if(title)$<h1>$title$</h1>$endif$.
  • Results of template substitution is available using the toString() method.

Requiring arguments to be assigned beforehand makes sure that your code has no order-of-computation dependencies, that make your code difficult to change.

Example template "page.st"

 <html>
<head>
<title>$title$</title>
<meta name="keywords" content="$keyword; separator=","$"/>
</head>
<body>

<h1>Hello $username$!</h1>

<ul>$person:{
<li><a href="mailto:$attr.email$">$attr.name$</a></li>}$
</ul>

</body>
</html>

Example Java code

 import org.antlr.stringtemplate.*;

class Person {
       public String name;
       public String email;

       Person(String name, String email) {
             this.name = name;
             this.email = email;
       }
}

public class Main {

       /**
        * Simple StringTemplate example.
        * @param args
        * @throws IOException
        */

       public static void main(String[] args) throws IOException {
             StringTemplateGroup group = new StringTemplateGroup("website", ".");
             StringTemplate page = group.getInstanceOf("page1");
             page.setAttribute("title", "StringTemplate Rocks!");
             page.setAttribute("username", "Foo Bar");
             page.setAttribute("keyword", "foo");
             page.setAttribute("keyword", "bar");
             page.setAttribute("person",
                    new Person("Webmaster", "webmaster@domain.com"));
             page.setAttribute("person",
                    new Person("Manager", "manager@domain.com"));
             page.setAttribute("item", "bar");
             System.out.println(page.toString());
       }
}

Example result

 <html>
<head>
<title>StringTemplate Rocks!</title>
<meta name="keywords" content="foo,bar"/>
</head>
<body>

<h1>Hello Foo Bar!</h1>

<ul>
<li><a href="mailto:webmaster@domain.com">Webmaster</a></li>
<li><a href="mailto:manager@domain.com">Manager</a></li>
</ul>

</body>
</html>

Templates can be applied to attributes

The example code assigns more items to the person attribute, that are formatted into a list of links. The syntax used is:

 $person:{<ul><a href="mailto:$attr.email$">$attr.name$</a></ul>}$ 

The text between the curly brackets is a template to format a person. There is no need for special looping syntax, because the template is applied to each person.

Extract templates into separate files and call them by name

The person template can be extracted into a separate file and called by its name.

Example template "email_link.st"

 <li><a href="mailto:$attr.email$">$attr.name$</a></li> 

Change inside template "page.st"

 [...]
<ul>
$person:email_link()$
</ul>
[...]

Templates with named arguments

The default argument name is "attr", however it is also possible to use named arguments:

Example template "label_input.st"

 <p>
  <label for="$id$">$label$</label><br/>
  <input name="$id$" id="$id$" type="text" value="$value$"/>
</p>

Example call

 <form>
$label_input(id="test",label="Message",value="Hello World")$
</form>

Example results

 <form>
<p>
  <label for="test">Message</label><br/>
  <input name="test" id="test" type="text" value="Hello World"/>
</p>
</form>

Advanced features

Examples and documentation are in the excellent StringTemplate documentation. More  advanced features of StringTemplate are:

  • Template group files
  • Template inheritance

Group files use the *.stg extension and embed a number of named templates. When you have lots of small templates, this might be more convenient.

Templates are ordered in named groups. It is possible to use an existing template group as a basis and override/extend some templates.

Conclusion

StringTempate helps ANTLR to add a new language backend without adjusting a single line of code. This is a showcase of the power of StringTemplate and how it helps to define complex templates in a clean way.

StringTemplate available for different platforms: Java, C# and Python. It is an interesting project if you need clean templates, certainly worth a look!

Links:

Friday, July 06, 2007

Code Complexity

written by Daniel Rijkhof

About

This blog entry is quick read summary about code complexity. It gives a definition of code complexity and several signs how to notice code complexity. It also provides a brief description how to measure code complexity and suggests a way to keep it low.
Most of the concepts are taken from Structure 101 help section.

This blog entry is based upon my code complexity presentation for www.greetz.com.

Definition of Code Complexity

Reg. Charney defines Code Complexity as:
the amount of effort needed to understand and modify the code correctly.
see http://www.linuxjournal.com/article/8035.

Excessive complexity: When is a code-base too complex?

Signs of Logical complexity:
  • part of the design is no longer fit for its purpose
  • unclear purpose
  • adding new features becomes harder than it should be
Signs of Structural complexity:
  • the code is hard to understand
  • changes have unexpected side effects


The need to know about code complexity

Keeping track of code complexity helps to:
  • Predict (future) feature implementation times
  • prioritize areas of the code for structural refactoring
What happens if you don't manage complexity?
It will cost!

Manage complexity like debt
Howard Cunningham 'Mr. Wiki' compared complexity with debt:
"Manage complexity like debt"
skipping designs = borrowing money
maintenance headaches = interest payments
refactoring = repaying debt
cannot refactor = cash-flow insolvency
creating engineering policies = devising financial policies


Andy Hunt extends the analogy concisely:
"Just like real debt, it doesn't take much to get to the point where you can never pay it back, where you have so many problems you can never go back and address them."


What can we do? Measure Complexity!

Although we cannot specify the amount of effort needed. We can calculate a complexity index.

This index enables us to:
  • Compare projects
  • Monitor trends (getting more or less complex)
  • Discover which items at what level are causing the complexity.


Measuring Code Complexity

Measure the complexity at every level of design breakout, method, class, package and
high-level package (High level packages contain only other high-level packages or leaf packages).

Measuring occurs by counting items and dependencies it immediately contains.

Method complexity is usually calculated by cyclomatic complexity.

About Cyclomatic complexity

What is Cyclomatic complexity?
A measurement for the complexity of a peace of source code.
What does it measure?
The number of linearly independent paths through a peace source code.

Cyclomatic Complexity @ wikipedia

Calculating Cyclomatic Complexity

To calculate cyclomatic complexity build a graph that describes the control flow of the program. The nodes of the graph correspond to the commands of a program. A directed edge connects two nodes if the second command might be executed immediately after the first command.






The number of linearly independent paths through the first method is 3, and the second is 2.

In Structure 101, class, package and high-level package complexity is calculated by counting items and dependencies they immediately contain (screenshot from Structure 101 help):



Design Tangles
Design tangles are cyclic, package-level dependencies. Design Tangle Metric quantifies the amount of cyclic dependencies.



Refactoring
Defenition of Refactoring:
improving the design of existing code.

Always Refactor when adding new features to you code.

Quote Chris Chedgey:
"You use personality, charisma, leadership and/or donuts to convince your team that henceforth, they will not add any more complexity debt to the code base. Now watch what happens..."

I suggest reading Chris blog item: http://chris.headwaysoftware.com/2006/10/reducing_comple.html.

The need to Rebuild
In some cases redesign and rebuild is faster then refactoring. The complexity index of the tipping point cannot be determined.

Future Vision
Chris Chedgey says: "keep a lid on it"
I agree!

  • Monitor complexity (Structure 101)
  • Keep complexity low (stay away from the need to rebuild)



Resources

Structure 101 Help see http://www.structure101.com
Cyclomatic Complexity @ wikipedia

Chris Chedgey blog entries:
http://chris.headwaysoftware.com/2006/09/complexity_over.html
http://chris.headwaysoftware.com/2006/10/reducing_comple.html


http://www.linuxjournal.com/article/8035

Wednesday, July 04, 2007

Flex and AIR application with one codebase

written by Marcel Panse

I'm creating my first AIR application, or better i'm porting my existing webapplication to an AIR project. The application is all about online imaging and the one thing it is missing is local file access; a perfect setup for an AIR application.

First i wanted to just make my Flex project AIR compatible.. but weird enough that is not possible. I added a Apollo buildcommand and apollo nature to my project file, but flexbuilder can't handle both a flex nature and a apollo nature, so he just picks one and youre project isn't flex compatible anymore (you get an error when lauching through the Run... buttons).

So i went for the next approuch, too seperate projects with the same codebase. There are several options to achieve this.
1. Create libraries and modules for common code
2. Create a symlink to the source dir

The first one looks the best option but needs a lot of refactoring at the moment in the project, thats what we are going to do when there is more time (this is a proof of concept).
The latter is the easyest solution. I Created an AIR project and created a symlink by clicking:
New -> Folder -> Advanced -> 'Link folder to the file system'
and linked it to the source dir.

Now i still continue to work on my Flex Project and once in a while i can create an AIR Installer file by simply clicking the button in the other project.

Next i created a 'Seamless Installer'. This piece of code simply checks wether the user has the AIR runtime and let the user install your application including the runtime or just the application.

You create this 'badge' by copying the badge.swf from
'sdks/moxie/samples/badge/badge.swf'
and create a html file like:
<html>
<head>
<title>title</title>
</head>
<body>
<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=7,0,0,0" width="217" height="180" id="badge" align="middle">
<param name="allowScriptAccess" value="all" />
<param name="movie" value="badge.swf" />
<param name="quality" value="high" />
<param name="bgcolor" value="#FFFFFF" />
<param name="FlashVars" value="appname=ApplicationTitle&appurl=http://localhost/application.air&airversion=1.0.M2&buttoncolor=008811&messagecolor=000000" />
<embed src="badge.swf" quality="high" bgcolor="#FFFFFF" width="217" height="180" name="badge" align="middle" allowScriptAccess="all" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" FlashVars="appname=ApplicationTitle&appurl=http://localhost/application.air&airversion=1.0.M4&buttoncolor=008811&messagecolor=000000"/>
</object>
</body>
</html>

Simply use the flashVars to config the badge.
BTW. If you want to adjust the badge, the .fla is also in the samples dir..

Tuesday, June 12, 2007

How to build ant scripts for Flex

Almost every project nowdays needs an automatic build server for integration tests, while this is common practice in java oriented companies it is fairly new to Flex developers.
First of all you need some kind of versioning system for your code (you really really really can't go without a versioning system for your code!).. I am using subversion (http://subversion.tigris.org/) for my projects.
At one point conflict resolution is not enough when you have multiple developers working on a piece of software with a versioning tool, you have to know day by day if the commits from you and youre co-workers are not conflicting with one another on a functional level (i'm not talking about compile time issues here). So you need to compile the code on the server and run some tests to automatically check if everything still works fine.
Herefore i use the cruisecontrol (http://cruisecontrol.sourceforge.net/) build server together with Ant build scripts and FlexUnit tests.
There are tons of tutorials and howto's about how you install cruisecontrol, subversion and flexUnit.

There is a project in adobe labs called Flex Ant Tasks , wich enables you to compile your flex/actionscript code from ant. It is pretty straightforward if you are familiar with Ant, the only thing i had some problems with is the wrapper creation. The 'standard' way for this is to use the predefined html-wrapper task, that works fine but takes a template from the FLEX-SDK install dir. I have custom html-wrapper in my project and i don't want to copy them on every development machine to the FLEX-SDK. I can't find a way to configure the ant script so that it points to some other directoy in my project. So i had to write that part myself..

The following code is a complete ant script and build.properties file which you can use as a template/reference for you own build scripts. Just place the build.xml and build.properties in the root of your project and alter the variables the way you like. The script is pretty ok documented so i won't go in detail on this. Don't forget that you have to install ANT to run the builds ;-P

build.xml

<?xml version="1.0" encoding="ISO-8859-1" ?>
<project name="Flex Ant File Compiler" default="masterbuild" basedir=".">

<!-- Load Environment specific properties from properties file -->
<property file="build.properties" />

<!-- Load the flex tasks for compiling the actionScript code and running flexUnit -->
<taskdef resource="flexTasks.tasks" classpath="${FLEX.TASK.DIR}" />
<taskdef resource="com/adobe/ac/ant/tasks/tasks.properties" classpath="${FLEX.ANT.TASK.DIR}"/>

<!-- Init with echoing some info to the console -->
<target name="init" description="Initializes the build">
<tstamp/>
<echo message="============================================="/>
<echo message="${project.name}-${project.version} [${TODAY}]"/>
<echo message="Copyright (c) ${project.year} ${project.owner}"/>
<echo message="OS : ${os.name}" />
<echo message="Author: ${author}" />
<echo message="=============================================="/>
</target>

<!-- Compile Main application -->
<target name="compile" depends="init" description="Compiles the mxml/as source files">
<mxmlc
file="${main.class}"
output="${swf.export}"
actionscript-file-encoding="${ENCODING}"
keep-generated-actionscript="false"
incremental="false"
>
<load-config filename="${FLEX_HOME}/frameworks/flex-config.xml"/>
<source-path path-element="${FLEX_HOME}/frameworks"/>
<compiler.source-path path-element="${src.dir}"/>
<compiler.include-libraries dir="${basedir}" append="true">
<include name="${lib.dir}" />
</compiler.include-libraries>
</mxmlc>
</target>

<!-- Run unit test -->
<target name="unit-tests" depends="init" description="Compiles and runs the tests">
<mxmlc
file="${flex.unit.runner}"
output="${flex.unit.swf}"
actionscript-file-encoding="${ENCODING}"
keep-generated-actionscript="false"
incremental="false"
>
<load-config filename="${FLEX_HOME}/frameworks/flex-config.xml"/>
<source-path path-element="${FLEX_HOME}/frameworks"/>
<compiler.source-path path-element="${src.dir}"/>
<compiler.include-libraries dir="${lib.dir}" append="true">
<include name="flexunit.swc" />
<include name="FlexUnitOptional.swc" />
</compiler.include-libraries>
</mxmlc>

<flexunit
timeout="0"
swf="${flex.unit.swf}"
toDir="${report.dir}"
haltonfailure="true" />

<junitreport todir="${report.dir}">
<fileset dir="${report.dir}">
<include name="TEST-*.xml"/>
</fileset>
<report format="frames" todir="${report.dir}/html/"/>
</junitreport>
</target>

<!-- Generate ASDOC -->
<target name="doc" depends="init" description="Generates the asdoc of the source files">
<java className="${asdoc.tool}" fork="true" failonerror="true">
<classpath >
<fileset dir="${FLEX_HOME}/asdoc/lib" includes="*.jar" />
<fileset dir="${FLEX_HOME}/lib" includes="*.jar" />
</classpath>
<jvmarg line="-Dapplication.home=${FLEX_HOME} -Xms32m -Xmx768m -Dsun.io.useCanonCaches=false -Xbootclasspath/p:${FLEX_HOME}/asdoc/lib/xalan.jar"/>
<arg line="-library-path+='${basedir}/${lib.dir}/Cairngorm.swc'"/>
<arg line="-library-path+='${basedir}/${lib.dir}/flexunit.swc'"/>
<arg line="-library-path+='${basedir}/${lib.dir}/corelib.swc'"/>
<arg line="-library-path+='${basedir}/${lib.dir}/FlexUnitOptional.swc'"/>
<arg line="-library-path+='${FLEX_HOME}/frameworks/libs'"/>
<arg line="-library-path+='${FLEX_HOME}/frameworks/locale/en_US'"/>
<arg line="-doc-sources '${src.dir}'" />
<arg line="-main-title '${asdoc.docsname}'" />
<arg line="-window-title '${asdoc.docsname}'" />
<arg line="-output '${docs.asdoc.dir}'" />
<arg line="-footer 'CONFIDENTIAL. Copyright 2007 Your Company'" />
</java>

</target>

<!-- Clean output dirs -->
<target name="clean" description="clean all generated files">
<delete includeemptydirs="true">
<fileset dir="${docs.asdoc.dir}" includes="**/*"/>
<fileset dir="${bin.dir}" includes="**/*" />
<fileset dir="${report.dir}/html" includes="**/*" />
</delete>
<delete>
<fileset dir="${report.dir}" includes="**/*.xml" />
</delete>
</target>

<!-- Create HTML wrapper -->
<target name="wrapper" depends="compile" description="Creates the HTML wrapper">
<!-- Copy the html-wrapper dir except the index.template.html -->
<copy todir="${bin.dir}">
<fileset dir="${wrapper.dir}">
<exclude name="**/index.template.html" />
</fileset>
</copy>
<!-- Copy and rename the index.template.html -->
<copy file="${wrapper.dir}/index.template.html"
tofile="${html.file}" />

<!-- Replace placeholders in the html with our variables -->
<replaceregexp
file="${html.file}"
flags="gs"
match="\$\{width\}"
replace="100%"/>
<replaceregexp
file="${html.file}"
flags="gs"
match="\$\{height\}"
replace="100%"/>
<replaceregexp
file="${html.file}"
flags="gs"
match="\$\{title\}"
replace="{project.name}"
encoding="utf-8"/>
<replaceregexp
file="${html.file}"
flags="gs"
match="\$\{version_major\}"
replace="9"/>
<replaceregexp
file="${html.file}"
flags="gs"
match="\$\{version_minor\}"
replace="0"/>
<replaceregexp
file="${html.file}"
flags="gs"
match="\$\{version_revision\}"
replace="0"/>
<replaceregexp
file="${html.file}"
flags="gs"
match="\$\{application\}"
replace="${application.name}"/>
<replaceregexp
file="${html.file}"
flags="gs"
match="\$\{bgcolor\}"
replace="#FFFFFF"/>
<replaceregexp
file="${html.file}"
flags="gs"
match="\$\{swf\}"
replace="${application.name}"/>
</target>

<!-- Run all, default -->
<target name="masterbuild"
depends="clean, compile, unit-tests, wrapper"
description="Complete build in efficient sequence"/>

</project>


build.properties

######################################
## Project information
######################################
author = Marcel Panse
project.owner = Your Company
project.owner.url = http://www.yourcompany.com
project.fullname = Your Project
project.version = 1.0.0 alpha # major.minor[.revision[.build]]
project.name = Project name
project.year = 2007
application.name = Application Name

# Where flex is installed:
FLEX_HOME=C:/DEVELOPMENT/flex_sdk_2
DEFAULT.LOCAL = en_US
ENCODING = UTF-8
######################################
## tools
######################################

### FlexTask
FLEX.TASK.DIR=tools/FlexTasks/lib/flexTasks.jar
FLEX.ANT.TASK.DIR=tools/FlexAntTasks/flexAntTasks.jar
wrapper.dir=html-template

### Asdoc
asdoc.tool=flex2.tools.ASDoc

# The name that will appear in the documentation that is generated.
asdoc.docsname=Project API Documentation

# Browsers
firefox=C:/Program Files/Mozilla Firefox/firefox.exe
ie=C:/Program Files/Internet Explorer/iexplore.exe

# Flash Player
saplayer=player/debug/SAFlashPlayer.exe

######################################
## Properties
######################################
src.dir=source
bin.dir=deploy
build.dir=build
docs.dir=docs
docs.asdoc.dir=${docs.dir}/asdocs
docs.junitreport.dir=${docs.dir}/junitreport
lib.dir=lib
html.file=${bin.dir}/${application.name}.html

main.class = ${src.dir}/Application.mxml
swf.export = ${bin.dir}/Application.swf

# ASSETS DIR
assets.dir=${src.dir}/assets/

######################################
## Flex Unit
######################################

flex.unit.runner = ${src.dir}/AntTestRunner.mxml
flex.unit.swf=${basedir}/${bin.dir}/AntTestRunner.swf
report.dir=${basedir}/docs/junitreport


I also included asDocs in my ant scripts, which generates javaDoc style documentation for your actionScript project. I don't have it fully running myself yet because the asDoc compiler is much stricter then the flex builder sdk compiler, so i get a lot of errors on unused imports and stuff and i just don't have the time to fix it (for now).

The directory structure of my project is as follows:

-root
  -deploy
  -docs
    -asdocs
    -junit report
     -html
  -html-template
  -lib
  -source
  -tools
   -FlexAntTasks (contains the FlexAntTasks.jar)
   -FlexTasks (contains the flexTasks.jar
-.actionScriptProperties
-.flexProperties
-build.properties
-build.xml


written by Marcel Panse

Tuesday, May 15, 2007

Configuration of Environment Settings

written by Daniel Rijkhof

I get a lot of questions asking how I deal with configuring environment specific settings. I'll explain my solution here.

The following solution depends on the Spring framework.

1) have a separate package per environment (e.g. production, test, local)
2) put a properties file in this directory (e.g. webapp.properties)
3) configure the spring context
4) set a system environment variable to choose your environment


I'll use the following packages:

com.mad.project.env.junit
com.mad.project.env.local
com.mad.project.env.test
com.mad.project.env.acceptance
com.mad.project.env.production


The webapp.properties files i'm using are simular to my junit.properties file:

hibernate.schemaUpdate=true

hibernate.dialect=org.hibernate.dialect.HSQLDialect
hibernate.show_sql=false

dataSource.driverClassName=org.hsqldb.jdbcDriver
dataSource.url=jdbc:hsqldb:mem:test
dataSource.username=sa
dataSource.password=

webapp.logDir=../logs/junit

env.dir=junit
env.name=junit environment

Note: the env.dir line is only present in my junit env properties file.


The context:

<!-- Property Placeholder -->
<bean id="propertyPlaceholderConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="order" value="1" />
<property name="locations">
<list>
<value>classpath:com/venspro/payment/env/junit/junit.properties</value>
<value>classpath:com/venspro/payment/env/${env.dir}/webapp.properties</value>
</list>
</property>
<property name="ignoreResourceNotFound" value="true" />
</bean>

<!-- Session Factory Bean -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="schemaUpdate" value="${hibernate.schemaUpdate}"/>
<property name="annotatedClasses">
<list>
...
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
</props>
</property>
<property name="dataSource" ref="dataSource" />
</bean>

<!-- Data Source Beans -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<description>Main DataSource</description>
<property name="driverClassName" value="${dataSource.driverClassName}"/>
<property name="url" value="${dataSource.url}"/>
<property name="username" value="${dataSource.username}"/>
<property name="password" value="${dataSource.password}"/>
</bean>

...



Take a close look at the propertyPlaceHolderConfigurer; there is a default configured, and one with an EL expression. If ${env.dir} is not specified, it will not find the properties file, and ignore this because of the ignoreResourceNotFound setting.

The properties in the junit.properties file, are overwritten by any settings in the next properties file.

The only thing left to do is specify the environment setting 'env.dir'. This can be done in several ways; in the servlet container configuration, or on the system environment, or as a parameter to the jvm (-Denv.dir=test).

Wednesday, April 18, 2007

Debug messages

Got some weird debug messages today:

Here is the first i encounterd: "Send Failed".

Appearantly the flex compiler includes a context in the swf. When the swf is downloaded and tries a RemoteObject or other request to the server, it uses the precompiled context of your webapp. So if you are developing at "http://localhost/appcodename", then after a couple of weeks hard work you create a war file like "financeApp.war" and you deploy it to like "http://domain.com/financeApp/". Then suddenly your remote requests give a weird "Send Failed" error... I found out that the url it is requesting is wrong (after hours of debugging) and ended up recompiling the SWF files with the correct context (i set the context from the flex builder -> project properties -> Flex Server. So i changed 'appcodename' to 'financeApp'

Another fun error message: Error #2044: Unhandled SecurityErrorEvent:. text=Error #2047: Security sandbox violation: LocalConnection.send: pc002 cannot access http://domain.com/flexapp/app.swf.

And this message pops up randomly when accessing a flex generated html page with does nothing more then embedding the swf file.

I'm not sure what causes this error, only some flexplugins have this problem and only occasionnally. It has something to do with the history management of your browser. The solution to this problem is to remove the IFrame where flex does its history management (history.htm). The error message dissapears when removing the IFrame. I am not sure why or how, but i recommend not to compile your apps with history management if you don't use it.

Why do i never get a debug message with usefull information?


written by Marcel Panse