Category Archives: Play

Play Authenticate No Context

Hopefully this saves someone a little time.  Starting with a working project that had play authenticate fully integrated and  all of its controller methods fixed to work with 2.4.4/2.4.6 injected routes, I deleted everything but the bare metal code to create an entire application template for future projects.  When trying to pull up the home page, I was getting a runtime error from the Application.java controller on construction saying that it could not be injected because there was no http context available.  By removing code from the main page, i quickly determined that the error was coming from the authentication references.  I checked the old application again and everything critical to authentication seemed to be there.  To make a much longer than it should have been story short, the problem was simply that I had not defined an index.html.scala template.  I was using a template named “home” but did not realize that authenticate needed this.  Exactly why would require digging that I don’t care to do, however, in researching the problem, i noticed that in the Global class where I would expect context initialization to happen, the index template was referenced.  So, I added it back with a simple forward to my home page as so

<meta http-equiv=”refresh” content=”0; url=@routes.Application.home” />

and that was all it took.   Anyone interested in this working, starter application please let me know as I will be happy to share it or whatever i’m using for a play starting point at the time.  I am not sure if play authenticate has been updated to be compatible with 2.4.x play yet so this may save  you quite a bit of work.  Hope this helps someone 🙂

Play Framework JavascriptRouter Connecting to a Java Controller

Just wanted to go over some of the basics of making use of the

javascriptrouter javascript routing capability in the Play Framework

.  I won’t go in to any major detail but instead will give examples of the minimal setup in Play necessary to get this working.  With this functionality, you can access back end data through your Java controller from a page without a page refresh.  While there are several ways of doing this, wrapping things with Play provides a simple, consistent path with powerful implications.

First, add a route for javascript routing to use and a route for the method that will be called in the routes file:


GET /assets/js/routes controllers.Application.jsRoutes()

GET /cities/:id controllers.Application.getCities(id: Long)

In this, I am passing a simple integer parameter to the getCities method in my Application controller.

Now, in your template, add this script to expose this route

<script src="@controllers.routes.Application.jsRoutes()" type="text/javascript"></script>

You will probably want to throw this in to your main template. This is the one that holds your basic page layout, headers, footers, standard menu items etc. This way it will be available in all of the other templates that include the main template.

In your controller, set up a method to handle javascript routes and a method corresponding to the getCities(int) call

public Result getCities(Long id) {
System.out.println("in getCities in the Application controller");
System.out.println("The id passed in is " + Long.toString(id));
return ok();
}


public Result jsRoutes()
{
response().setContentType("text/javascript");
return ok(Routes.javascriptRouter("appRoutes", //appRoutes will be the JS object available in our view
routes.javascript.Application.getCities()));
}

I’m not doing anything here or passing anything back. Once you have this working, it is up to you what you want to return to the call from javascript. This method simply displays the id passed in to show that it is being called.

Finally, in the template you wish to fetch data for, add the code to make your call through the router from javascript. In this example I am simply passing in a parameter of 1 and showing the returned string data in an alert box. In the provided java method, nothing is returned. You will want to do something real in your method and pass back something useful.


