Skip to content

FreeMarker Project History

revusky edited this page Jul 13, 2024 · 4 revisions

FreeMarker is, at this point in time (mid-2024) a very established Java library. It has been part of Apache Software Foundation (ASF) since 2014. (ASF is where mature, inactive software projects frequently go to die.)

I am trying to revive some active development on FreeMarker outside of ASF and I am writing this project history to answer certain questions that may come up frequently. Certainly, anybody who wants to get involved seriously with FreeMarker (and that actually includes "Apache FreeMarker") would do well to read this history, so that they understand how certain things evolved, where they came from...

Let us start at the beginning...

FreeMarker 1.x

FreeMarker 1.x was the original FreeMarker, created by Benjamin Geer and Mike Bayer, at some point in the late nineties. I think it was pretty much entirely implemented by Ben Geer, with the core design largely coming from Mike Bayer, which is why he was credited as co-author.

I guess there are several aspects of FreeMarker 1 that left their mark on the project -- even well after any code from the original 1.x implementation was gone:

HTML-ish syntax

FreeMarker 1 opted for a syntax that resembled HTML superficially, as in:

 <if condition>
    blah blah
 <else>
    blah blah blah
 </if>

I guess the original motivation for this was to make the syntax look more familiar to people who primarily work with web pages, an idea that has some merit. However, the Webmacro (and Velocity) approach of having the directives not resemble HTML tags was probably better overall. This seems clear in retrospect. The terse syntax in FreeMarker3 might be considered a (long overdue) recognition of that. In most cases, one can dispense with any <# or [# as long as the directive is on its own line.

Interface-based design (not reflection-based)

FreeMarker 1 used an interface-based design. It was built around a set of core interfaces: TemplateScalarModel, TemplateListModel, and TemplateHashModel. Any variable exposed to the template would implement one (or more than one) of those three interfaces. FreeMarker 1.x had no support for anything numerical, i.e there was no TemplateNumberModel. (The most advanced version of FreeMarker, FreeMarker3 mostly does away with all this and internally uses POJOs directly.)

(Note, by the way, that this interface-based design, IBD if you will, was conceived at a point in time when Java did not yet have annotations. Annotations were introduced in JDK 5, which I think came out in 2004. In terms of specifying in Java code how objects are to be dealt with on the view layer, annotations make more sense than these sorts of marker interfaces. So, one thing I am considering is introducing some set of annotations that allow developers to specify in a more fine-tuned way how Java objects interact with templates. But that is mostly an idea floating around in my head at the moment -- though I initially started thinking about all these things back in 2007 or so, when I became aware of what annotations could offer....)

In retrospect, FreeMarker 2.x (as with the HTML-ish syntax) should probably have moved away from IBD much earlier. The latest FreeMarker3 codebase almost totally eliminates IBD. The various marker interfaces are still there but use is vestigial, mostly to support a certain level of backward compatibility.

Macros

FreeMarker 1.x had macros (even if they were misnamed as "functions"). The macro functionality was primitive, since there was no concept of local variables or namespaces generally.

Now, when I say that the original FreeMarker was really quite primitive, I certainly do not say that to denigrate the original creators, Geer and Bayer. In fact, FreeMarker macros (even in 1.x) were implemented more competently than the so-called velocimacros in Velocity, which did not allow forward referencing and thus, recursion was impossible. I actually do not know for sure if those horrible limitations have been addressed in the last 20 years. In any case, the original 1.x implementation did provide enough of a basis to work on and eventually was transformed into what it is now.

Note that the technology that Java's owner, Sun Microsystems, was promoting at that time, Java Server Pages (JSP for short) was really so utterly horrible that there was significant demand for an alternative. WebMacro, written by Justin Wells, also gained some level of popularity at roughly the same time as FreeMarker 1.

My own involvement with FreeMarker 1.x was simply as a user. I used FreeMarker in a number of projects in the late nineties and had become kind of fond of it -- though I was also quite aware of its limitations.

FreeMarker 2.x

