Monday, September 24, 2012

Sublime Text Editor tricks for web developers


Last weekend we were at Apache Barcamp Spain with a talk about cool tools for web developers.

Aside: if you are coming to a single event in Spain on a given year, make it this one. Barcamp Spain has developed its own soul, where the beer+networking experience is so much fun, and the food by itself is totally worth the trip.

Some people were asking for a transcript of the third part, our own set of tips and tricks to boost Sublime Text Editor for web development. So here it comes:

Feel comfortable

Chances are Sublime Text Editor is not your first editor. You probably had a previous life, in which you were already proficient with some editor (Eclipse, Bean, TextMate, whatever). This is about getting things done, so I would recommend to configure Sublime with the typical shortcuts that are hard-coded into your brain. Me, I am used to Eclipse shortcuts.

The idea is to feel comfortable. Get whatever you need to make Sublime as good as your previous editor of choice. Now, awesomeness can start.

Maximize space

I am not quite a fan of the distraction-free mode in Sublime, but I do want to maximize the used space on screen (the data-ink ratio, for Tufte fans). So here it goes:
  • Toggle sidebar on/off: Ctrl + K, Ctrl + B. This is useful if you rarely use it. In my case, it's Shift+Ctrl+R to open any file, which makes the sidebar mostly ignored.
  • See several files at once: Shift + Alt + [1234589] (you have to choose one). You can compare them side by side, top vs bottom, etc. Once you are done, you can switch back with Shift+Alt+1.



Surround with tag: Shift+Alt+W

This is a useful shortcut for inline tags (bold, italics, links), but not so much for block tags (div, p, etc). Try it:
  • Write any text.
  • Select a word, press Shift+Alt+W, then type b.


Block select: Shift + Right-click drag

This is great when you need to insert tags at the start of each line (p, li).
  • Prepare your list of data
  • Select the code and hit Tab to indent it a bit.
  • While holding the Shift key, right click and drag to select a rectangular selection of code.
  • Now type the start tag to get it inserted at the beginning of each line.




Multiple cursors

The previous are just concrete examples of using multiple cursors. For the purpose of understanding, let's say you can have multiple instances of a SublimeCursor class (I do not have any insight of the source code, but I found this approach easier to understand). This is a compiled list of things you can do, extracted by trial and error:
  • Ctrl + click: create new cursor.
  • Ctrl + double click: create a new cursor selecting the word that was double-clicked.
  • Shift + click: select using the latest cursor (so: ctrl + click, then shift + click to add a selection to the set of cursors)
  • Any keyboard action: Operate on all cursors at once. Keyboard operations (like Ctrl+V) will work, and so will normal typing (like hitting <end> to write the ending tag at the end of each line).
This is best understood with a set of examples:
  • Write any text.
  • Ctrl+click at the beginning of each line.
  • Write <p> or <li>




Forgot to enclose tag attributes with quotes?
  • Ctrl + double click on every attribute
  • Type "



  • Ctrl + double click on words that you want to make bold. 
  • If you want to select more than one, Ctrl+Click at the beginning, then Shift+Click at the end.
  • Hit Shift + Alt + W, then type b





There are tons of possible applications, and we found ourselves doing some really funky stuff. What is your personal trick? Use the comments section or tweet me @nachocoloma.

Monday, June 11, 2012

Using LiveReload on Linux

This is a guest entry from José Roberto Vidal, our newest acquisition at Extrema Sistemas. It's a perfect combination between me, not having enough time to write something coherent, and Roberto having something interesting to say and nowhere to stick it on. You can also find a Spanish version here.

LiveReload is an application that allows you to refresh automatically your browser whenever any file gets modified, even compiling any Sass / Less / CoffeeScript files. In a nutshell, it avoids you the tedious-to-death Alt+Tab F5.

Its installation in Mac OS or Windows is quite straightforward, but things get a bit trickier with Linux (surprise, surprise). This is what this post is about.

Installation and configuration

Leave the usual sacrifice of blood and caffeine by the side table. Thank you

Where Ruby gems get involved:

sudo apt-get install ruby1.9.1 ruby1.9.1-dev

Now you can use RubyGems to get the application. Inside your project folder, do:

sudo gem install bundle
sudo gem install guard
sudo gem install guard-livereload
bundle init

Edit the recently created Gemfile and add these two lines:

gem 'guard'
gem 'guard-livereload'

And execute

bundle exec guard init livereload

Monitored files and browser extension

Your generated Guardfile includes some predefined monitoring folders that you may have to modify if yours is not a Rails project. After that, just start the Guard server:

$ bundle exec guard
Guard uses NotifySend to send notifications.
Guard is now watching at '/home/me/workspace/project'
LiveReload 1.6 is waiting for a browser to connect.
> 

At this point you probably can't wait to crack your knuckles and give it a try... Download the LiveReload extension for your browser (Chrome, Firefox) and configure it (right click -> options) to specify the hostname and port used by the Guard server (by default localhost:35729).

Once enabled, the guard-livereload server will notice it:

> Browser connected.
Browser URL: http://mymachine:myport/

Disco!

If you get here, any modification to monitored files (CSS stylesheets, images, even JavaScript files) is noticed and applied immediately at the browser without refreshing.

Guard comes whith a lot of different flavors to automatize tasks in different environments. Get your own, or follow their nice screencast.

More

This is one of the labs that you can find in our HTML5+CSS3 course, together with Bootstrap, Sass and another 25 labs. It's just three days that you may choose to come to one of our public scheduled dates or make one specific for your own company.

Friday, October 28, 2011

Eclipse shortcuts for Sublime Text 2

I am a Linux guy. I used to pimp gedit with all plugins under the sun in an effort to transform it into TextMate, but no matter what I try it keeps being an awkward coding experience. Still on the search for alternatives, last month I discovered Sublime Text 2 and its entire new way of understanding text editing.

Sublime Text is just perfect for lightweight coding. I am not going to get into the details, since there are better places documenting this (see for example this list of tips and tricks). It is the perfect tool for times where a full-blown IDE is overkill: after all, it makes little sense to open Eclipse if you are going to spend the next eight hours debugging JavaScript or HTML (Agile and all that).
Now, this is the thing: I work with multiple major projects in the same week, performing different tasks and roles. I switch environments A LOT. Having to think "where am I editing?" before duplicating lines or saving files was messing into my flow.
So, without further ado, behold the

Ultimate eclipse shortcuts for Sublime Text 2

Not exactly rocket science, but still: go to Preferences -> Key bindings - User and paste this:

[
 { "keys": ["shift+enter"], "command": "run_macro_file", "args": {"file": "Packages/Default/Add Line.sublime-macro"} },
 { "keys": ["alt+up"], "command": "swap_line_up" },
 { "keys": ["alt+down"], "command": "swap_line_down" },
 { "keys": ["ctrl+alt+j"], "command": "join_lines" },
 { "keys": ["ctrl+alt+down"], "command": "duplicate_line" },
 { "keys": ["shift+ctrl+r"], "command": "show_overlay", "args": {"overlay": "goto", "show_files": true} },
 { "keys": ["ctrl+shift+s"], "command": "save_all" },
 { "keys": ["ctrl+l"], "command": "show_overlay", "args": {"overlay": "goto", "text": ":"} },
 { "keys": ["shift+ctrl+f4"], "command": "close_all" },
 { "keys": ["shift+ctrl+y"], "command": "lower_case" },
 { "keys": ["shift+ctrl+x"], "command": "upper_case" },
 { "keys": ["ctrl+d"], "command": "run_macro_file", "args": {"file": "Packages/Default/Delete Line.sublime-macro"} }
]

Save, and you will have a selection of finest eclipse shortcuts configured right into your editor. It is as far as I could get without getting into macros. You can help yourself and find the complete list of commands under Preferences -> Key bindings - Global, and complement this with our own discoveries.
If you like this, do not miss our new post about Sublime Text Editor tips for Web Developers.

Thursday, October 13, 2011

Apache Barcamp Spain: a wrap-up