appRoutes.controllers.Application.getCities(1).ajax({success : function(data) {alert(data);});

A reworked and more useful example of the controller method here sends back a set of json formated key value pairs.

public Result getCities(Long id) {
Map cities = City.options(id);
Gson gson = new GsonBuilder().create();
String json = gson.toJson(cities);
return ok(json);
}

That’s all there is to it! Now that you have the page talking to the controller, you can do most anything you might normally handle with a submit and page refresh without sending back a whole page. For example, as I may be preparing to in this case, load up a list of cities in a dropdown based on a selected state (onchange event) in another dropdown. The documentation I’ve seen on this is mostly geared towards those writing their controller in Scala too. Play has very good support for Java and will hopefully continue to allow both Java and Scala controllers in the future. It is currently my favorite way of putting Java to use on the web. If the 3.x versions of Play become even more Scalified, that is, the option of writing model and controller code in Java rather than Scala goes away, I will abandon Play and try something else. Basically I am saying, if I have to program everything in Scala, I would just as soon make the move to NodeJS. I am using Play specifically because of the cool way it handles routing web requests to Java code. The Scala you have to use in templating is fairly simple. I’ve even developed a few little Scala tricks I’ve become fond of in my template code. However, I’m not at all interested in developing complex application logic in Scala or javascript for that matter. Scratch the NodeJS comment. I’ll just skip the framework all together and create REST stuff by hand. For now though, the Play framework has been a great addition to my web application strategy. This javascript routing stuff is an example of just how slick it is as a framework for modern web applications.

For more information, check out this article which goes in to a little more detail on javascriptrouters in play with java controller code

 

In Play Problem with MariaDB JDBC Driver Client org.mariadb.jdbc.Driver

My latest Play problem was actually a jdbc driver bug.

With all the fixing (and learning) I’ve been doing the last few days trying to get the hang of ebeans in Play 2.4.x, the last thing I expected was one of my biggest hangups to be a jdbc bug.  As anyone who has been here knows, I am a huge fan of MariaDB so don’t take this to mean otherwise.  However, if using the Maria client 1.3.2 in Play with ebeans or likely with many other common ORM’s, and you get an error like:

[PersistenceException: ERROR executing DML bindLog[] error[getGeneratedKeys error. Statement.RETURN_GENERATED_KEYS must be precised on connection.prepareStatement(String sql, int autoGeneratedKeys) or statement.executeUpdate(String sql, int autoGeneratedKeys)]]

It isn’t you. It is actually a bug. A smart guy timowest pointed this out on github 10 days ago

Looks like a bug in the driver
https://github.com/MariaDB/mariadb-connector-j/blob/1.3.0/src/main/java/org/mariadb/jdbc/MariaDbConnection.java#L359

The flag Statement.RETURN_GENERATED_KEYS is missing.

I switched to the oracle driver in application.conf and all works great.  Good find Tim!  I’ll be switching back as soon as this is resolved in the maria client binary.  I’m hoping this has been reported.

While I’m giving a shout out.  Thanks also to Matthieu Guillermin and his great post on getting around ebean optimistic locking in Play.  You can find his great post here

 

Play 2 Framework Pagination Stuff Has Changed Version 2.3.7 to 2.4.1

If you are trying to get the computer database example in Play 2 to work which is in 2.3.7 and you are using version 2.4.1 or later, you will find that there are some minor changes to the pagination code.  Here is how to get Play 2 Framework Pagination working.

 

The original code will look something like this:


public static Page page(int page, int pageSize, String sortBy, String order, String filter) {
return
find.where()
.ilike("name", "%" + filter + "%")
.orderBy(sortBy + " " + order)
.fetch("company")
.findPagingList(pageSize)
.setFetchAhead(false)
.getPage(page);
}

Upon you compiling, you will find that FindPagingList is now gone.  Use findPagedList(int,int) instead.  Here is an example that works for  a different table.  Just replace “alias” with “name” and change the fetch to “company” and things should be back working in version 2.4.1


public static PagedList page(int page, int pageSize, String sortBy, String order, String filter) {
return
find.where()
.ilike("alias", "%" + filter + "%")
.orderBy(sortBy + " " + order)
.fetch("version")
.findPagedList(page, pageSize);
}

You will need to import the com.avaje.ebean stuff too.

import com.avaje.ebean.Model;
import com.avaje.ebean.PagedList;

Finally, don’t forget to change your views to use com.avaje.ebean.PagedList too.

Play Framework 2.4.3 – Problems Building Example Templates in Activator

 

If you have downloaded the Play Framework version 2.4.3 code lately and are “playing” with Activator, you will probably notice that most of the examples will not build successfully.  The error you encounter will look something like this:

(*:update) sbt.ResolveException: unresolved dependency: com.typesafe.play#sbt-fork-run-plugin;2.3.6: not found

Here is the fix that worked for me:

You need to load a more current sbt-plugin.  Wish there was a cleaner way to demo Play as I do like it a lot so far.  Go to “code” and select Project.  Select the “plugins.sbt” file and edit the line under “//The Play Plugin” to read:

addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.3.9")

Then, in the same directory level, either edit the “play-fork-run.sbt” file to match changing the version number to 2.3.9 or you may even be able to delete it as it usually will be rebuilt when the project is built again.  I would suggest editing it as I’ve seen a few projects that die during the build because they are looking for it.  Not sure why as I am not an expert on this build system yet 🙂  At this point, if you have activator set to a”compile on file change” it should already be working.  If not, click compile and everything should work for you now. Have fun with play!