Truth told, I do not think that Ben Geer was really involved in the project for that long after creating it. When I made overtures to the existing FreeMarker community, in late 2001, the original authors were certainly long gone. I don't know whether they created the FreeMarker project on Sourceforge (which is what people used before Github) but they were not involved there. The freemarker-devel mail archive dates back to January 2000 and the original authors did not participate in any discussion there. One can see that there was some bit of activity on the mailing list, but there was no real roadmap for further development.

My original motivation for getting involved with FreeMarker was that I was quite interested in learning how to use a parser generator tool, something like JavaCC, and I decided to try to rewrite FreeMarker's parser (originally hand-coded by the aforementioned Ben Geer) using JavaCC. I now see, looking back, my announcement of a first version of a JavaCC-generated parser, was on 17 September 2001. I guess I did not yet have commit rights to the CVS repository, so I attached my initial version of a JavaCC grammar for FreeMarker to the email.

For the first period of my involvement, I had configured the use of the new JavaCC based parser as an experimental option. The newer parser, via code actions in the grammar, built the same tree of nodes as the older hand-written parser. However, at some point in the next few months, the older hand-written parser was thrown away as unneeded. One could say that this is when FreeMarker 2 was born!

The first public release of FreeMarker 2 was in March of 2002. From that point, for the next two years roughly, FreeMarker went through an intense evolution, going through several release cycles, 2.0, 2.1, 2.2, and 2.3. I shall refer to this period of intense development as the "big push".

Notes on FreeMarker 2.x Evolution

One could say that the original interface-based design of FreeMarker 1 was a very purist approach to the problem. In that original design, the programmer would expose specialized view objects to the template, any objects that implemented one (or more) of the TemplateXXXModel interfaces. For example, if you had:

${foo.bar}

in your template, the object corresponding to foo would have to be an instance of TemplateHashModel, an interface with one method:

TemplateModel get(String key);

In turn, for ${foo.bar} to be displayed, the assumption was that foo.get("bar") would return an instance of TemplateScalarModel, which was also an interface with a single method:

String getAsString();

So, the practical implication of this is that if I had an object from my business logic and I wanted to expose it directly to the template as a string, like:

${myAccount}

in this case, the underlying object would have to implement TemplateScalarModel and I would need to manually add the getAsString() method, like so:

public class MyAccount... implements TemplateScalarModel {
   public String getAsString() {
    ....
       return whatever_result;
   }
}

That was the original design and it did have a certain conceptual coherence about it. However, it was, in many ways, less comfortable to use than the reflection-based approach taken by WebMacro and the very similar Velocity template library from Apache Software Foundation. If you used either of those libraries, you could drop a plain old java object (POJO for short) into the context and the template could access its public methods or properties. (In Java, the so-called "properties" were really just methods that followed a certain getXXX/setXXX naming pattern for the most part. Thus foo.bar was taken to mean foo.getBar()).

On the one hand, the approach taken by the original FreeMarker design was more inherently secure than simply exposing all the methods on objects by default. And it probably did foster a greater "separation of concerns", since methods that existed to expose data to the "view" were clearly identifiable as such. However, it was also more cumbersome since it required more ceremony or scaffolding. In any case, FreeMarker, from 2.1 onwards, offered similar functionality to expose POJOs. You could just drop a POJO into the template's context and the methods/properties would be exposed. However, this was achieved under-the-hood by creating adapter or wrapper objects that actually implemented the core TemplateXXXModel interfaces. (Note, though, that the number of core interfaces grew over time, since we introduced TemplateNumberModel, TemplateBooleanModel, TemplateDateModel, TemplateMethodModel and TemplateNodeModel.)

This was implemented by Attila Szegedi, who had already written a separate Expose package (for use with FreeMarker 1.x) that could automatically create TemplateXXXModel wrappers to expose POJOs to the template layer via run-time reflection. In FreeMarker 2, Attila's add-on Expose package was rolled into FreeMarker itself and rechristened the BeansWrapper. In fact, the BeansWrapper was a concrete implication of an ObjectWrapper abstraction, an object that, given a POJO, would create a wrapper or adapter object that implemented one or more of the core TemplateModel APIs. This actually gave power users an extra degree of freedom to control the precise semantics of how objects were exposed to the template layer. (However, truth told, probably this was little used and could also be considered an example of speculative generality.)

