<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:creativeCommons="http://backend.userland.com/creativeCommonsRssModule">

<channel>
	<title>Objectify</title>
	<atom:link href="http://www.objectify.be/wordpress/?feed=rss2" rel="self" type="application/rss+xml" />
	<link>http://www.objectify.be/wordpress</link>
	<description>vb. Giving reality to...</description>
	<lastBuildDate>Thu, 17 May 2012 11:45:20 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
<creativeCommons:license>http://creativecommons.org/licenses/by-nc/3.0/</creativeCommons:license>		<item>
		<title>Play&#8217;s Build.scala file &#8211; a very subtle gotcha</title>
		<link>http://www.objectify.be/wordpress/?p=475</link>
		<comments>http://www.objectify.be/wordpress/?p=475#comments</comments>
		<pubDate>Thu, 17 May 2012 11:45:20 +0000</pubDate>
		<dc:creator>steve</dc:creator>
				<category><![CDATA[play! framework]]></category>
		<category><![CDATA[gotcha]]></category>
		<category><![CDATA[play!]]></category>

		<guid isPermaLink="false">http://www.objectify.be/wordpress/?p=475</guid>
		<description><![CDATA[Work on the new module repository for Play is progressing nicely, but a very subtle bug was introduced into the Build.scala file. As a result, artifacts from the first repository were not being found. Can you spot the difference here? &#8230;<p class="read-more"><a href="http://www.objectify.be/wordpress/?p=475">Read more &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<div class="dzone_button" style="float: right; margin-left: 10px;">
<script type="text/javascript">
var dzone_url = 'http://www.objectify.be/wordpress/?p=475';
var dzone_title = 'Play&#8217;s Build.scala file &#8211; a very subtle gotcha';
var dzone_blurb = '';
var dzone_style = '1';
</script>
<script language="javascript" src="http://widgets.dzone.com/links/widgets/zoneit.js"></script>
</div><p>Work on the <a href="https://github.com/playframework/modules.playframework.org" target="_blank">new module repository</a> for Play is progressing nicely, but a very subtle bug was introduced into the Build.scala file.  As a result, artifacts from the first repository were not being found.  Can you spot the difference here?  The first code snippet is correct, and the second is faulty.</p>
<pre class="code">
val main = PlayProject(appName, appVersion, appDependencies, mainLang = JAVA).settings (
    resolvers += Resolver.url("Objectify Play Repository", url("http://schaloner.github.com/releases/"))(Resolver.ivyStylePatterns),
    resolvers += Resolver.url("Scala Tools", url("http://scala-tools.org/repo-releases/"))(Resolver.ivyStylePatterns)
  )
</pre>
<pre class="code">
val main = PlayProject(appName, appVersion, appDependencies, mainLang = JAVA).settings {
    resolvers += Resolver.url("Objectify Play Repository", url("http://schaloner.github.com/releases/"))(Resolver.ivyStylePatterns)
    resolvers += Resolver.url("Scala Tools", url("http://scala-tools.org/repo-releases/"))(Resolver.ivyStylePatterns)
  }
</pre>
<p>The problem was caused by using curly brackets instead of parentheses.  Note also that when using curly brackets, you can&#8217;t put a comma after the first resolver.  However, the file still compiles without a problem.  Very subtle, very annoying!</p>
<p>So, the correct form is the first snippet above &#8211; here with bold to emphasise the key points.</p>
<pre class="code">
val main = PlayProject(appName, appVersion, appDependencies, mainLang = JAVA).settings <strong>(</strong>
    resolvers += Resolver.url("Objectify Play Repository", url("http://schaloner.github.com/releases/"))(Resolver.ivyStylePatterns)<strong>,</strong>
    resolvers += Resolver.url("Scala Tools", url("http://scala-tools.org/repo-releases/"))(Resolver.ivyStylePatterns)
  <strong>)</strong>
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.objectify.be/wordpress/?feed=rss2&#038;p=475</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Play 2 &#8211; modules, plugins, what&#8217;s the difference?</title>
		<link>http://www.objectify.be/wordpress/?p=464</link>
		<comments>http://www.objectify.be/wordpress/?p=464#comments</comments>
		<pubDate>Wed, 09 May 2012 09:16:21 +0000</pubDate>
		<dc:creator>steve</dc:creator>
				<category><![CDATA[how to]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[play! framework]]></category>
		<category><![CDATA[Scala]]></category>
		<category><![CDATA[how-to]]></category>
		<category><![CDATA[modules]]></category>
		<category><![CDATA[play!]]></category>
		<category><![CDATA[plugins]]></category>
		<category><![CDATA[scala]]></category>

		<guid isPermaLink="false">http://www.objectify.be/wordpress/?p=464</guid>
		<description><![CDATA[There seems to be some confusion regarding Play 2 modules and plugins. I imagine this is because the two are often synonymous. In Play (both versions &#8211; 1 and 2) there are distinct differences. In this post, I&#8217;m going to &#8230;<p class="read-more"><a href="http://www.objectify.be/wordpress/?p=464">Read more &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<div class="dzone_button" style="float: right; margin-left: 10px;">
<script type="text/javascript">
var dzone_url = 'http://www.objectify.be/wordpress/?p=464';
var dzone_title = 'Play 2 &#8211; modules, plugins, what&#8217;s the difference?';
var dzone_blurb = '';
var dzone_style = '1';
</script>
<script language="javascript" src="http://widgets.dzone.com/links/widgets/zoneit.js"></script>
</div><p>There seems to be some confusion regarding Play 2 modules and plugins. I imagine this is because the two are often synonymous. In Play (both versions &#8211; 1 and 2) there are distinct differences.  In this post, I&#8217;m going to look at what a plugin is, how to implement one in Java and Scala, and how to import plugins from modules.</p>
<h2>Plugins</h2>
<p>A Play 2 plugin is a class that extends the Java class <a href="http://www.playframework.org/documentation/api/2.0.1/java/play/Plugin.html" target="_blank">play.Plugin</a> or has the Scala trait <a href="http://www.playframework.org/documentation/api/2.0.1/scala/index.html#play.api.Plugin" target="_blank">play.api.Plugin</a>.  This class may be something you have written in your own application, or it may be a plugin from a module.</p>
<h3>Writing a plugin in Java</h3>
<p>Create new class, and have it extend play.Plugin.  There are three methods available to override &#8211; onStart(), onStop() and enabled().  You can also add a constructor that takes a <a href="http://www.playframework.org/documentation/api/2.0.1/java/play/Application.html" target="_blank">play.Application</a> argument.</p>
<p>To have some functionality occur when the application starts, override onStart().  To have functionality occur when the application stops, override onStop().  It&#8217;s that simple!  Here&#8217;s an example implementation which doesn&#8217;t override enabled().</p>
<pre class="code">
package be.objectify.example;

import play.Application;
import play.Configuration;
import play.Logger;
import play.Plugin;

/**
 * An example Play 2 plugin written in Java.
 */
public class MyExamplePlugin extends Plugin
{
    private final Application application;

    public MyExamplePlugin(Application application)
    {
        this.application = application;
    }

    @Override
    public void onStart()
    {
        Configuration configuration = application.configuration();
        // you can now access the application.conf settings, including any custom ones you have added
        Logger.info("MyExamplePlugin has started");
    }

    @Override
    public void onStop()
    {
        // you may want to tidy up resources here
        Logger.info("MyExamplePlugin has stopped");
    }
}
</pre>
<h3>Writing a plugin in Scala</h3>
<p>Create a new Scala class, and have it extends play.api.Plugin.  Just as in the Java version, there are onStart(), onStop() and enabled() methods along with an play.api.Application constructor argument.  Here&#8217;s the Scala implementation:</p>
<pre class="code">
package be.objectify.example

import play.api.{Logger, Application, Plugin}

/**
 * An example Play 2 plugin written in Scala.
 */
class MyExamplePlugin(application: Application) extends Plugin
{
  override def onStart()
  {
    val configuration = application.configuration;
    // you can now access the application.conf settings, including any custom ones you have added
    Logger.info("MyExamplePlugin has started");
  }

  override def onStop()
  {
    // you may want to tidy up resources here
    Logger.info("MyExamplePlugin has stopped");
  }
}
</pre>
<h3>Hooking a plugin into your application</h3>
<p>Regardless of the implementation language, plugins are invoked directly by Play once you have added them to the conf/play.plugins file.  This file isn&#8217;t created when you start a new application, so you need to add it yourself.  The syntax is  &lt;priority&gt;:&lt;classname&gt;.  For example, to add the example plugin to your project, you would use</p>
<pre class="code">
10000:be.objectify.example.MyExamplePlugin
</pre>
<p>The class name is that of your plugin.  The priority determines the order in which plugins start up, and just needs to be a number that is larger or smaller than that of another plugin.  If you have several plugins, you can explicitly order them:</p>
<pre class="code">
5000:be.objectify.example.MyExamplePlugin
10000:be.objectify.example.MyOtherExamplePlugin
</pre>
<h2>Modules</h2>
<p>A module can be thought of as a reusable application that you can include in your own app. It&#8217;s analogous to a third-party library that adds specific functionality. A module can contain plugins, which you can hook into your app using the conf/play.plugins file.</p>
<p>For example, if you&#8217;re using Deadbolt 2 you would need to add the following to your play.plugins file:</p>
<pre class="code">
10000:be.objectify.deadbolt.DeadboltPlugin
</pre>
<p>A list of Play 2 modules can be found on the <a href="https://github.com/playframework/Play20/wiki/Modules" target="_blank">Play 2 GitHub wiki</a>.</p>
<p>You can read more on creating modules for Play 2 <a href="http://www.objectify.be/wordpress/?p=363" target="_blank">here</a> and <a href="http://www.objectify.be/wordpress/?p=374" target="_blank">here</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.objectify.be/wordpress/?feed=rss2&#038;p=464</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Women in IT &#8211; thoughts triggered by a female colleague</title>
		<link>http://www.objectify.be/wordpress/?p=461</link>
		<comments>http://www.objectify.be/wordpress/?p=461#comments</comments>
		<pubDate>Tue, 08 May 2012 14:40:15 +0000</pubDate>
		<dc:creator>steve</dc:creator>
				<category><![CDATA[personal]]></category>
		<category><![CDATA[thoughts]]></category>
		<category><![CDATA[do i sound like a dipshit here?]]></category>
		<category><![CDATA[women in IT]]></category>

		<guid isPermaLink="false">http://www.objectify.be/wordpress/?p=461</guid>
		<description><![CDATA[This post is coming quite a way after the fact, but I just read this tweet from Pamela Fox and it reminded me that I&#8217;ve been meaning to mention this for ages. Back in November at Devoxx here in Belgium, &#8230;<p class="read-more"><a href="http://www.objectify.be/wordpress/?p=461">Read more &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<div class="dzone_button" style="float: right; margin-left: 10px;">
<script type="text/javascript">
var dzone_url = 'http://www.objectify.be/wordpress/?p=461';
var dzone_title = 'Women in IT &#8211; thoughts triggered by a female colleague';
var dzone_blurb = '';
var dzone_style = '1';
</script>
<script language="javascript" src="http://widgets.dzone.com/links/widgets/zoneit.js"></script>
</div><p>This post is coming quite a way after the fact, but I just read <a href="https://twitter.com/#!/pamelafox/status/199864930449633281" target="_blank">this tweet</a> from <a href="http://www.pamelafox.org/" target="_blank">Pamela Fox</a> and it reminded me that I&#8217;ve been meaning to mention this for ages.</p>
<p>Back in November at Devoxx here in Belgium, one of the major themes was women in IT*.  I asked my female colleague (who is, by the way, an exceptional developer but I&#8217;m not going to name her because I haven&#8217;t asked permission!) if she was attending any of the talks.  She said no, and then went on to explain her viewpoint.</p>
<p>I&#8217;m paraphrasing from memory here, but the gist of the argument was &#8220;software developers are already a minority, and <strong>I don&#8217;t like the idea of creating an unnecessary sub-minority</strong>&#8220;.</p>
<p>This surprised me a lot.  From one point of view, I can see where she&#8217;s coming from &#8211; as software developers, we&#8217;re already regarded (to a lesser or greater degree) as a bit strange**, and we need to hang together if we&#8217;re going to avoid being hung separately.  From another viewpoint, however, it ignores the marginalisation of women by men who are in the same industry.  I was going to use the word victimisation, but I&#8217;ve never witnessed it personally (and you can be damn sure it wouldn&#8217;t happen twice in my presence, regardless of the gender of the victim) &#8211; maybe a commenter can bring me up to speed on this?</p>
<p>I&#8217;ve been lucky enough through my career to work with some exceptional developers who happened to be female.  In fact, I&#8217;ve never worked with a female developer who was any less than excellent &#8211; but there&#8217;s probably a very good reason for that.  Since the overwhelming majority of developers are men, it follows that the majority of bad developers are also men.  I&#8217;m pretty crappy with statistics, and they can famously be made to say anything, but it seems to me that the women who punch through the marginalisation barrier do so based on skill, and thus skew the figures even more.</p>
<p>Right now, I&#8217;m feeling very concious about what I&#8217;m writing, with the usual thoughts of sounding patronising and, frankly, feeling like the kind of dipshit who dumps his brain into his blog only to get it run through a blender.  C&#8217;est le vie. </p>
<p>* The chivalrous part of me wasn&#8217;t sure to use women, ladies, girls or females.  Since &#8220;Men in IT&#8221; is what I would write if this were about men, the feminine noun seems to me to be the correct one.<br />
** Strange, in this case, defining a group of people who will have vitriolic arguments over the formatting of JavaScript, for example.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.objectify.be/wordpress/?feed=rss2&#038;p=461</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>The Play! Framework Belgian User Group</title>
		<link>http://www.objectify.be/wordpress/?p=455</link>
		<comments>http://www.objectify.be/wordpress/?p=455#comments</comments>
		<pubDate>Sun, 06 May 2012 13:02:05 +0000</pubDate>
		<dc:creator>steve</dc:creator>
				<category><![CDATA[play! framework]]></category>
		<category><![CDATA[Play! Framework Belgian User Group]]></category>
		<category><![CDATA[belgium]]></category>
		<category><![CDATA[play!]]></category>
		<category><![CDATA[user group]]></category>

		<guid isPermaLink="false">http://www.objectify.be/wordpress/?p=455</guid>
		<description><![CDATA[When I attended the BeJUG session on the Play! Framework a few weeks ago, I was glad (but not especially surprised) to see how popular the session was. It&#8217;s been a busy few weeks since then, but in the meantime &#8230;<p class="read-more"><a href="http://www.objectify.be/wordpress/?p=455">Read more &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<div class="dzone_button" style="float: right; margin-left: 10px;">
<script type="text/javascript">
var dzone_url = 'http://www.objectify.be/wordpress/?p=455';
var dzone_title = 'The Play! Framework Belgian User Group';
var dzone_blurb = '';
var dzone_style = '1';
</script>
<script language="javascript" src="http://widgets.dzone.com/links/widgets/zoneit.js"></script>
</div><p>When I attended the <a href="http://www.parleys.com/#st=5&#038;id=3143&#038;sl=0" target="_blank">BeJUG session</a> on the Play! Framework a few weeks ago, I was glad (but not especially surprised) to see how popular the session was.  It&#8217;s been a busy few weeks since then, but in the meantime I&#8217;ve been thinking it&#8217;s time for a Belgian User Group for Play!.  </p>
<p>I&#8217;ve already created a Google Group for it at <a href="https://groups.google.com/forum/#!forum/play-be" target="_blank">https://groups.google.com/forum/#!forum/play-be</a> and sent out invitations to people that have expressed an interest.  Initially, I plan to start it small and get a meet-up organised.  Belgium is small enough that (in theory) no-one should have to travel too far.*</p>
<p>This is the first time I&#8217;ve ever tried something like this, so I&#8217;ll be asking various other user group founders for tips and hints to make the process as painless and smooth as possible.  I&#8217;ll be blogging on the development of the group as more things happen, and will include any and all good advice I receive for anyone else who&#8217;s thinking of doing this.</p>
<p>Against some of the perceived issues that have arisen between versions 1 and 2, an explicit goal of this user group is to include Play 1, Play 2, Java and Scala &#8211; the key is Play, and not a subset of it. </p>
<p>* Of course, in Belgium, distance is measured in traffic density and not kilometers</p>
]]></content:encoded>
			<wfw:commentRss>http://www.objectify.be/wordpress/?feed=rss2&#038;p=455</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The Play Framework is now officially an embarrassment</title>
		<link>http://www.objectify.be/wordpress/?p=444</link>
		<comments>http://www.objectify.be/wordpress/?p=444#comments</comments>
		<pubDate>Wed, 02 May 2012 19:40:07 +0000</pubDate>
		<dc:creator>steve</dc:creator>
				<category><![CDATA[open source]]></category>
		<category><![CDATA[play! framework]]></category>
		<category><![CDATA[thoughts]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[play!]]></category>

		<guid isPermaLink="false">http://www.objectify.be/wordpress/?p=444</guid>
		<description><![CDATA[If you&#8217;ve read any other entries on this blog, you&#8217;ll know that I&#8217;m an advocate of the Play! Framework. As of today, this has changed. My client is currently in the process of migrating their services to a federated collection &#8230;<p class="read-more"><a href="http://www.objectify.be/wordpress/?p=444">Read more &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<div class="dzone_button" style="float: right; margin-left: 10px;">
<script type="text/javascript">
var dzone_url = 'http://www.objectify.be/wordpress/?p=444';
var dzone_title = 'The Play Framework is now officially an embarrassment';
var dzone_blurb = '';
var dzone_style = '1';
</script>
<script language="javascript" src="http://widgets.dzone.com/links/widgets/zoneit.js"></script>
</div><p>If you&#8217;ve read any other entries on this blog, you&#8217;ll know that I&#8217;m an advocate of the <a href="http://www.playframework.org/" target="_blank">Play! Framework</a>.</p>
<p>As of today, this has changed.</p>
<p>My client is currently in the process of migrating their services to a federated collection of web services.  Business metrics are required, and so we needed to look at a logging service.  We discussed various options, and my proposal was accepted.  We have a few well-defined fields, and service-specific data is logged as a JSON document.  The discussion lasted about 25 minutes or so.</p>
<p>I went back to my desk, and wrote the code &#8211; a RESTful service, an asynchronous client using Akka, and a front-end in 15 minutes &#8211; using Play 2.</p>
<p>Let me spell that out, in case you missed the figures.  <strong>Implementing the entire solution took 3/5s the length of time of the meeting</strong>.</p>
<p>Can you imagine doing that with another web framework, especially in the Java space?  Play is, by definition at this point, an embarrassment &#8211; it can, should and will make other frameworks embarrassed of what they can offer.</p>
<p>I&#8217;m no longer an advocate of the Play! Framework.  I&#8217;m an <strong>unequivocal</strong> advocate of it. </p>
<p><strong>Edit</strong>: I&#8217;ve changed ashamed to embarrassed &#8211; ashamed was the wrong word to use, and gave negative connotations.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.objectify.be/wordpress/?feed=rss2&#038;p=444</wfw:commentRss>
		<slash:comments>23</slash:comments>
		</item>
		<item>
		<title>jQuery AJAX with Play 2</title>
		<link>http://www.objectify.be/wordpress/?p=428</link>
		<comments>http://www.objectify.be/wordpress/?p=428#comments</comments>
		<pubDate>Fri, 27 Apr 2012 06:42:17 +0000</pubDate>
		<dc:creator>steve</dc:creator>
				<category><![CDATA[how to]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[json]]></category>
		<category><![CDATA[open source]]></category>
		<category><![CDATA[play! framework]]></category>
		<category><![CDATA[ajax]]></category>
		<category><![CDATA[how-to]]></category>
		<category><![CDATA[play!]]></category>

		<guid isPermaLink="false">http://www.objectify.be/wordpress/?p=428</guid>
		<description><![CDATA[I&#8217;ve just prepared a course on jQuery to give to my colleagues, and one of the sections covers jQuery&#8217;s AJAX features. To demonstrate these, I wrote a quick web app using Play 2. Since there have been a few questions &#8230;<p class="read-more"><a href="http://www.objectify.be/wordpress/?p=428">Read more &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<div class="dzone_button" style="float: right; margin-left: 10px;">
<script type="text/javascript">
var dzone_url = 'http://www.objectify.be/wordpress/?p=428';
var dzone_title = 'jQuery AJAX with Play 2';
var dzone_blurb = '';
var dzone_style = '1';
</script>
<script language="javascript" src="http://widgets.dzone.com/links/widgets/zoneit.js"></script>
</div><p>I&#8217;ve just prepared a course on jQuery to give to my colleagues, and one of the sections covers jQuery&#8217;s AJAX features.  To demonstrate these, I wrote a quick web app using <a href="http://www.playframework.org/" target="_blank">Play 2</a>.  Since there have been a few questions asked in various places on how this works, I&#8217;m going to break it down here with some simple examples of the main <a href="http://api.jquery.com/jQuery.ajax/" target="_blank">$.ajax()</a> method, plus the <a href="http://api.jquery.com/category/ajax/shorthand-methods/" target="_blank">shorthand methods</a> that simplify its use.</p>
<h2>$.ajax()</h2>
<p>jQuery&#8217;s <a href="http://api.jquery.com/jQuery.ajax/" target="_blank">$.ajax()</a> method is part of the low-level interface, and can be configured to provide all your AJAX needs.  For this example, we&#8217;re going to do a simple GET that will result in a 200 response from the server, along with a text message.</p>
<p>The JavaScript:</p>
<pre class="code">
$.ajax(ajaxParameters({
      url: '/ajax',
      success: function(data, textStatus, jqXHR) {
        window.alert(data);
      },
      error: function(jqXHR, textStatus, errorThrown) {
        window.alert(textStatus);
      }
    }));
</pre>
<p>Note the URL &#8211; this results in a call to http://localhost:9000/ajax, and so must appear in the routes file:</p>
<pre class="code">
GET     /ajax                       controllers.Application.ajax()
</pre>
<p>The server-side implementation is about as simple as it gets:</p>
<pre class="code">
public static Result ajax()
{
    return ok("Here's my server-side data");
}
</pre>
<h3>Responding to errors</h3>
<p>Take a look at the JavaScript again &#8211; you will see there are handlers declared for success and error conditions.  What&#8217;s the difference?  A 200 response will trigger the success handler, and other codes trigger the error handler.  Let&#8217;s tweak the code to show this working.</p>
<p>The JavaScript.  The only thing that has changed here is the URL &#8211; it now points to a URL that is guaranteed to return a non-200 response.</p>
<pre class="code">
$.ajax(ajaxParameters({
      url: '/ajaxWithError',
      success: function(data, textStatus, jqXHR) {
        window.alert(data);
      },
      error: function(jqXHR, textStatus, errorThrown) {
        window.alert(textStatus);
      }
    }));
</pre>
<p>The route:</p>
<pre class="code">
GET     /ajaxWithError              controllers.Application.ajaxWithError()
</pre>
<p>And the server-side implementation:</p>
<pre class="code">
public static Result ajaxWithError()
{
    return badRequest("Somehow, somewhere, you screwed up");
}
</pre>
<p>And that&#8217;s it &#8211; you&#8217;re now handling success and error conditions.</p>
<h2>Shorthand methods</h2>
<p>jQuery usefully provides shorthand methods that simplify usage of $.ajax(), and in some cases provide additional functionality such as parsing repsonse data into JSON objects, or loading content into elements.</p>
<h2>$.get()</h2>
<p><a href="http://api.jquery.com/jQuery.get/" target="_blank">$.get()</a> is, unsurprisingly, for issuing asynchronous GETs to the server.  You can provide parameters, and give a single function that will be executed if the call is successful.</p>
<p>The JavaScript:</p>
<pre class="code">
$.get('/get',
      {'foo': 'bar'},
      function(data) {
          window.alert(data);
      });
</pre>
<p>The route &#8211; note this doesn&#8217;t specify a method parameter!</p>
<pre class="code">
GET     /get                        controllers.Application.get()
</pre>
<p>The server-side implementation:</p>
<pre class="code">
public static Result get()
{
    Map<String,String[]> queryParameters = request().queryString();
    return ok(String.format("Here's my server-side data using $.get(), and you sent me [%s]",
                            queryParameters.get("foo")[0]));
}
</pre>
<h3>Handling errors</h3>
<p>In the real world, you will receive errors sometimes and the above JavaScript doesn&#8217;t handle this.  The key is to use jQuery&#8217;s event-handling features instead of providing callbacks.  In this example, any success, error and completion events fired by $.get() are handled.</p>
<pre class="code">
$.get('/getWithError')
      .success(function(data) {
        window.alert('Success: ' + data);
      })
      .error(function(data) {
        window.alert('Error: ' + data.responseText);
      })
      .complete(function(data) {
        window.alert('The call is now complete');
      });
</pre>
<p>The route:</p>
<pre class="code">
GET     /getWithError               controllers.Application.getWithError()
</pre>
<p>The server-side implementation:</p>
<pre class="code">
public static Result getWithError()
{
    return badRequest("Something went very, very wrong");
}
</pre>
<h2>$.post()</h2>
<p>So far, so good, but what if you want to POST data to the server?  You can use <a href="http://api.jquery.com/jQuery.post/" target="_blank">$.post()</a> for this.  Interestingly, there are no shorthand methods for DELETE, PUT, etc &#8211; you have to use the $.ajax() method for these.</p>
<p>The semantics are the same as for $.get(), so I&#8217;m not going to provide an event-driven here.  This is using a regular callback.</p>
<p>The JavaScript:</p>
<pre class="code">
$.post('/post',
      {'foo':'bar'},
      function(data) {
          window.alert(data);
      });
</pre>
<p>The route &#8211; note the POST HTTP method is used.</p>
<pre class="code">
POST    /post                       controllers.Application.post()
</pre>
<p>And the server-side code:</p>
<pre class="code">
public static Result post()
{
    Map<String,String[]> parameters = request().body().asFormUrlEncoded();
    String message = parameters.get("foo")[0];

    return ok(message);
}
</pre>
<h2>$.getJSON()</h2>
<p><a href="http://api.jquery.com/jQuery.getJSON/" target="_blank">$.getJSON()</a> loads JSON-encoded data from the server using a GET HTTP request (to steal a line from the jQuery docs).  This means the data returned can be treated immediately as a JSON object without the need to process it further.</p>
<p>The JavaScript:</p>
<pre class="code">
$.getJSON('/getJson',
          function(data) {
              // data is a JSON list, so we can iterate over it
              $.each(data, function(key, val) {
                  window.alert(key + ':' + val);
          });
       });
</pre>
<p>The route:</p>
<pre class="code">
GET     /getJson                    controllers.Application.getJson()
</pre>
<p>Server-side code:</p>
<pre class="code">
public static Result getJson()
{
    List<String> data = Arrays.asList("foo", "bar");
    return ok(Json.toJson(data));
}
</pre>
<h2>$.getScript()</h2>
<p><a href="http://api.jquery.com/jQuery.getScript/" target="_blank">$.getScript()</a> loads a script from the server using a HTTP GET, and then executes it in the global context.</p>
<p>The JavaScript:</p>
<pre class="code">
$.getScript('/getScript');
</pre>
<p>The route:</p>
<pre class="code">
GET     /getScript                  controllers.Application.getScript()
</pre>
<p>Server-side code:</p>
<pre class="code">
public static Result getScript()
{
    return ok("window.alert('hello');");
}
</pre>
<h3>Handling events</h3>
<p>This example couldn&#8217;t be simpler.  It could, however, be slightly more complex.  The events generated by $.getScript() are slightly different to the success, error, etc events of the other methods.  For $.getScript(), there are <strong>done</strong> and <strong>fail</strong> events.  For success, you have to use a callback.</p>
<pre class="code">
$.getScript('/getScriptWithError',
            function() {
                window.alert('This is the success callback');
            })
            .done(function(script, textStatus) {
                window.alert('Done: ' + textStatus);
            })
            .fail(function(jqxhr, settings, exception) {
                window.alert('Fail: ' + exception);
            });
</pre>
<p>The route:</p>
<pre class="code">
GET     /getScriptWithError         controllers.Application.getScriptWithError()
</pre>
<p>The server-side implementation.  Note it&#8217;s returning a 200 response but with broken JavaScript.</p>
<pre class="code">
public static Result getScriptWithError()
{
    return ok("this is not a valid script!");
}
</pre>
<h2>.load</h2>
<p>Last but not least is <a href="http://api.jquery.com/load/" target="_blank">.load()</a>.  Note this <strong>isn&#8217;t</strong> $.load(), but rather $(a selector).load() as its purpose is to retrieve HTML from the server and place it into the matched element.</p>
<p>The JavaScript:</p>
<pre class="code">
$('#loadContainer').load('/load');
</pre>
<p>The route:</p>
<pre class="code">
GET     /load                       controllers.Application.load()
</pre>
<p>The server-side implementation:</p>
<pre class="code">
public static Result load()
{
    return ok(snippet.render());
}
</pre>
<p>The template:</p>
<pre class="code">
&lt;div id="aTable"&gt;
    &lt;table&gt;
        &lt;tr&gt;
            &lt;td&gt;Foo&lt;/td&gt;
            &lt;td&gt;Bar&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt;Hurdy&lt;/td&gt;
            &lt;td&gt;Gurdy&lt;/td&gt;
        &lt;/tr&gt;
    &lt;/table&gt;
&lt;/div&gt;
&lt;div id="aList"&gt;
    &lt;ul&gt;
        &lt;li&gt;Foo&lt;/li&gt;
        &lt;li&gt;Bar&lt;/li&gt;
    &lt;/ul&gt;
&lt;/div&gt;
</pre>
<h3>Loading fragments</h3>
<p>.load() can take a second parameter <strong>within</strong> the URL string, separated by a space.  This parameter is a selector &#8211; if present, jQuery will extract the selected element from the HTML and insert only that into the target.</p>
<pre class="code">
$('#loadFragmentContainer').load('/load #aList');
</pre>
<p>Note there is no change to the route, the server-side code or the template here &#8211; this is purely a client-side operation.</p>
<h2>That&#8217;s all, folks</h2>
<p>jQuery simplifies making AJAX calls, and Play simplifies receiving and responding to those calls.  A perfect match!</p>
<p>An example implemtation of all these features is available here: <strong><a href='http://www.objectify.be/wordpress/wp-content/uploads/2012/04/jquery-ajax.zip'>jquery-ajax</a></strong></p>
]]></content:encoded>
			<wfw:commentRss>http://www.objectify.be/wordpress/?feed=rss2&#038;p=428</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Publishing Play 2 modules on github</title>
		<link>http://www.objectify.be/wordpress/?p=410</link>
		<comments>http://www.objectify.be/wordpress/?p=410#comments</comments>
		<pubDate>Sat, 21 Apr 2012 08:19:52 +0000</pubDate>
		<dc:creator>steve</dc:creator>
				<category><![CDATA[how to]]></category>
		<category><![CDATA[modules]]></category>
		<category><![CDATA[play! framework]]></category>
		<category><![CDATA[github]]></category>
		<category><![CDATA[how-to]]></category>
		<category><![CDATA[maven]]></category>
		<category><![CDATA[open source]]></category>
		<category><![CDATA[play!]]></category>

		<guid isPermaLink="false">http://www.objectify.be/wordpress/?p=410</guid>
		<description><![CDATA[Now you&#8217;ve doubtless followed my earlier guides on writing modules for Play 2, I imagine you&#8217;re keen to show your coding chops to the world. The problem is &#8211; and this is quite a big one, I&#8217;m afraid &#8211; there &#8230;<p class="read-more"><a href="http://www.objectify.be/wordpress/?p=410">Read more &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<div class="dzone_button" style="float: right; margin-left: 10px;">
<script type="text/javascript">
var dzone_url = 'http://www.objectify.be/wordpress/?p=410';
var dzone_title = 'Publishing Play 2 modules on github';
var dzone_blurb = '';
var dzone_style = '1';
</script>
<script language="javascript" src="http://widgets.dzone.com/links/widgets/zoneit.js"></script>
</div><p>Now you&#8217;ve doubtless followed my <a href="http://www.objectify.be/wordpress/?p=363" target="_blank">earlier</a> <a href="http://www.objectify.be/wordpress/?p=374" target="_blank">guides</a> on writing modules for <a href="http://www.playframework.org/" target="_blank">Play 2</a>, I imagine you&#8217;re keen to show your coding chops to the world.  The problem is &#8211; and this is quite a big one, I&#8217;m afraid &#8211; there is no place to publish your modules to.  When I first starting writing Play modules, the repository was already set-up and ready to go &#8211; however, it used a custom format (state of the art download-and-unzip).  This changed to some degree with Play 1.2, but I have to say I&#8217;m not a fan of that dependency management mechanism; I&#8217;m just too damn old to learn these shiny new things.</p>
<p>With Play 2, things swung around again and the dependency mechanism is compliant with Maven and Ivy.  I can hear enterprises up and down the planet rejoicing.</p>
<p>However, this still doesn&#8217;t help you achieve your well-deserved glory and fame, unless you happen to host your own Maven/Ivy repo or feel like hacking the auto-generated artifact models that Play generates.  Help is hand, until Play 2 modules have an official release mechanism, using GitHub&#8217;s Pages feature.  Very simply, we&#8217;ll use Play&#8217;s publish-local task to generate all the files we need in the correct directory structure, and then copy that structure as-is directly into GitHub pages.  A publish in this manner can be done in less than a minute, after you&#8217;ve done the initial set-up in GitHub.</p>
<h3>Creating the repository in GitHub</h3>
<p>If your GitHub user name is, for example, <strong>foo</strong>, then creating a repository called <strong>foo</strong>.github.com hooks you into Pages &#8211; what you commit here will be available at http://foo.github.com.  There&#8217;s no GitHubby goodness when it comes to displaying files here &#8211; what you commit is what&#8217;s available in its native form.  Commit a HTML file (let&#8217;s call it bar.html), and point your browser at http://foo.github.com/bar.html and you&#8217;ll see the rendered HTML &#8211; not the source of it.  This makes it ideal for exposing files that you want represented in their raw form &#8211; say, the jar file containing your Play 2 module.</p>
<p>So, go ahead and create a <your username>.github.com repository and clone it to your workspace, and cd into it.  In here, you can replicate (kind of &#8211; see later) a meven repository.</p>
<p>To keep things nice, the first directory you should create is <strong>releases</strong>.  If you also want to add a snapshot directory, do it at this level.</p>
<p><strong>Note:</strong> When you first create the repository in GitHub, it can take up to 10 minutes for it to become available.  If you haven&#8217;t changed your email preferences, you should receive a notification when it is ready.  This doesn&#8217;t stop you committing to the repository in the meantime.</p>
<h3>Publish the files locally</h3>
<p>Let&#8217;s assume your module name is <strong>hurdy</strong> as the artifact name.  Your Build.scala looks like this:</p>
<pre class="code">
import sbt._
import Keys._
import PlayProject._

object ApplicationBuild extends Build {

    val appName         = "hurdy"
    val appVersion      = "1.0"

    val appDependencies = Seq(
    )

    val main = PlayProject(appName, appVersion, appDependencies, mainLang = JAVA).settings(
    )
}
</pre>
<p>(The mainLang value may be something else, depending on your primary language).</p>
<p>In the root of your module, start up Play and publish it locally:</p>
<pre class="code">
steve@hex:/tmp/hurdy$ play
[info] Loading project definition from /tmp/hurdy/project
[info] Set current project to hurdy (in build file:/tmp/hurdy/)
       _            _
 _ __ | | __ _ _  _| |
| '_ \| |/ _' | || |_|
|  __/|_|\____|\__ (_)
|_|            |__/ 

play! 2.0, http://www.playframework.org

> Type "help play" or "license" for more information.
> Type "exit" or use Ctrl+D to leave this console.

[hurdy] $ clean
[success] Total time: 0 s, completed Apr 21, 2012 9:49:00 AM
[hurdy] $ compile
[info] Updating {file:/tmp/hurdy/}hurdy...
[info] Done updating.
[info] Compiling 4 Scala sources and 2 Java sources to /tmp/hurdy/target/scala-2.9.1/classes...
[success] Total time: 7 s, completed Apr 21, 2012 9:49:08 AM
[hurdy] $ publish-local
[info] Packaging /tmp/hurdy/target/scala-2.9.1/hurdy_2.9.1-1.0-SNAPSHOT-sources.jar ...
[info] Done packaging.
[info] Wrote /tmp/hurdy/target/scala-2.9.1/hurdy_2.9.1-1.0-SNAPSHOT.pom
[info] :: delivering :: hurdy#hurdy_2.9.1;1.0-SNAPSHOT :: 1.0-SNAPSHOT :: release :: Sat Apr 21 09:49:12 CEST 2012
[info] 	delivering ivy file to /tmp/hurdy/target/scala-2.9.1/ivy-1.0-SNAPSHOT.xml
[info] Generating API documentation for main sources...
[info] Packaging /tmp/hurdy/target/scala-2.9.1/hurdy_2.9.1-1.0-SNAPSHOT.jar ...
[info] Done packaging.
model contains 23 documentable templates
[info] API documentation generation successful.
[info] Packaging /tmp/hurdy/target/scala-2.9.1/hurdy_2.9.1-1.0-SNAPSHOT-javadoc.jar ...
[info] Done packaging.
[info] 	published hurdy_2.9.1 to /home/steve/development/play/play-2.0/framework/../repository/local/hurdy/hurdy_2.9.1/1.0-SNAPSHOT/poms/hurdy_2.9.1.pom
[info] 	published hurdy_2.9.1 to /home/steve/development/play/play-2.0/framework/../repository/local/hurdy/hurdy_2.9.1/1.0-SNAPSHOT/jars/hurdy_2.9.1.jar
[info] 	published hurdy_2.9.1 to /home/steve/development/play/play-2.0/framework/../repository/local/hurdy/hurdy_2.9.1/1.0-SNAPSHOT/srcs/hurdy_2.9.1-sources.jar
[info] 	published hurdy_2.9.1 to /home/steve/development/play/play-2.0/framework/../repository/local/hurdy/hurdy_2.9.1/1.0-SNAPSHOT/docs/hurdy_2.9.1-javadoc.jar
[info] 	published ivy to /home/steve/development/play/play-2.0/framework/../repository/local/hurdy/hurdy_2.9.1/1.0-SNAPSHOT/ivys/ivy.xml
[success] Total time: 3 s, completed Apr 21, 2012 9:49:15 AM
</pre>
<h3>Move the published files into GitHub</h3>
<p>The files have been published to <strong>${PLAY_HOME}/repository/local</strong>, and are contained in the <strong>hurdy</strong> directory.  Move this entire directory to your new git repository</p>
<pre class="code">
cp -rv ${PLAY_HOME}/repository/local/hurdy &lt;your username&gt;.github.com/releases
</pre>
<p>Change directory to <strong><your username>.github.com</strong>, and add all the files to the git repository, commit and push them.</p>
<pre class="code">
steve@hex:/tmp/schaloner.github.com$ git add .
steve@hex:/tmp/schaloner.github.com$ git commit -m "Added release 1.0 to repository"
steve@hex:/tmp/schaloner.github.com$ git push -u origin master
</pre>
<h3>Use the dependency</h3>
<p>Create a new project (or open up an old one), and add the dependency and its location.</p>
<pre class="code">
object ApplicationBuild extends Build {

    val appName         = "my-cool-project"
    val appVersion      = "2.1"

    val appDependencies = Seq(
      "hurdy" %% "hurdy" % "1.0"
    )

    val main = PlayProject(appName, appVersion, appDependencies, mainLang = JAVA).settings(
      resolvers += Resolver.url("My GitHub Play Repository", url("http://&lt;your username&gt;.github.com/releases/"))(Resolver.ivyStylePatterns)
    )
}
</pre>
<p><strong>Note: </strong> Play has published the files in an Ivy style pattern, so this needs to be specified in your Build.scala</p>
<p>Start Play in your application root, and run the &#8220;dependencies&#8221; task.  If all goes well &#8211; and I&#8217;m sure you&#8217;ll let me know if it doesn&#8217;t &#8211; your module will be pulled from GitHub and made available to your application.</p>
<h3>Specifiying an organisation</h3>
<p>Because there&#8217;s no organisation specified in Build.scala, the organisation (repository/local/<strong>hurdy</strong>/hurdy_2.9.1) is taken to be the same as the module name.  If you want an organisation, add it in the <strong>main</strong> definition:</p>
<pre class="code">
val main = PlayProject(appName, appVersion, appDependencies, mainLang = JAVA).settings(
      organization := "com.example"
    )
</pre>
<p>Now, when you publish locally the files will be placed in repository/local/<strong>com.example</strong>/hurdy_2.9.1.  In this case, it&#8217;s the <strong>com.example</strong> directory that should copied from the local repository to your GitHub repo.  The Build.scala of any application using your dependency will be similarly different:</p>
<pre class="code">
val appDependencies = Seq(
      "com.example" %% "hurdy" % "1.0"
    )
</pre>
<h3>Real-world proof this works</h3>
<p>Deadbolt 2 is currently available using this mechanism, using <a href="https://github.com/schaloner/schaloner.github.com" target="_blank">http://schaloner.github.com</a> as the repository.  Here, there are release and snapshot versions so the Build scala of the sample applications looks like this:</p>
<pre class="code">
import sbt._
import Keys._
import PlayProject._

object ApplicationBuild extends Build {

    val appName         = "deadbolt-usage"
    val appVersion      = "1.1.3-SNAPSHOT"

    val appDependencies = Seq(
      "be.objectify" %% "deadbolt-2" % "1.1.3-SNAPSHOT"
    )

    val main = PlayProject(appName, appVersion, appDependencies, mainLang = JAVA).settings(
      // Change this to point to your local play repository
      resolvers += Resolver.url("Objectify Play Repository", url("http://schaloner.github.com/releases/"))(Resolver.ivyStylePatterns),
      resolvers += Resolver.url("Objectify Play Repository", url("http://schaloner.github.com/snapshots/"))(Resolver.ivyStylePatterns)
    )
}
</pre>
<p>If I change the required version from 1.1.3-SNAPSHOT (which is in the snapshots/ directory) to 1.1.3 (which will be in the releases/ directory), the dependency will be resolved correctly.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.objectify.be/wordpress/?feed=rss2&#038;p=410</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Sometimes, it&#8217;s like the internet never happened &#8211; listen and learn, Disney</title>
		<link>http://www.objectify.be/wordpress/?p=407</link>
		<comments>http://www.objectify.be/wordpress/?p=407#comments</comments>
		<pubDate>Sun, 08 Apr 2012 21:16:42 +0000</pubDate>
		<dc:creator>steve</dc:creator>
				<category><![CDATA[personal]]></category>
		<category><![CDATA[thoughts]]></category>
		<category><![CDATA[disney]]></category>
		<category><![CDATA[life]]></category>

		<guid isPermaLink="false">http://www.objectify.be/wordpress/?p=407</guid>
		<description><![CDATA[Ever read Freakonomics? There&#8217;s a great chapter on how internet-accessible information drove down insurance premiums massively. The same story can be found in many places &#8211; but some companies are apparently completely oblivious to this. Which is the specific company &#8230;<p class="read-more"><a href="http://www.objectify.be/wordpress/?p=407">Read more &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<div class="dzone_button" style="float: right; margin-left: 10px;">
<script type="text/javascript">
var dzone_url = 'http://www.objectify.be/wordpress/?p=407';
var dzone_title = 'Sometimes, it&#8217;s like the internet never happened &#8211; listen and learn, Disney';
var dzone_blurb = '';
var dzone_style = '1';
</script>
<script language="javascript" src="http://widgets.dzone.com/links/widgets/zoneit.js"></script>
</div><p>Ever read <a href="http://www.freakonomics.com/" target="_blank">Freakonomics</a>?  There&#8217;s a great chapter on how internet-accessible information drove down insurance premiums massively.  The same story can be found in many places &#8211; but some companies are apparently completely oblivious to this.</p>
<p>Which is the specific company that triggered this blog post?  Disney &#8211; Disneyland Paris, to be exact.</p>
<p>On visiting their site, I immediately got redirected to the Belgian version of their website.  While my level of Dutch is good enough to deal with this, I do prefer English just for speed of reading so I switched to the UK website.  I looked up 5 nights in a specific hotel, 2 adults, 1 five-year-old child, starting August 1st.  The resulting price &#8211; <strong>£1338</strong>.  Expensive, but about what you would expect from Disney.  For comparison, the currency converter at <a href="http://www.oanda.com/" target="_blank">OANDA</a> converts this at today&#8217;s rate to <strong>€1620.70</strong>.</p>
<p>Now, having lived in Belgium for some time, and being acutely aware of how expensive it is, I decided to check out the same deal from the Belgian website.  Same people, same date, same duration.  The result this time?  A jaw-dropping <strong>€2306</strong>.  Since this doesn&#8217;t include transport, it would be cheaper for me to drive to the UK, turn around, drive to Paris and have the holiday than just drive 3 hours south and have the same exact holiday.  What would Al Gore say about this carbon impact?</p>
<p>This goes completely against the concept that people won&#8217;t pay 10 for something when information is freely and easily available that indicates they should be paying 5.  It does take into account the inherent laziness of some people, and the fact that some people are unaware of this information.  For people who are aware of this info, and are willing to do something about it (i.e. me) it&#8217;s a complete insult.  It&#8217;s also a great incentive to not go to Disney.</p>
<p>Remember, the democratization of information the web has brought doesn&#8217;t mean anything if you don&#8217;t vote!  In the meantime, let&#8217;s call this a fail for Disney.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.objectify.be/wordpress/?feed=rss2&#038;p=407</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The all-new Play Module Repository</title>
		<link>http://www.objectify.be/wordpress/?p=400</link>
		<comments>http://www.objectify.be/wordpress/?p=400#comments</comments>
		<pubDate>Wed, 04 Apr 2012 10:25:20 +0000</pubDate>
		<dc:creator>steve</dc:creator>
				<category><![CDATA[modules]]></category>
		<category><![CDATA[open source]]></category>
		<category><![CDATA[play! framework]]></category>
		<category><![CDATA[play!]]></category>

		<guid isPermaLink="false">http://www.objectify.be/wordpress/?p=400</guid>
		<description><![CDATA[Back in November, I spoke to Nicolas Leroux of the Play framework about creating a module repository. He agreed it would be a good idea, but lack of time has prevented me from starting this. Following the stormy events of &#8230;<p class="read-more"><a href="http://www.objectify.be/wordpress/?p=400">Read more &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<div class="dzone_button" style="float: right; margin-left: 10px;">
<script type="text/javascript">
var dzone_url = 'http://www.objectify.be/wordpress/?p=400';
var dzone_title = 'The all-new Play Module Repository';
var dzone_blurb = '';
var dzone_style = '1';
</script>
<script language="javascript" src="http://widgets.dzone.com/links/widgets/zoneit.js"></script>
</div><p>Back in November, I spoke to Nicolas Leroux of the <a href="http://www.playframework.org/" target="_blank">Play framework</a> about creating a module repository.  He agreed it would be a good idea, but lack of time has prevented me from starting this.  Following the <a href="http://www.objectify.be/wordpress/?p=395" target="_blank">stormy events</a> of last week in the Play Google Group, I&#8217;ve decided to prioritise it.  A working prototype should be available in a couple of weeks.</p>
<p>The overview:<br />
<strong>1. It&#8217;s open source</strong><br />
Obviously</p>
<p><strong>2. It&#8217;s written in Play 2</strong><br />
Just to piss off the nay-sayers <img src='http://www.objectify.be/wordpress/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p><strong>3. Module creation</strong><br />
At the moment, to get a module into the module repository you have to get authorisation from a member of the Play team.  I want to have a repo where you can upload any module, as long as it conforms to certain minimum requirements.  These are<br />
 * a README file<br />
 * a license (preferably, but not constrained to, a business-friendly one)<br />
 * actual code, to prevent a bunch of empty modules being created</p>
<p><strong>4. Open accounts</strong><br />
 Users can create accounts by logging in via twitter, facebook, etc, and link multiple sign-in methods to their accounts.</p>
<p><strong>5. Security</strong><br />
 Authentication will come via SecureSocial (so Jorge Aliss needs to start coding!) and authorisation will be implemented in Deadbolt 2.  As a result, this will supercede the SociallySecure example app which showed how to integrate the two. </p>
<p><strong>6. Modules are web-accessible</strong><br />
 Modules can be downloaded directly through the browser</p>
<p><strong>7. Modules are framework-accessible</strong><br />
 Regardless of the version of Play, and therefore regardless of the dependency mechansim, the repository will serve modules directly to the framework.  In other words, when you add modules to dependencies.yml or Build.scala, those modules will be fetched by the framework.  Manual installation is not required.</p>
<p><strong>8. Voting</strong><br />
 Any logged-in user can vote up a module.  One vote per module, to keep things fair.</p>
<p><strong>9. Commenting</strong><br />
 Any logged-in user can comment.  Because of the open sign-in method, I think it doesn&#8217;t make sense to have anonymous comments.  Trolls can go elsewhere.</p>
<p><strong>10. Play 1 modules</strong><br />
 Play 1 modules will be hosted directly in the repo.</p>
<p><strong>11. Play 2 modules</strong><br />
 Play 2 modules can also be hosted in the repo, but since they can also be hosted in any Maven or Ivy repo it&#8217;s possible to link to the remote repo instead.  This doesn&#8217;t impact point #7 since it will be transparent to the framework itself.</p>
<p><strong>12. No ambiguity</strong><br />
 One very important point comes from Ben Verbeken &#8211; &#8220;We&#8217;ll just have to make sure it&#8217;s really obvious to the visitor that they are browsing either the play 1 or play 2 modules (no hidden filter feature, but a big red switch at the top e.g. <img src='http://www.objectify.be/wordpress/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> )&#8221;</p>
<p> The github repository (which is currently empty, because it was created nine minutes ago) can be found at <a href="https://github.com/playframework/modules.playframework.org" target="_blank">https://github.com/playframework/modules.playframework.org</a></p>
<p> At the moment, we&#8217;re purely at the planning stage but I plan to use my favourite development style (evolutionary prototying) to get something up and working fast.  The github repo will be created tonight, and regular updates will be posted here.</p>
<p>Peter Hilton has posted some more details over at the Play <a href="https://groups.google.com/d/msg/play-framework/oC4DuQRWDDw/m8-6nMCEiEMJ" target="_blank">Google Group</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.objectify.be/wordpress/?feed=rss2&#038;p=400</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Play 2 &#8211; some people don&#8217;t seem to realise what they have</title>
		<link>http://www.objectify.be/wordpress/?p=395</link>
		<comments>http://www.objectify.be/wordpress/?p=395#comments</comments>
		<pubDate>Fri, 30 Mar 2012 12:58:01 +0000</pubDate>
		<dc:creator>steve</dc:creator>
				<category><![CDATA[java]]></category>
		<category><![CDATA[open source]]></category>
		<category><![CDATA[play! framework]]></category>
		<category><![CDATA[thoughts]]></category>
		<category><![CDATA[play!]]></category>
		<category><![CDATA[scala]]></category>

		<guid isPermaLink="false">http://www.objectify.be/wordpress/?p=395</guid>
		<description><![CDATA[There&#8217;s a very active discussion going on at the moment regarding Play 2 over the Google Group, and it&#8217;s really polarising opinion. A lot of people still seem to be under the impression that Play 2 is only a Scala &#8230;<p class="read-more"><a href="http://www.objectify.be/wordpress/?p=395">Read more &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<div class="dzone_button" style="float: right; margin-left: 10px;">
<script type="text/javascript">
var dzone_url = 'http://www.objectify.be/wordpress/?p=395';
var dzone_title = 'Play 2 &#8211; some people don&#8217;t seem to realise what they have';
var dzone_blurb = '';
var dzone_style = '1';
</script>
<script language="javascript" src="http://widgets.dzone.com/links/widgets/zoneit.js"></script>
</div><p>There&#8217;s a very active discussion going on at the moment regarding <a href="http://www.playframework.org/" target="_blank">Play 2</a> over the <a href="https://groups.google.com/d/topic/play-framework/AcZs8GXNWUc/discussion" target="_blank">Google Group</a>, and it&#8217;s really polarising opinion.  A lot of people still seem to be under the impression that Play 2 is only a Scala framework, with a crappy half-baked Java API bolted on as an afterthought.  It&#8217;s not &#8211; both Java and Scala are first class citizens in Play 2, and it amazes me that so much FUD is surrounding this issue.</p>
<p>People also seem to be viewing it as a usurper to Play 1, and that Play 1 is now a dead framework walking.</p>
<p>I&#8217;m going to do the laziest thing possible in a blog, and reproduce my contribution to this argument (with added emphasis on some parts):</p>
<blockquote><p>I&#8217;ve got projects in production using Play 1.x (including a huge one that took over a year to write &#8211; and which would have taken much longer without Play).  Do I think Play 1 is going to die? No &#8211; because lots of people, including Zenexity, have got lots of projects running on Play 1.  For them to let it die would be like shooting themselves in the foot &#8211; got this from Guillaume and Sadek directly last night.</p>
<p>Do I want to port those projects over to Play 2? No &#8211; because they&#8217;re running perfectly well on Play 1, and are now in maintenance mode.</p>
<p>What will I choose for my next project?  Probably Play 2, unless the code requires deployment as a war, and this seems to be a point that a lot of people are missing.  There&#8217;s nothing that can be done in Play 1 that can&#8217;t be done in Play 2, and if you want, you can do it all in Java.  <strong>My Scala is still pretty much at the beginning of the learning process, but this in no way discourages me from coding with Play 2 because *I don&#8217;t need to know Scala*</strong>.  For a comparison, how many people knew Groovy before they started using Play 1 Groovy templates?</p>
<p>Backwards compatibility is important, and that&#8217;s why Play 1.2.5 (and .6 and .7 and .n) will be backwards compatible.  For Play 2 to not be able to move past what has come before would maybe win some fans in the short term, people who want to be able to drop their Play 1 projects into Play 2 without a code change, but in the mid- to long-term it would have been obsolete before it even started.</p>
<p><strong>There is no Play Scala or Play Java &#8211; it&#8217;s Play JVM, and that&#8217;s what it always has been!</strong> </p></blockquote>
<p>For reference, the thread is <a href="https://groups.google.com/d/topic/play-framework/AcZs8GXNWUc/discussion" target="_blank">https://groups.google.com/d/topic/play-framework/AcZs8GXNWUc/discussion</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.objectify.be/wordpress/?feed=rss2&#038;p=395</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>