After ten years of IT events, one would think that I have already seen everything under the sun: Spain, Germany, Switzerland, Flanders, Java-related or not, we all end up doing similar things. Come, learn something, attend networking, maybe get some book signed by some mega-crack author with a funny name. Exchange business cards or LinkedIn ids or Twitter names or QR codes. That's it.

Then something like Apache Barcamp Spain gets together and it's like - WOW.

If I had to coin some term, it would be "beer-oriented event". This being my first barcamp, I must say that the format is a fresh and new perspective much more interesting that the typical "get together and talk" mumble-jumble.

The talks

First off, you don't know what you are getting into. Literally. You make the trip to Seville, which in our case means getting three people into the A-Team van to co-star a 500+ km of roadtrip movie. You do all that, yet you don't know the talks that will happen the day after. Everyone proposes a talk and a voting process happens, and for all you know you could end-up learning new, surprising flavors of freaky.

Fortunately this was not the case: from Play! framework to GIS, Agile, Maven, Groovy, Web or Mobile, the landscape was full of well-seasoned experts. I loved the talks, but also the pace: instead of the typical 45-minute sessions, these were shortened up to 30 which leaves just the time to get to the point. No fluff, no fillers, just beans.

With three parallel tracks, you know you will miss 66% of the talks. I know I did, and some great talks are not included here. Sorry for that.

The following is my contribution about CSS. Bear in mind that these are introductory talks, but I tried to make them fun and throw something in for the most experienced.

The people

CELEBRITIES. All of them. Hey, we got a T-shirt to prove it.

Seriously, the organization made a big effort to make it clear that this show was about the people. I mean, of course all events do, but here you could really feel the love. Beer-time was the required great excuse to meet great people, and I found this to be one of the best formulas to get in touch. Relaxed and natural, like friends at a party.

Pity that we were just 100 people. I know quite a crowd that was left out because of the limited capacity.

The party

This event was co-sponsored by several companies, Extrema between them, but one company really stood out: Atlassian.

Atlassian sponsored the closing party, and a huge one at that. Flamenco, beers, jamón serrano, mojitos when the time was right. It was exactly the kind of party I would ask of Seville.

Funny fact of the night: After one hour of animated chat, I ended up recognizing Carlos Sanchez because of the avatar in his business card. Avatares reales ya :)

Thursday, September 22, 2011

Style your forms using JavaScript or CSS

These days we are hacking like crazy in CSS land, trying to introduce in our project some nice memories from our Java background like Not Reinventing The Wheel or avoiding the NIH syndrome. Which brings us to this little nice thought:

I don't want to style buttons EVER AGAIN.


I simply have some better things to do. Call it "button", "a.button", "input[type=submit]", I don't care. I just want them to look gorgeous, be as lightweight as possible, and look the same in all browsers. Since it's 2011, I will get all cocky and also want them to be free.

Since we are at it, let's take a look at how to style form controls, period.

Style your widgets using JavaScript


Aristo is a great theme for jQuery UI that includes some great styles for everything under the jQuery sun, which includes buttons of several kinds. It's really great if your needs are not that simple (complex layouts with something clever like sliders or datepickers).
The only problem is that it relies on jQuery to initialize the correct Look & Feel artifacts, which means that during the first access to your web page there are a couple of seconds of my patented YourButtonsLookLikeCrap (tm) effect. There are plenty of workarounds for this, like creating the whole button markup using javascript.

If you need something less heavy there is a project to get Aristo buttons using just CSS, but it's still too green. Better go with skeleton.

Style your controls using just CSS


Skeleton is an extension over the 960 grid system. They extend the grid concept by adding extra typography and media queries oriented to mobile, and it absolutely excels at providing lightweight form controls. It's likely that it will not fit perfectly into your own design, but the stylesheet is really easy to understand and you can tune it to your needs. It's also extremely lightweight, in case that's a concern.

Style your select controls


You know those huge combo boxes that happen every now and then, when reality hits your application? With Chosen you can replace them transparently:
They have plenty of examples of controls, including ways to provide for your Ajax needs.

I know there must be other exciting tools out there that I am missing. How do you make your forms rock? Please share!