In any case, this ObjectWrapper/BeansWrapper construct is basically how FreeMarker continued with the original interface-based design yet offered the same ease of use to application programmers as its competitors, WebMacro and Velocity. (Though, increasingly, FreeMarker's main competitor in the templating space was the latter, which had a very big visibility advantage over the former.)

FreeMarker and its Competitors

Certainly, within maybe half a year of my first appearance in the FreeMarker community in late 2001, I (revusky) had basically taken control of the project. I reckon that by mid-2002, the FreeMarker codebase did not have a single line from the original FreeMarker 1. Even the core TemplateXXXModel interfaces were substantially refactored.

Thus, I was project lead and pretty much free to impose my own vision (or obsessions...). One of the things that had always bothered me very much about the original FreeMarker was its extremely lax approch to error handling/reporting. For example, the original FreeMarker would just interpret any undefined variable as an empty string. In fact, the original FreeMarker seemed to go to outrageous lengths to avoid reporting errors. I guess some people think that it is better to show the user a page of any sort rather than an error message. I was (and am) quite certain that this is a very misguided notion. For example, if you wrote:

<list nonList as item>
  ...
</list>

rather than simply telling you that the variable nonList is not a list so you can't iterate over it, it would interpret this as a singleton list with a single item, itself. If the variable was not even defined at all, it would just be taken to be an empty list. That is just one example of how things that were bound to be logical errors in the code were just swept like dirt under the carpet. In FreeMarker 2, if you tried to iterate over something that was not a list, it would tell you that this was not a list. And, at least as importantly, it would point to the exact place in your template that the error occurred.

It actually turned out that FreeMarker's approach to errors was quite possibly the biggest single factor that caused people to switch from Velocity to FreeMarker. In early 2006, Max Andersen, the project lead of Hibernate Tools, wrote a blog post detailing why he switched from Velocity to FreeMarker in his own work, and error reporting was by far the most important reason given. That blog post is still up. See: https://in.relation.to/2006/02/03/a-story-about-free-marker-and-velocity/

Internationalization, Correct Display of Numbers, Currency, Dates...

One fascinating thing about both WebMacro and Velocity is that they had no handling of decimal numbers at all. In fact, notoriously, if you wrote:

#set ($x = 5)
${x/2}

the output would be not be 2.5, but simply 2. FreeMarker, on the other hand, (from 2.x onwards, of course) would display the correct value, 2.5, but if the template was associated with a locale where the comma is the decimal separator, it would display, of course, 2,5.

It simply seemed to me that, since all of the information about how to display numbers, dates, and currencies in the appropriate locales was built into the JDK, it would be utterly ridiculous for a tool of this nature not to leverage that. I believe this is contributed to FreeMarker becoming such a famous, standard sort of tool in China. (I only became aware of how popular FreeMarker was in China in 2011, when I visited and actually talked to some developers there.)

So, aside from my determination to make FreeMarker more fail-fast and report errors in as detailed a manner as possible, I was quite obsessed, from the very start, with having the tool handle the pesky internationalization issues transparently out-of-the-box.

I think that one can also say that, by the time I had had my grubby hands on the thing for a year or more, FreeMarker was about the only tool in its space to really have the dispositions for engineering robust large systems -- not only error reporting, but also the whole concept of importing sets of macros (libraries) into their own namespaces. For this reason, FreeMarker would be the obvious choice over the comparatively primitive Velocity for people writing Web frameworks.

That said, in retrospect, it certainly took a good long time to overcome the branding/visibility advantage of our biggest direct competitor, Apache Velocity. I think the aforementioned article by Max Andersen from early 2006 may have marked a sort of inflection point. But that was over 4 years after I picked up the project, and certainly, for most of that period, FreeMarker was overwhelmingly superior; it was not even close!

FreeMarker Documentation

It was in May of 2002 that Daniel Dekany joined the project and he did make a push to improve the situation with respect to documentation. I first made Daniel Dekany's acquaintance on the Velocity mailing list. I was present there a fair bit in the 2002-2003 period. Whenever anybody would bring up some problem in Velocity -- very frequently it was the complete lack of handling of decimal numbers but sometimes other things -- I would point out that the feature already existed in FreeMarker. On occasion, the desired feature did not exist in FreeMarker either, but I would quickly implement it and tell people that it was there. It was a rather comical situation because the reaction of the "community" there was invariably to get angry at me, never to actually address the problem. Never.

The lead developer of Velocity at that time, one Geir Magnusson Jr., like the rest of the people there, seemed to genuinely believe that people should saddle themselves with an utterly inferior tool because... -- I don't honestly know why, come to think of it. I guess it has some relationship with fan-boy-ism in sports. People will support their chosen team, even if it is a lousy team that will always be at the bottom of the league. (Though that is not quite the same thing since supporting a weak sports team is not the same as knowingly putting an inferior tool in your tool stack...) But this is something that I noticed in various other communities as well, this lack of any concept of the state of the art in a space. The idea that they were supposed to offer something broadly competitive was basically alien to them. This is also quite noticeable, for example, in the legacy JavaCC community and its various fanboy acolytes.

When I met Daniel, he was on the Velocity list being very vocal and bringing up entirely valid points about the tool's (Velocity's) flaws. I dropped him a note telling him that he should join our community, where there was a pretty good chance that if he had a valid suggestion, we would implement it! In retrospect, it was already quite obvious that, by May 2022, Velocity was already kind of a Nothingburger -- though apparently, the project had only been in existence for about two years, created originally as a kind of me-too copycat version of the aforementioned Webmacro. In a Nothingburger project, the ostensible maintainers will typically expend a lot of energy explaining why there is no need to remedy the various deficiencies (even outright bugs) in their product.

