Franz Blog

Yet another Java 8 Optional post

Posted in Stuff by franzgranlund on 8 November, 2014

So there are quite a lot of blogposts out there talking about Java 8s Optional<T>. I will not join the debate about when and if to use Optional<T>, but instead I will demonstrate how to use it.

Most of the blogposts seems to advocate to first check using isPresent() and then get the value using get(). Unfortunately the get() method will throw an exception if trying to get from an empty Optional, so if you forget to check it using isPresent() you’re screwed. This method will not improve your code at all; sure, it will make you think of the possibility that the value may be empty, but the code will still look like this:

        Optional<String> o = Optional.ofNullable(mayReturnStringOrNull());
        
        if (o.isPresent()) {
            String value = o.get();
            if (value.equals("hello")) {
                Logger.info("{} world", value);
            }
        }

The better alternative would of course be to use orElse() to provide a default value if the Optional is empty, like so:

        Optional<String> o = Optional.ofNullable(mayReturnStringOrNull());
        String value = o.orElse("default value");
        
        if (value.equals("hello")) {
            Logger.info("{} world", value);
        }

“flatMap that shit!”

What most posts about Optional<T> seems to forget are the most powerful methods, namely map(), flatMap(), filter(), ifPresent() and orElseGet().

        Optional.ofNullable(mayReturnStringOrNull())
                .filter("hello"::equals)
                .ifPresent(v -> Logger.info("{} world", v));

Remember that map returns and Optional describing the result (can be another type!). If the mapping functions return null, then an empty Optional is returned.

        // Imagine that getGroup returns an empty Optional if username
        // doesn't belong to group.
        Function<String, Optional<String>> getGroup = (username) -> Optional.of("admins");

        // Get the group for the user root and execute admin-stuff if 
        // it belongs to the admin group.
        Boolean executed = getGroup.apply("root")
                .filter("admin"::equals)
                .map(group -> {
                    // Execute the admin stuff
                    return true;
                })
                .orElseGet(() -> {
                    Logger.error("Permission denied.");
                    return false;
                });

        System.out.println(executed);

Using these methods one can chain logic in an easy and readable way, just by playing the Optionals.

The following is almost directly from a program I made a while ago, and I think everyone, even non-programmers, can easily follow what it does:

        Optional.ofNullable(incomingFile)
                .filter(this::validFile)
                .filter(this::validSize)
                .map(this::getArchiveDir)
                .map(archiveDir -> createIfNotExist(archiveDir))
                .map(archiveDir -> move(incomingFile, archiveDir))
                .map(archivedFile -> DB.insert(Type.byFile(incomingFile), archivedFile))
                .ifPresent(DbStoreFile -> 
                        Logger.info("{} stored successfully.");
                );

Play Framework 2.0 – javascriptRouter in Java

Posted in Stuff by franzgranlund on 29 March, 2012

* * * UPDATE * * *
The code now supports Play Framework version 2.0.2.

I asked on Stackoverflow if there was any equivalent to Play Framework 1.2’s jsAction in Play Framework 2.0 and got pointed to helper.javascriptRouter-tag. Unfortunately Play 2.0 lacks documentation about how to use it and it took a while to figure out. Plays sample-application zentasks makes use of javascriptRouter, but it is a bit hard to follow, so here is an easier example.

Create a new Java project, let’s call it jsrouter:

$ play new jsrouter
$ cd jsrouter
$ play run

Create two new methods in Application.java, plus and minus. Both methods will take 2 strings as arguments. The strings will be converted to Integers and either added or subtracted with each other. The answer will be rendered on a small template called ajax_result.scala.html. We also need to create one last method that will return the javascript that sets up the routes for us. We’ll call it javascriptRoutes.

Application.java should look like this:

package controllers;

import play.*;
import play.mvc.*;

import views.html.*;

public class Application extends Controller {

  public static Result index() {
    return ok(index.render("Your new application is ready."));
  }

  public static Result plus(String num1, String num2) {
	  Integer answer = Integer.valueOf(num1) + Integer.valueOf(num2);
	  return ok(ajax_result.render(answer));
  }

  public static Result minus(String num1, String num2) {
	  Integer answer = Integer.valueOf(num1) - Integer.valueOf(num2);
	  return ok(ajax_result.render(answer));
  }

  public static Result javascriptRoutes() {
    response().setContentType("text/javascript");
    return ok(
      Routes.javascriptRouter("jsRoutes",
        // Routes
        controllers.routes.javascript.Application.plus(),
        controllers.routes.javascript.Application.minus()
      )
    );
  }

}

Now, create the template that will be loaded by our ajax, ajax_result.scala.html:

@(result: Int)
@result

Set up your routes file:

# Routes
# Home page
GET    /                               controllers.Application.index()

GET    /plus                           controllers.Application.plus(num1: String, num2: String)
GET    /minus                          controllers.Application.minus(num1: String, num2: String)