Aside: These be Crazy Months


I just came back from spending my whole summer in Beijing. It was an incredible experience that I am absolutely planning to repeat in February, this time with Shanghai. So far I now just the survival basics like "hello", "thanks", "chicken" and "tea". With that (and smiling a lot) you can survive a whole month and get a grip of the culture, which by the way is quite impressive. I also managed to save some time to learn chinese chess, and I can proudly say that I'm absolutely lame at it.

 Now I just got back to Spain! Next month I'll be at Apache BarCamp Spain with a CSS for non-designers and CSS3 101 talks, hope to see you there to share some beers and plenty of chinese stories.

Tuesday, May 24, 2011

Firefox 4 and 3.6 at the same time

With the arrival of HTML5 web development has turned into the sunny side of the hill again. These days the world would be a perfect place if I could launch two browser instances at the same time, one with support for the latest standards (almost) and another without.

This is something that has been documented online, but from fragmented sources: it is possible to have Firefox 3.X and 4 installed and running at the same time. Actually, it's quite simple as the whole installation process takes less than ten minutes.


Step one: Installing the thing


This one is a no-brainer: you should install both Firefox 3.6 and 4 in separate folders. For Windows, this means using different folders and creating separate shortcut icons.




For Linux, it means installing Firefox 4 from your favorite package manager (.rpm or .deb) and downloading Firefox 3.6 as .tar.gz and uncompressing it somewhere like /usr/local/firefox3.6 (depending on your Linux version, you may prefer to do it the other way around).

In both cases, you need the link to download an older version of Firefox, which is somehow hidden in their website (search for "All systems and languages" and "Other Firefox Downloads", or just click here).

Step two: add -no-remote


Firefox will check at launch time if there is a running instance and attach to it instead of starting a new one, which is definitely not what we want since it will not check for versions in the process. Launching 3.6 will result in your existing Firefox 4.0 window getting the focus, but nothing else. No new window. No "ta-daaaa!"

This behavior can be overriden by adding -no-remote to your program shortcuts (Windows or Linux). That will skip the check, and your new window will open.

Step three: use different profiles


You may be able at this point to launch separate windows for Firefox 3.6 and 4 at the same time, but this is no good if they start stepping on the plugins of each other. The plugin release that may be valid for 3.6 is not for 4, and viceversa (fact is, anything other than Firebug has big chances of not having been ported to Firefox 4 yet). You need separate plugin folders.

The good news is that your plugins are stored in a folder relative to your Firefox profile. Most users (99.9% or so) have a single "default" profile that is selected automatically and are not aware about profiles (now you are; lucky you!). Just launch:

firefox -ProfileManager



Create two separate profiles, which will allow for two separate sets of plugins. I like to name them "Firefox 3.6" and "Firefox 4", in an attempt to be original and unexpected. They will be stored inside your user home folder. Accept and close the window.

To avoid the profile selection window over and over again, the profile can be set at your Firefox launcher (or shortcut icon, if you are using Windows). I will assume some locations and profile names here:

Linux
/usr/bin/firefox -no-remote -P "Firefox 4"
/usr/local/firefox3.6/firefox -no-remote -P "Firefox 3.6"

Windows:
"C:\Program Files\Firefox 4.0\firefox" -no-remote -P "Firefox 4"
"C:\Program Files\Firefox 3.6\firefox" -no-remote -P "Firefox 3.6"

That's it. Now you can develop using both versions with separate Firebug installations.

More. More. More.


This is an excerpt of the first lab in our HTML5 and CSS3 course that is starting tomorrow. This 4-day course includes 20+ labs filled with polyfills, mobile and print CSS, Internet Explorer workarounds, transitions, form controls and mostly everything under the CSS3 / HTML5 sun.

Thursday, February 10, 2011

Applications dealing with multiple timezones

This is a requirement that can hardly be considered common. Most applications are not forced to deal with more than one timezone: intranet applications, nationwide deployments (most European Countries enjoy this great invention that is Central European Time), even air navigation systems place everything in UTC.