Daniel Dekany was (and still is, I think) a very abrasive individual and I definitely recall that Attila Szegedi wrote me a note in private warning me that this guy could be very annoying. Coincidentally (and it really seems to just be a coincidence) both Attila Szegedi and Daniel Dekany are Hungarians.

Now, I have been involved with open source software projects for some time -- mostly FreeMarker originally, but now my main interest is CongoCC -- and I can certainly say that it is rare that anybody really shows up with any gumption to do any serious work on a project. So I was delighted that Daniel Dekany bit off the task of working up a serious manual for FreeMarker, and he did a good job. I think that having a serious manual, well organized with a table of contents and index, was also a significant factor that helped FreeMarker achieve widespread acceptance.

Tracing back, my own intense involvement with FreeMarker started at the end of 2001, and I guess you could say I was obsessed with it in 2002 and 2003. It is not so easy to put myself back in the mind-set of that time. I did have the desire to turn FreeMarker into a sort of standard thing and maybe I thought (very vaguely) that this would turn into some sort of business model, but it never did. I guess you could say that I set myself a certain task, kind of like Sir Edmund Hillary climbing Everest, and finally, I did it because it was there.

After the "Big Push"

So, as I say, there was approximately two years of intense activity which resulted in the main feature set of FreeMarker. In fact, the version of FreeMarker currently labeled as "Apache FreeMarker" does not have hardly any meaningful functionality beyond what FreeMarker (not from Apache) had 20 years ago.

We could call that intense activity on FreeMarker 2, mostly in the 2002/2003 period, "the Big Push". After the "Big Push", activity on FreeMarker was considerably less intense. One benefit of that is that it did become much more stable from the point of view of the end user.

Actually, in terms of the big push, a picture tells a thousand words, and you can see this on this page. Just look at the activity levels of the freemarker-devel mailing list in the successive years 2002, 2003, 2004.

After the "Big Push", I was (perhaps understandably) somewhat burned out and was not nearly as active in the project as before. In fact, for some periods, I was so inactive that it might have seemed like I had left the project.

In terms of the main design goals of FreeMarker 2.x, they had basically been achieved. In retrospect, the next major iteration of development should have been labeled FreeMarker 3 -- though I believe, at that time, we mostly referred to it as 2.4.