# Javascript routing
GET    /assets/javascripts/routes      controllers.Application.javascriptRoutes()

# Map static resources from the /public folder to the /assets URL path
GET    /assets/*file                   controllers.Assets.at(path="/public", file)

Now for the fun part, including the javascript. In index.scala.html:

@(message: String)

@import helper._
@import controllers.routes.javascript._

@main("Welcome to Play 2.0") {

  <script type="text/javascript" src="@routes.Application.javascriptRoutes"></script>

  <input type='text' id='num1'/>
  <input type='text' id='num2'/>
  </br>
  <input type='button' value='+' id='plusBtn' />
  <input type='button' value='-' id='minusBtn' />
  <br />
  <div id="result" />

  <script type="text/javascript" charset="utf-8">
    var plus = function() {
      var num1 = $('#num1').val();
      var num2 = $('#num2').val();

      jsRoutes.controllers.Application.plus(num1,num2).ajax({
        success: function(data) {
          $("#result").html(data);
        },
        error: function() {
          alert("Error!")
        }
      })
    };

    var minus = function() {
      var num1 = $('#num1').val();
      var num2 = $('#num2').val();

      jsRoutes.controllers.Application.minus(num1,num2).ajax({
        success: function(data) {
          $("#result").html(data);
        },
        error: function() {
          alert("Error!")
        }
      })
    };

    $('#plusBtn').click(plus);
    $('#minusBtn').click(minus);
  </script>

}

If you run the page in your browser you should see 2 inputs, plus and a minus button. Entering numbers in the inputs and pressing one of the buttons will call, with ajax, either the Application.plus or Application.minus method and load the result into the result-div. The magic here is of course that Application.javascriptRouter will generate javascript-functions, based on your routes, making it easy to use from the other javascripts on your page.

If you open your inspector in your favorite web browser you will see that when pressing buttons it will send GET http://localhost:9000/plus?num1=42&num2=34

Just for fun, if you change the plus route in the routes file to this:

GET		/plus/:num1/:num2			controllers.Application.plus(num1: String, num2: String)

then your GET will automatically begin to look like GET http://localhost:9000/plus/45/23

Good luck.

Life before Google

Posted in Stuff by franzgranlund on 12 July, 2010

5 myter om programmering

Posted in Stuff by franzgranlund on 12 July, 2010

5 myter om programmering:

  • More documentation is always better.
  • Programmers can be equated.
  • Resources can be added to a late project to speed it.
  • It is possible to estimate software development reliably.
  • Programmers’ productivity can be measured in terms of some simple metric, like lines of code.

Läs mer om How to be a Programmer här. Väldigt bra läsning för stora och små.

Chase Jarvis berättar om deras workflow

Posted in Stuff by franzgranlund on 6 July, 2010

Fotografen Chase Jarvis berättar om hur deras workflow fungerar. Intressant video som även passar in på annat än fotografering.

Panic Status Board – vill ha!

Posted in Stuff by franzgranlund on 8 June, 2010

Panics ursnygga blogg så hittar man en riktigt kul grej som de snickrat ihop. En Status Board för pågående projekt, twitter-feeds, tågtidtabeller osv.

Lek runt med JavaScript

Posted in Stuff by franzgranlund on 4 June, 2010

Hittade en trevlig sida som låter en testa dina JavaScript-koder direkt. Sidan kallas jsFiddle och är ännu i utvecklingsskedet, men funkar rätt hyfsat ändå.

MobileMe Mail Beta

Posted in Stuff by franzgranlund on 25 May, 2010

Hoppsan, fick visst tillgång till MobileMe Mail Betan! De verkar ha slipat upp det en hel del vilket är trevligt. Det är denna version man skulle vilja ha med i Mac OS X Server!

Väska värdig MacBook Pro?

Posted in Stuff by franzgranlund on 15 May, 2010

En av sakerna som skulle införskaffas under shopping-resan till Helsingfors var en väska till vår MacBook Pro. Vi hade redan före kollat in olika alternativ och fastnat för en Knomo Stirling. När vi väl såg dem i verkligheten så föll intresset för den liggande varianten av samma väska, d.v.s. Knomo Bristol.

Väskan ser snygg ut och man märker att det är lite mera kvalitet och still än andra laptop-väskor. Detta märks också på prislappen.. MacBook Pro 15″arn passar perfekt i väskan och känns riktigt bra skyddad, även utan sleeve.


Knomos väskor har också små detaljer här och där, vilket höjer kvalitets-känslan. Jag har alltid varit lite småkär i de där pyttesmå detaljerna som bara vissa lägger märke till.


Givetvis var jag tvungen att införskaffa ett matchande iPhone-fodral till väskan. Min fästmö passade även på att skaffa ett matchande iPhone-fodral till barnvagnen.

Stackars liten

Posted in Stuff by franzgranlund on 14 May, 2010

Städerskan för vårt hotellrum kan inte ha haft det lätt som liten med detta namn..