We recently deployed Koliseo on AppEngine. This is still a work in progress, where some features have raised interesting questions: what happens when a friend tells you to meet on Friday at 17:15? How should you store this in the database?

Multiple painzones


I love the way computers measure time: milliseconds since 1970. Holy cow. No leap years, no arbitrary seconds-in-a-minute conversion, no Daylight Saving Time and it doesn't matter where you are. Give me a number that I can sort and compare. Computers do not have problems with dates. Humans do.

Then, the only problem is parsing and formatting these dates.

Parse date


Ye olde way of providing time information says that you should put a test field, label it "when" and let the user do his thing. Suppose that he introduces "25 Oct 2010 at 00:00", sitting comfortably in his nice office in Madrid (GMT + 1, where DST applies).

  • What the user means: "25 Oct 2010 at 00:00" in NiceAndWarmOffice@Madrid
  • What the server understood: "25 Oct 2010 at 00:00" in local server time. For AppEngine this is UTC, which means one or two hours less, depending on the season.

The user wanted to express Oct 25 00:00 (Madrid time), but the server understood Oct 24 23:00 (Madrid time). This is the value that will get stored in the database.

You need to ask for the timezone of the user. It can be automatically deduced using javascript (it comes in small and jumbo sizes), but it is nice practice to let the user modify the timezone later, just in case.

This timezone must be stored associated to something, which in our case is a venue. From there on, any date introduced in Koliseo must be associated to this entity. Following this example, any Performance must specify where before telling when if we want to be able to parse the introduced timestamp.

The code to parse is quite straightforward thanks to Saint JodaTime:

DateTimeZone dtz = DateTimeZone.forID(timezoneID);
DateTimeFormatter formatter = DateTimeFormat
 .forPattern("yyyy-MM-dd HH:mm") // replace with your favorite format string
 .withZone(dtz)
 ;
Date date = formatter.parseDateTime(dateAsString).toDate();

Format date


How do you want to display dates to the user?

  • Relative units: This is the best way to display unambiguous dates ("ten minutes ago", "one week ago", etc). This is done in Loom by using l:formatDate, but the first case I can remember of this practice was found in Ruby
  • User time: This is usually not interesting, since a date is associated to something happening (in Koliseo, a performance) and is usually meaningful inside their own context and timezone.
  • Original timezone: This is the most common case. Example: tell me that the show is scheduled at 17:30 (local time of the show, in this case Madrid), not browser time (Helsinki or whatever).

To format dates in the original timezone you can use the same snippet of code just replacing formatter.parse() with format().

Javascript code


Whenever you send or receive a Date from the server, the typical JSON serialization uses "milliseconds from 1970", which can be a problem. This value cannot be used as is because the timezone information is missing. 17:35 in Madrid will be deserialized as 16:35 if I am browsing from London, which is wrong.

Twitter solves this by serializing dates as text, then you can parse and separate the parts to display (day, month, year, weekday). To test your javascript code, just add "-Duser.timezone=UTC" to your server launch script and play a little with your application. If you do not see any date mismatch, everything is good.

Monday, November 01, 2010

Loom 2.2 has been released

We have just released Loom 2.2 with a lot of stuff to make web development easier:

Better javascript/CSS resource bundles


Loom has been supporting javascript and CSS dependencies for some time, and now they just got easier (think sprockets):

JSP file:
<l:css resource="style.css"/>
<l:script resource="main.js"/>

style.css:
/* 
// @include "myfile.css" 
// @include 'classpath:/mypackage/file2.css' 
*/ 

main.js:
// @include "myfile.js" 
// @include 'classpath:/mypackage/file2.js' 

These dependencies can now be redefined without restarting the server. In production environments they will be concatenated, minified and gzipped - which brings us to the next point:

More and better features

Added support for Google Closure Compiler


According to multiple sources Google Closure Compiler produces a better compression rate than YUI Compressor. This is nice, but what really got us is the awesome error reporting which even warns about IE gotchas (trailing commas, anyone?).

Google Closure compiler is now the preferred javascript compressor and will be used if it is present in the classpath. For CSS, YUI compressor is still the (only?) solution.