During the big push period, FreeMarker went through 4 major release cycles, 2.0, 2.1, 2.2, and 2.3. (The first 2.3 release marked as stable, i.e. not as pre or RC, was in mid-2004, but we were actually very conservative in terms of marking a release as stable.)

If you look on the Apache FreeMarker page, you can see that the latest release of "Apache FreeMarker" is 2.3.33. In short, the FreeMarker project went through 4 release cycles during the big push period and then, after that, for over 20 years, never had another significant release. Incremental improvements, granted, but nothing very major.

Why is that?

The Roots of Later Dysfunction

From a certain point in FreeMarker development, we tried to have the trappings of a major-league corporate sort of project. We typically had a "stable" branch and a "development" branch. So, in principle, if we were working on putting out 2.3, and the new releases were labeled as previews, like 2.3pre4 or something like that, then there was the "stable" branch which was the 2.2 branch. This is admittedly very typical practice in project management. All of that is not, in and of itself a bad idea but...

Well, one problem with all that is that FreeMarker was never a project with the scale or the manpower such that these formalities, like the stable vs. the development branch, really made that much sense. After all, the "big push" was mostly just a one-man show, me getting very obsessed with turning this thing into a best-of-breed tool. There was only one other person who ever did meaningful amounts of work on the code, Attila Szegedi. The participation of the other Hungarian, Daniel Dekany, was really entirely on the documentation, though he also took ownership of other ancillary things, becoming our "release manager", as it were.

In retrospect, all of these project management formalities, the "stable" vs. "development" branches in particular, actually were central in the project becoming utterly dysfunctional over the following years.

I looked back and discovered that I was the one who originally created the "stable" branch for bug-fixes. However, I am quite certain that I never (or just about never) did any work on anything but the trunk of the repository. (That is the branch that is called "master" or nowadays "main" in Git.)

At some point, my only real collaborator on the code, Attila Szegedi, decided that he was going to work exclusively on the "stable" branch. He even took it upon himself to backport new features that I had implemented (in one of my occasional bursts of activity) in the trunk to the stable branch. Now, this is actually a very bad thing to do. New features in the development branch should most definitely not be backported like that. The reason is that, if somebody finds the new feature appealing and wants to use it, they should have to use the more cutting-edge code because that is precisely how the newer codebase gets widely tested!

Moreover, why should an end user use the version labeled as less stable if the "stable" version is going to have whatever new features in short order? Really, it has to be understood that the choice of using the "stable" version entails not getting any new features! If you want the sexy new features being discussed on the dev list, you have to use the "development" version of the code. That really should be understood, at least IMHO.

The other paradox of the backporting is that if you are implementing new features in the "stable" branch, on what grounds is this branch any more stable than the development branch anyway? (In fact, I don't believe that the so-called "stable" branch typically was more robust than the code in the development branch!) But, really, aside from all that, there is just the issue of the waste of manpower. Somehow, we entered into a modus operandi where I would implement some new feature in the trunk and then Szegedi would backport the new feature to the "stable" branch. (That is assuming that the new feature was relatively easy to backport. There was new functionality in the trunk that never was backported because it wasn't really possible to do so.)

Well, in essence, the two Hungarians -- and I am not going to use the loaded word "conspire" or "conspiracy" because I don't think it was that -- managed to create this kind of fiction or alternate reality that we really had two branches of development that could be worked on. I recall Szgedi huffily announcing that he would only be working on the "stable branch". At this point, looking back, I marvel at my relative passivity in terms of reacting to that.

I don't know exactly how to put this. I do not believe that this was deliberate, conscious sabotage on Szegedi's part -- though it was fundamentally stupid and pointless and had a significant amount of (probably unconcious) passive aggression about it. However, when I look at the behavior of the other Hungarian, Daniel Dekany, in the post-big-push period, I now see that he was deliberately sabotaging me. (I probably realized this at the time, on some level, but was somehow suppressing it.) Probably the main reason that we never got the 2.4 release cycle going was because Dekany all but refused to put out releases. Well, he would put out regular releases based on the 2.3 maintenance branch, but not the trunk of the code. I didn't put out the releases myself because somehow Daniel had taken ownership of the process; he had worked up some 1000-line ant script that automated the releases that I really didn't understand and I was counting on him to put out the releases.

