Your Play project is Java and Scala, at the same time

In the moment of creation a Play application, we are obliged to choose between Java and Scala as the base of our code, which is good because you can prefer one or another. The problem with this choice is that the programmers, basically Java programmers, they think that is a final choice. It is not unusual see some doubts in Play’s user forum about how to do something in Java version which is already well know in Scala version. For example, how to implement Web Sockets.

Of course, if there is a Java way to accomplish the task, go ahead and use it but, if there is not a Java way or this way is worst than the Scala version, still go ahead and use Scala. This is the point of this post, Play is possibly the only framework thought to be used with Scala and Java together, and not separated. Another example, all view templates are written in Scala. You still have the router file :).

Let’s see some examples! The first one is if you need to receive a Option in your template. You can try to pass a Option from play.libs.F.Option to your template.

    @(maybeTag:JavaOption[Hashtag])

    @maybeTag.map { tag:Hashtag =>
          @tag
    }.getOrElse {
          tagless
    }

The problem is that template, that becomes a Scala class after compilation, does not have any conversion from play.libs.F.Option to scala.Option. So code showed above will not work. There is no problem at all, instead of pass Play’s wrapper as argument, you can create a new Scala Option and solve your problem.

    ok(views.html.index.render(scala.Option.apply(hashtag)));

Another situation. Sometimes you have a class that simply holds a value. For example, in one of my current projects, I have a class called ImportStat.

    public class ImportStat {

    	private Number count;
    	private PhotoStatus photoStatus;

    	public ImportStat(Number count, PhotoStatus photoStatus) {
    		super();
    		this.count = count;
    		this.photoStatus = photoStatus;
    	}

    	public Number getCount(){
    		return this.count;
    	}

    	public PhotoStatus photoStatus() {
    		return photoStatus;
    	}

    }

I need to print the count value to give some information about a task that is being done by some Actor in my system. One way to do this is:

    @for(stat <- stats) {
     	  @stat.photoStatus():@stat.getCount()
    }

But, with a minor change you can take advantage of Scala syntax sugar to return values of your objects. You can use the apply() method. So let’s change our class.

    public class ImportStat {

    	private Number count;
    	private PhotoStatus photoStatus;

    	public ImportStat(Number count, PhotoStatus photoStatus) {
    		super();
    		this.count = count;
    		this.photoStatus = photoStatus;
    	}

    	public Number apply(){
    		return this.count;
    	}

    	public PhotoStatus photoStatus() {
    		return photoStatus;
    	}

    }

Now, in your template, you can write something like this.

    @for(stat <- stats) {
     	  @stat.photoStatus():@stat()
    }

The last one is the better, at least for me. I needed to use SSE to push notifications to browser. I googled about it and found this link, there was not a Java version! So I kept looking for and I found this blog post, which showed to me that Scala version was already implemented and it is much better than Java way, even if you use the pull request that brings SSE to Java version. So, for this case, I preferred to write the controller in Scala. Let’s just take a look in how you can open a SSE connection.

    package controllers

    //imports

    object UpdatePhotosController extends Controller {

      val (chatOut, chatChannel) = Concurrent.broadcast[JsValue]

      def newPhotos() = Action {
        implicit req =>
          {
            Ok.feed(chatOut &> EventSource()).as("text/event-stream")
          }
      }
    }

Now, let’s look how you can push information through the channel. And we will make this from an Actor written in Java!

    public class UpdatePhotoPanelActor extends UntypedActor{

    	@Override
    	public void onReceive(Object message) throws Exception {
    		final String id = (String) message;
    		Photo photo;
    		try {
    			photo = JPA.withTransaction(new Function0() {

    				@Override
    				public Photo apply() throws Throwable {
    					return Photos.byId(id);
    				}
    			});
    		} catch (Throwable e) {
    			throw new Exception(e);
    		}

    		UpdatePhotosController.chatChannel()
    		    .push(PanelPhotosJson.toScalaJsValue(0,photo));
    	}

    }

That is it! Don’t be afraid to mix both languages. If you are in Java project, your code will be 90% in Java and just 10% in Scala, not a big problem. The important part of Play written in Scala is the core, to build real world application is not important which one you gonna pick :). Choose the option that better fits to your team.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s