New Ajax Paged Table


Loom includes some great server-side paged components. With 2.1 we introduced a new Ajax paged list where the whole pagination process was performed by javascript code, and with 2.2 we are extending this to paged tables:

var paged = new loom.ui.PagedTable($('container2'), { 
        url: '<l:url mapping="Action.event" decorator="link-only"/>', 
        columnNames: [ 'timestamp', 'contents', 'user.name', 'user.avatar' ], 
        // optional fields: specify CSS class names and cell renderer
        columnClassNames: ['date'], 
        columnRenderers: [ function(o) { return o.timestamp == null? '' : new Date(o.timestamp); } ] 
  }); 

This is an alternative to server-side paging. Just use the solution that suits you.

Better fluent interfaces


Some interfaces got better at handling HTTP headers and cookies:

// the bad: 
Resolution res = forward() 
   .set("foo", "bar"); 
res.addCookie("baz", "bar"); 
return res; 

// the ugly: 
getResponse().addHeader("baz", "bar"); 
return forward(); 

// the new API:
return forward() 
   .set("foo", bar") 
   .addCookie("baz", "bar") 
   .addHeader("Content-Type", "application/javascript") 
;

CacheControl has also been improved:

// Before: 
CacheControl c = new CacheControl(); 
c.setCacheYears(10); 
c.setLastModified(new Date()); 
return forward().withCacheControl(c); 

// After: 
CacheControl c = new CacheControl()
   .withYears(10)
   .withLastModified(new Date());
return forward().withCacheControl(c);

Others


There is a lot of smaller improvements such as:
Work on the next release (2.3) has already started, including the redesign of some internals to address Google AppEngine development with Guice. It's exciting!

Monday, October 04, 2010

Loom 2.2 is almost out: things we learned so far

I feel guilty talking about a male customer through this post. Actually, in our case he is a she.
We just got out the new e-banking portal for BBVA Suiza. BBVA Suiza is the BBVA Group's International Private Banking unit, one of the most visible projects we had originally developed with Loom 0.8 - now with 2.2 - and a lot has happened since then.

This post is about things we learned during these last years, and how they were combined to make our experience extremely enjoyable.

It's all about the UI


The most interesting discussions during this project were not about technology or banking products, but about the interface. We spent literally hours discussing one single page, trying to fit things in the most natural way, getting all the non-essential out.

Anyone can design an interface that takes two weeks to learn, but it gets much harder to design something intuitive. It takes a lot of work to arrive to your hamburger interface. On the way we have challenged the breadcrumbs location, the tabs metaphor, the nesting of contents, everything.

It's not about stateless or stateful


It's not 1999 anymore. The caveats of stateless and stateful interfaces are well known, and unless you are a zealot of some concrete Church of Thought, your sweet spot will most probably be somewhere in the middle. Free your server resources by moving more to the browser. Remember that sometimes light pages will do better than a super XXL javascript golem. Get faster responses by avoiding a full page refresh. Do not put too much stress on javascript unless you want to spend your life debugging. Hate IE over everything else. Remember your SEO.

The list is long, and you should make your own choices. Just remember not to waste too much time arguing about which way is better.

Speed!


Any idiot can carve lots of features into your application and make it clunky, take years to download, and lose the train of thought of your users in the eternity that happens between one page and the next. If you aim to make your users rock (as you should) your application should feel natural, which means working towards the 1 second goal.

There are lots of tricks to get there. We have posted some here and there, but nothing beats simplicity: there is nothing faster than not including a feature.

Of course, your customer may not always agree. This is were the next point gets relevant.

Get your customer on your same train


You can align your customer with your own goals just by delivering Software That Works, so don't try to agree to all crazy features or deliver the supah-dupah-canvas-based forms with embedded music. It's important to make a distinction between what the user asks and what he needs, and it helps if the rationale behind a refusal is clear and shared by everybody.

So?


We are not there yet. There are things that we would do different and legacy features we would love to drop, but all in all, everyone is happy. Their customers are calling just to send congratulations (how often do you see that), and suddenly we found ourselves talking to another three banks that want to build something similar.

The technology helped a lot. But what really allowed us to deliver was all the weight that was ditched by the way.

Monday, September 13, 2010

SimpleDS 1.0 is released

Gotta love 1.0 releases
This week we are releasing version 1.0 of SimpleDS. SimpleDS is a simple persistence framework for Google AppEngine that provides an alternative to JDO or JPA.

This release brings a lot of new features:

Cached queries


This is the star feature of this release. Starting with 1.0, all query results can be cached. To maximize cache performance only the returned primary keys will be cached, so you still have to use @Cacheable to cache the entity itself.

There are cases were this feature is killer, e.g. to retrieve a User given the email:

User user = entityManager.createQuery(User.class)
  .equal("email", googleUser.getEmail())
  .withCacheSeconds(3600)
  .asSingleResult()
  ;

DEBUG CacheManagerImpl - Level 2 cache hit: qdata{kind=User,pred=[email = test@example.com]}
DEBUG CacheManagerImpl - Level 2 cache hit: User(5)
DEBUG Level1Cache - Level 1 cache hit: User(5)

Cached queries work with FetchOptions (cursors, limit and offset) and support only count(), asSingleEntity(), asList() and asPagedList(). Any invocation to asIterable() / asIterator() will ignore the cache. To clear cached data, just prepare the same query and invoke clearCache().

More about cache here.

Better fluent interfaces


The syntax has been simplified from this (older version):

SimpleQuery query = entityManager.createQuery(User.class).equal("name", "foo");
return entityManager.find(query);

To this:

return entityManager.createQuery(User.class)
  .equal("email", email)
  .equal("enabled", true)
  .sortAsc("email")
  .asList()
  ;

Now we rarely use more than one line for most queries. In this example, if email is null it will just be ignored.

Several methods have been added: asList(), asSingleResult(), asIterator(), asIterable() and PagedQuery.asPagedList(). The old EntityManager methods have been deprecated.

More about queries here.

New Functions


We are also adding some new Functions for transforming persistent entities. Some examples of use:

// save space for your relationships by storing Set instead of Set
Set userIds = user.getFriends();
Collection userKeys = Collections2.transform(userIds, new IdToKeyFunction(User.class));
Collection users = entityManager.get(userKeys);

// transform back
CompositeFunction func = new CompositeFunction(
 new EntityToKeyFunction(User.class), 
 new KeyToIdFunction()
);
user.setFriends(Collections2.transform(users, func));

// just return a collection of email addresses
return Collections2.transform(users, new EntityToPropertyFunction(User.class, "email"));

More about functions and transformations here.

Added JRebel support


I personally use JRebel for development, which means that I rarely restart my development server. This was a problem with SimpleDS, which was unable to detect changes such as new persistent attributes, etc. SimpleDS can now be used with JRebel just by adding this to your startup code:

if (SystemProperty.environment.get().equals("Development"))
   ClassMetadataReloader.register();

Then in eclipse ("Go to your launcher config -> Arguments -> VM Arguments")

-javaagent:/usr/local/java/appengine-java-sdk/lib/agent/appengine-agent.jar -noverify
"-javaagent:${env_var:REBEL_HOME}/jrebel.jar"

Minor changes


  • Added @Property.converter to override the default converter for one persistent property. You can, for example, store a String attribute as Text.
  • Added new methods SimpleQuery.withReadPolicy(ReadPolicy) and SimpleQuery.withDeadline(double)
  • Added new methods SimpleQuery.withStartCursor(Cursor) and SimpleQuery.withEndCursor(Cursor)
  • Cache settings will be ignored when invoked within a transaction.
  • We have moved from commons-logging to slf4j. This may break binary compatibility, but is a huge boost in performance.

Let me get off-topic for a while


Last week this very same blog reached the 400-subscribers mark! It's awesome to find so many people interested, and I find extremely rewarding the contacts I receive every now and then, sometimes just to say hi. Last week it came from Australia! (hey Ángel).

So this is me, taking a small detour to say thanks. And yes, I will try to post more often :))