There was, of course, no valid reason not to just keep putting out new releases based on the trunk, and whatever "stable" branch should only have been used to fix show-stopping bugs that came to our attention -- assuming any did... Eventually, we would simply label the 2.4 releases as stable and also, they would tend to have enough attractive new features that many +people would want to use the 2.4, even if it was marked preview, rather than the older 2.3. In fact, this is how things had worked in all the previous release cycles but that whole virtuous cycle came to a stop for 2.4.

However, all that said, I would have to admit that the central problem in all of this was me -- I mean my own passivity in the face of all of this. Certainly, in retrospect, there should have been an ultimatum from me to the two Hungarians: stop ****ing around. To Dekany: put out new releases regularly based on the SVN trunk. To Szegedi: stop all this screwing around with the bug-fix branch, either work alongside me in the trunk or leave the project. I mean, if he really wanted to have his own branch of development to work on, he could fork off his own version of the project and work on that. That would be crazy, of course, but the open-source license permits this. But this bizarre pretense that we really had two branches of development and he could choose which one to work on should really have been nipped in the bud.

In any case, it bears repeating: we simply did not have the manpower to be doing this! And, moreover, this whole constructed fiction (I consider it a fiction!) that we really had two branches of development ended up being at the root of the dysfunctional mess that FreeMarker later became. Here is an example:

In early 2008, I made the acquaintance of Angelo Zerr, who is now at Red Hat, who was quite interested in developing tooling for FreeMarker, an eclipse plugin and maybe other things. The FreeMarker 2.3.x codebase was not really tool-friendly, since that had not been the main emphasis during the "big push" period. Thus, much of the focus of my work on the SVN trunk (ostensibly FreeMarker 2.4.x) was to make it much easier for tool writers such as Angelo to support FreeMarker. One thing was that there was an API for walking a template's syntax tree and a tool writer could even add a custom post-parsing tree-walking step. (That API is no longer there in FreeMarker 3, since the FreeMarker3 parser is built using CongoCC and has a similar tree-walking API for free.)

Apparently, Daniel Dekany told Angelo not to build on top of the SVN trunk, but on top of the 2.3 branch. Daniel said apparently that he doubted that the FreeMarker 2.4 would ever see the light of day! So, somehow, this alternate reality had shifted to a new level! Apparently, the 2.3 maintenance branch was the trunk of development and the actual trunk was... well... trash to be eventually thrown away. And it was eventually thrown away. When Daniel Dekany took the FreeMarker code over to Apache in 2014 and labeled it as "Apache FreeMarker" he took the 2.3 codebase, not the more advanced codebase that was the trunk. He also apparently assured the Apache people that I was no longer involved in the project. (At that point in time, I had not really been involved in the project for a number of years, but I had never explicitly said that I would never come back to it.) In fact, it now seems clear in retrospect that Dekany had decided, in his own mind, that FreeMarker was his, and he could shut me out of the project if he so chose. And again, this whole maneuver of representing that the "stable branch" was the trunk was central in all that.

FreeMarker 3 (continuation of the trunk outside of Apache)

Aside from general historical interest, I have felt it necessary to outline all of the foregoing so that people can understand that my behavior in all of this is actually quite reasonable. (Well, I think so...) If it was decided to base Apache FreeMarker on the FreeMarker 2.3 codebase and thus ignore all the work done after 2005 (or certainly 2006) in the SVN trunk, it is perfectly reasonable for me to pick up that abandoned codebase, that was meant to be a 2.4, and continue work on it myself. In other words, for me to continue working on a codebase that is (a) mostly my work and (b) they never laid claim to...

Now, to get back to the history of all this, from 2008 onwards, this becomes intertwined with my attempt to get involved with the JavaCC project. Well, initially, I attempted to get involved in the existing project, but eventually I had to fork off my own project, which I labeled "FreeCC". The history of this is outlined in greater detail here. One of the main improvements that FreeCC brought to the table was that, rather than generate Java code via out.println() statements, FreeCC used templates. Yes, FreeMarker templates, to output code. However, quite obviously, the FreeMarker that FreeCC (later relabeled as JavaCC21 and now CongoCC) used was the more advanced FreeMarker built from the SVN trunk.

After picking up my JavaCC fork again (I had drifted away in early 2009) at the very end of 2019, I did have cause to tweak the FreeMarker code here and there -- again, we're talking about the SVN trunk that Daniel Dekany threw away -- but also I made adjustments to the FreeMarker code that tracked changes in the CongoCC parser generator. You see, CongoCC and FreeMarker3 have an intertwined relationship in that they are mutual dependencies of one another: CongoCC is used to build FreeMarker3 and FreeMarker3 is basically a component of CongoCC, used to output code from templates. Typically, the very latest CongoCC is built using the very latest FreeMarker3 and the very latest FreeMarker3 is built using the very latest CongoCC. That all of the rebuilding and retesting works with the latest codebases of the respective projects is actually just about the biggest integrated functional tests of the entire system!

Finally, there was enough of an accumulated itch to scratch, as it were, and in summer/autumn of 2023, I made a mini-big-push and did a major overhaul of the FreeMarker3 code. And the various improvements are outlined on the FreeMarker3 wiki on Github. The accumulated improvements are significant enough that I finally felt that it would be a pity if nobody else got the benefit of them. Part of the mini-big-push was that I pretty much got rid of the interface-based-design that originated back in the old days of FreeMarker 1 -- though there are a few vestiges, it is basically gone. Internally, and in the API's it exposes, FreeMarker3 uses POJOs basically. The way you would specify that an object can be iterated over is by having it implement java.lang.Iterable, and so on. This overhaul had some striking benefits. For example, Szegedi's BeansWrapper code is now gone. That was well over 10,000 lines of code and what replaces it is maybe about 500 lines total.

Certain of the "new" features in FreeMarker3 features are not really new. For example, the strict variables syntax was already implemented in the trunk in SVN by 2008 (or maybe even 2007.) In fact, on the Apache FreeMarker roadmap for an eventual (probably never) FreeMarker3, you can see towards the bottom of this page:

Replace #assign/#global/#local with #var/#set. Allow block-scope variables. [Status: Not done]

Yes, a feature that was already implemented in the repository's trunk (pre-Apache) 16 years ago! So, Dear Reader, if you think that I (revusky) am such a villain for finally putting out a FreeMarker version that makes such functionality available for the end user, well, what can I say?

Final Remarks

The only version of FreeMarker that has any real future development-wise is the one under my control hosted here. The version of FreeMarker known as "Apache FreeMarker" is not only quite a bit more backward, but there is no serious prospect of any meaningful progress being made with it. That said, it is perfectly understandable that existing projects that use "Apache FreeMarker" will just continue to to use that. However, I would say that anybody starting a new project using FreeMarker would be better off using the newer FreeMarker3.

Now, let me be clear that there is no guarantee of all that much forward movement from this point even in FreeMarker3. It is not my main interest in terms of open source development. My main interest is the aforementioned CongoCC parser generator and, in fact, the main reason I ended up turning my attention to FreeMarker again was its relationship with CongoCC. Actually, that is a dual relationship, since FreeMarker3 is used internally by CongoCC to generate code in Java, Python, and C#. However, FreeMarker3 is also built using CongoCC and thus provides the best single large-scale example of CongoCC usage for people to study.

Well, to be clear, there is not much prospect of another "big push" in FreeMarker3 from my end. I am, however, the project's maintainer and I take that role seriously in terms of attending to bug reports and such. Any bug reported will typically be squashed immediately. I think it can be said that this is typical of any project in which I am active! That said, my real wish would be for other people to eventually assume ownership of the project. And, in that case, I would still be around, but mostly take a relatively hands-off approach -- unless people were doing something really barbaric that I totally disagreed with, in which case...

At this exact moment of writing (July 2024), I do feel that some advocacy effort is necessary, so I intend to be in touch with various communities that still make extensive use of the older FreeMarker and tell them that this is available. And we'll see what happens.

Clone this wiki locally