Concetto IT

To content | To menu | To search

Thursday 28 January 2016

Null safety in modern programming languages

This is the first part of a blog serie about modern programming languages. This part is about null safety, one of the annoying things in for example the Java programming language. How many times have you seen something like this:


 if(value != null && !value.equals("")) {  
   // do something  
 }  

or ( sometimes called defensive programming...)


 public String foo(String bar) {  
   if (bar == null) {  
     return null;  
   }  
   // do something  
 }  

Today’s IDE’s give you a warning when a variable may be referencing to null but even when you add null checks your code will be less readable, maintainable etc. So, what can we do about it?

Options

Functional programming languages model the absence of a value with an Option type of Maybe type since the start. The Scala language has an Option type and Java 8 now also has an Optional type. The main purpose of the Optional type in Java is to reduce the number of NullPointerExceptions. The combination of Optionals and Lambda expressions is really powerful. When used properly it is hard to produce NullPointerExceptions. The main problem is the readability of the code. For example, we want to check if a persons address has a country:


 public boolean hasCountry(Optional<Person> person) {  
   return person.map(p -> p.address)  
       .map(a -> a.country)  
       .isPresent();  
 }  

Because of backward compatibility the only place in Java 8 were Optionals are used is the Streams API: http://docs.oracle.com/javase/8/docs/api/java/util/class-use/Optional.html Luckily other languages have implemented more advanced mechanisms to prevent NullPointerExceptions.

Safety

In Kotlin, a language developed by Jetbrains, this can be expressed more easily in a one liner. An optional value is marked with a question mark and optionals can be chained:


 class Person {  
   val address: Address?  
   constructor(address: Address?) {  
     this.address = address  
   }  
 }  
 class Address {  
   var country: String?  
   var city: String  
   constructor(country: String?, city: String) {  
     this.country = country  
     this.city = city  
   }  
 }  
 fun hasCountry(person: Person?) : Boolean {  
   return person?.address?.country != null;  
 }  

The Kotlin compiler enforces that you can not pass null values to non-optional variables!

The Swift language is developed by Apple to replace the Objective-C language and claims to be a safe language. The language itself still has notion of null values (nil).


 struct Person {  
   var name : String;  
   var address : Address?  
 }  
 struct Address {  
   var city : String  
   var country: String?  
 }  
 let address = Address(city: "Utrecht", country: nil)  
 let person = Person(name: "test", address: address)  
 print(person.address?.country == nil)  

If we don’t declare the country variable as an optional string the code above will not compile.

The Rust language is designed to be a safe alternative to the C language and has some really cool safety features. For example you can never access a variable that is not initialised. See the first line in the main function, country must have a default value, if we do not declare a default value the code will not compile.


 struct Person {  
  name: String,  
  address: Option<Address>,  
 }  
 struct Address {  
  city: String,  
  country: Option<String>,  
 }  
 fn main() {  
  let address = Address { city: "utrecht".to_string(), country: Default::default()};  
  let person = Person { name: "a person".to_string(), address: Some(address) };  
  println!("Country is set? {}", person.address.unwrap().country.is_some());  
 }  

The compiler of both Rust and Swift is really helpful for the programmer. You have to explicitly declare variables as options in order to use the null reference in Swift. The Rust language does not know about the null reference at all.

More info about:

Kotlin - https://kotlinlang.org/
Swift - https://developer.apple.com/swift/
Rust - https://www.rust-lang.org/

Wednesday 30 September 2015

Microservices and Kerberos authentication

Kerberos authentication is used to secure a variety of big data products like Apache Hadoop and more recently Apache Kafka (>0.9). In case of Hadoop it is used to authenticate each user and service in order to use the Hadoop ecosystem. Also a lot of modern NoSQL databases offer support for Kerberos, for example Apache Cassandra and MongoDB. Kerberos authentication can also be useful in microservice architectures. It can be used to achieve single sign on functionality. A property that is less known is the possibility to delegate tokens to sub services.

Continue reading...

Thursday 2 July 2015

Mapping complex JSON structures with JDK8 Nashorn

How can you map a complex JSON structure to another JSON structure in Java? I think there are a few possible solutions in Java.

The first solution is to use a serialization framework like Jackson, GSON or smart-json. The mapping is a piece of awkward Java code with a lot of if-else conditions. The result is hard to test and hard to maintain. Schematic it looks like this:

JSON -> Java objects -> Mapping -> Java objects -> JSON

An second approach is to use a templating framwork (like Freemarker or Velocity) in combination with a serialization framwork. The logic of the mapping has moved to the template. Schematic it looks like this:

JSON -> Java objects -> Apply template -> JSON

One of the issues with this approach is that the template must enforce that the result is a valid JSON structure. I have tried this approach and it is really hard to produce a valid JSON structure in all use cases.

You could also map your JSON to XML and create the mapping with an XSL transformations. Schematic it looks like this:

JSON -> XML -> XSL transformation -> XML -> JSON

But the ideal schema looks like this:

JSON -> Mapping -> JSON

With JDK 8 and the Nashorn Javascript engine this becomes possible! This implementation provides JSON.parse() and JSON.stringify() by default.

Example Javascript:

function convert(val) {
  var json = JSON.stringify(val);
  var g = JSON.parse(json);
  var d = {
    chunkId: g.chunk.id,
    timestamp: g.chunk.timestamp
  };
  return JSON.stringify(d);
}

Java code:

private ScriptEngineManager engineManager;
private ScriptEngine engine;
public MyConverter() {
  ClassPathResource resource = new ClassPathResource("/converter.js");
  InputStreamReader reader = new InputStreamReader(resource.getInputStream());
  engineManager = new ScriptEngineManager();
  engine = engineManager.getEngineByName("nashorn");
  engine.eval(reader);
}
public String convert(String val){
  return (String) engine.eval("convert(" + source + ")");
}

I think this is -at the moment- the best approach, Java 9 will ship with native JSON support. Perhaps it will become more easier in the future.

Thursday 4 June 2015

Application testing with Protractor

Protractor is a framework to test Angular applications. It runs tests against your application in a browser, like Chrome or Firefox. You can use it for end-to-end testing but it’s is also possible to mock the backend services. In this blog we focus on the last option: mocking the backend services. There is a lot of information available on this topic on the internet but a lot of this information is outdated. Even the AngularJS website does not explain in detail how to mock your backend services.

This blog will explain how to setup a Protractor test and how to mock your backend services with the ngMockE2E module of AngularJS. There are also a lot of external frameworks on Github available but I think there is no reason to use these frameworks.

First, you have to make sure you have installed Protractor correctly. After that you have to make sure you load the angular-mocks javascript file (angular-test.js) in your application.

When testing an application we don’t want to mix test code and real application code. Luckily Protractor is able to load mock modules in your Angular application from your test code. See line 10 in the following test. (I have used Jasmine to write this test)


1:  describe('view1', function() {
2:   beforeEach(function() {
3:    var mock = function() {
4:     var module = angular.module('myMockApp', ['ngMockE2E']);
5:     module.run(function($httpBackend) {
6:      $httpBackend.whenGET('http://localhost:8080/test').respond({ dummy: 'test'});
7:      $httpBackend.whenGET('view1/view1.html').passThrough();
8:     });
9:    };
10:    browser.addMockModule('myMockApp', mock);
11:    browser.get('index.html#/view1');
12:   });
13:   afterEach(function(){
14:    browser.clearMockModules();
15:   });
16:   it('should render view1 when user navigates to /view1', function() {
17:    // expectations
18:   });
19:  });

After each test we clean up the mocks because we don’t want to influence other test scripts. (Line 14)

How does it work?

The following diagram from the Protractor documentation explains a lot.

In our test script we got a browser object which can instruct the real browser. So what happens if we call the function addMockModule?

  1. There will be a HTTP call from the NodeJs test to the Selenium server
  2. The Selenium server will forward the request to the browser and AngularJS will add the module to module list. The context of this module is the browser!

Synchronous communication

The example described above failed to work initially for our application. The mock was loaded but the Angular application was already started and looking for the view template. The result was a HTTP 404. The underlying problem was the configuration of our i18nextProvider. This module was configured to load the language files synchronously and causes latency on the main thread of our application.

If you have any questions or remarks please add a comment to this post.

Friday 17 April 2015

Uitbreiden van externe library's in Scala

Veel big data frameworks zoals Spark en Kafka zijn geschreven in Scala waardoor ik soms niet de exacte werking weet van een stuk code. In Scala kun je op verschillende manieren programmeren (functioneel, object georiënteerd) dat je niet snel uitgeleerd bent. Zo kwam ik tijdens het gebruik van de Spark Cassandra connector een stuk code tegen dat me nieuwsgierig maakte naar de precieze werking.

Met behulp van de Spark Cassandra connector is het mogelijk om datasets vanuit Cassandra in Spark jobs te gebruiken en weer weg te schrijven in Cassandra. Je kunt bijvoorbeeld een dataset inladen, verschillende aggregaties maken en vervolgens de resultaat set opslaan in een nieuwe tabel.

Allereerst wordt er een Spark configuratie aangemaakt:

1
2
3
4
5
val conf = new SparkConf(true)
.set("spark.cassandra.connection.host", "192.168.123.10")
.set("spark.cassandra.auth.username", "cassandra")
.set("spark.cassandra.auth.password", "cassandra")
val sc = new SparkContext("local[*]", "test", conf)

Een import toegevoegd:

1
import com.datastax.spark.connector._

Hierdoor zijn er extra methodes beschikbaar gekomen op de SparkContext en de RDD’s:

1
2
val rdd = sc.cassandraTable("test", "words")
rdd.toArray.foreach(println)

Hoe is dit mogelijk?

De functies zijn zelfs tijdens het compileren beschikbaar?! In de object georiënteerde taal Java wordt o.a. inheritance (overerving) gebruikt om functionaliteit uit te breiden. Dat is vaak bruikbaar als het om eigen code gaat maar helaas minder bruikbaar als het om externe library’s gaat zoals in bovenstaand voorbeeld. Om deze reden heeft Scala een feature genaamd impliciete type conversies. (implicit type conversions)

Hoe werkt het precies?

Normaal gesproken zou de volgende code niet compileren:

1
val rdd = sc.cassandraTable("test", "words")

De scala compiler is echter zo slim om opzoek te gaan naar functies die een type conversie maken. Doordat we een import statement hebben toegevoegd wordt zo’n type conversies ingeladen:

1
2
3
4
5
package object connector {
implicit def toSparkContextFunctions(sc: SparkContext): SparkContextFunctions =
new SparkContextFunctions(sc)
...
}

En de SparkContextFuncties ziet er als volgt uit:

class SparkContextFunctions(@transient val sc: SparkContext) extends Serializable {
  
  def cassandraTable[T](keyspace: String, table: String)
                       (implicit connector: CassandraConnector = CassandraConnector(sc.getConf),
                        readConf: ReadConf = ReadConf.fromSparkConf(sc.getConf),
                        ct: ClassTag[T], rrf: RowReaderFactory[T],
                        ev: ValidRDDType[T]) =
    new CassandraTableScanRDD[T](sc, connector, keyspace, table, readConf = readConf)

}

Met behulp van impliciete type conversies is het dus mogelijk om externe library’s aan te passen. Het is een krachtig mechanisme om interfaces en methode's toe te kunnen voegen aan bestaande code. Gebruik het echter voorzichtig. De werking is niet direct zichtbaar en je moet naar de import statements kijken om te zien hoe de code precies werkt. En dat laatste doe je niet zo snel.

Friday 27 March 2015

Minimaliseer kosten en maximaliseer kwaliteit met end-to-end testing met behulp van Protractor en Docker

Een end-to-end test wordt gebruikt om een keten te testen, je zou het ook een integratie test kunnen noemen. Een van de tools die hiervoor gebruikt kan worden is Selenium. Mijn ervaring met deze tool is echter niet zo best. Het is moeilijk om goede testen te schrijven omdat er allerlei sleep commando's nodig zijn en het onderhouden van de scripts is zelfs nog moeilijker. Het testen van een applicatie wordt zo een handmatig proces en dat is niet wenselijk. Organisaties willen namelijk snel nieuwe versies van software 'live' kunnen zetten om in te kunnen spelen op de veranderende vraag van hun klanten. Protractor is een tool die hiervoor een oplossing biedt.

Protractor

Met Protractor kun je eenvoudig een AngularJS applicaties testen. Het voorkomt dat je in een test allerlei sleep commando's moet zetten en verkort daardoor de doorlooptijd van het geautomatiseerd testen. Het kan ook eenvoudig geïntegreerd worden met bouw proces van de software. Onderliggend maakt Protractor gebruik van WebDriverJS, een onderdeel van Selenium en draait het op Selenium test server. Uiteindelijk draaien de testen in een echte browser en wordt het gedrag van een echte gebruiker nagespeeld. Mijn eerste ervaringen mij de tool zijn -ondanks dat ik eerst vrij sceptisch was- erg positief.

Een ander probleem bij end-to-end testen is de test omgeving. Hoe zorg je er bijvoorbeeld voor dat altijd de zelfde uitgangspositie voor een test run gebruikt wordt? En hoe maak je als organisatie efficient gebruik van de test omgevingen? De kosten voor het in de lucht houden van allerlei test omgevingen kunnen hoog zijn. En hoe ga je om met wijzigingen in de infrastructuur, bijvoorbeeld een upgrade van een database versie? Om deze vragen te omzeilen heb ik mijn eerste Protractor testen gemaakt zonder echte back-end services maar met behulp van mocks. Hierdoor is er geen sprake meer van een echte end-to-end test. Gisteravond heb ik een sessie bezocht bij Quintor over het gebruik van Docker in enterprise omgevingen en ik denk dat Docker een antwoord is op de eerder genoemde vragen.

Docker

Met behulp van Docker kun je op een eenvoudige manier containers maken die bepaalde services leveren. Zo zou je een container kunnen maken die een applicatie server (bijv Tomcat) dienst levert met daarop enkele web applicaties. Het enige dat je moet maken in een configuratie bestand waarin je de container beschrijft. Met behulp van docker compose kun je vervolgens een compositie maken van zulke containers. Zo kun je een hele testomgeving opbouwen. Het idee is dat een docker container binnen aantal seconden opstart. Door het gebruik van een versie beheer systeem kun je versies bijhouden van een configuratie. Zo kun je eenvoudig een oudere versie gebruiken om een bug fix van een productiesysteem te testen.

Het gebruik van Docker en Protractor stelt je dus in staat om echte integratie testen te maken. Als je het geheel ook nog integreert in het bouw proces van de software op bijvoorbeeld Jenkins kun je een testomgeving ad-hoc opbouwen om je Protractor testen uit te voeren. Zodra het bouwproces klaar is laat je de testomgeving weer afbreken. Op die manier kun je heel efficient met je resources om gaan en wordt de software continue getest. Zo kunnen de kosten gereduceerd worden en wordt de kwaliteit van het uiteindelijk product gewaarborgd.

Wil je meer weten over het gebruik van Docker? Op 14 april wordt er een herhaal sessie georganiseerd door Quintor. En op 16 april organiseert Flusso een IT-Krachtsessie over het gebruik van Docker.

Monday 2 March 2015

Excepties of return values?

Elke programmeertaal heeft zijn eigen constructies om met fouten om te gaan. In Java zijn dat er twee: excepties en return values. Deze constructies worden vaak door elkaar gebruikt waardoor er snel verwarring kan ontstaan. Zo kwam ik afgelopen weekend tijdens het opruimen van de kranten en tijdschriften het Java magazine van de NLJUG tegen. Altijd leuk om even door te bladeren. In het eerste artikel kwam ik het volgende stuk Java code tegen:

public boolean save(final User user) {
    entitymanager.persist(user);
    return user.getId() != null;
}

Deze functie persisteert een Java object -user- in de database door gebruik te maken van de methode persist op de entitymanager. De API van de EntityManager van Java.

Wat mij opvalt is dat de persist functie van de EntityManager geen waarde retourneert. Wat de meeste programmeurs verwachten is dat de persist functie op regel 2 aangeeft of het opslaan gelukt is door gebruik te maken van een boolean return type. Een heleboel database drivers doen dat doet op die manier. Dan krijg je het volgende:

public boolean save(final User user) {
    return entitymanager.persist(user);
}

Omdat de EntityManager deze logica niet bevat heeft de auteur van het artikel deze logica zelf geïmplementeerd.

Maar is dat verstandig?

Door te checken of het id van het user object een verwijzing naar NULL bevat kan blijkbaar afgeleid worden of het user object correct is opgeslagen. In de persist functie van de EntityManager wordt kennelijk het user object zo aangepast dat het id gezet is.

Het stuk code dat de save functie aanroept moet nu de situatie afhandelen dat het opslaan niet lukt, en daar op een goede manier mee omgaan:

public void registerUser(User user) {
     boolean result = save(user);
     if(!result) {
         // handel fout situatie af
     }
} 

Nu is het probleem dat de EntityManager van Java EE gebruik maakt van excepties om fout situaties af te handelen. Namelijk een EntityAlreadyExists, IllegalArgument en een TransactionRequired exceptie. Het stuk software dat de EntityManager gebruikt mag er dus vanuit gaan dat het opslaan gelukt is tenzij er een exceptie optreedt. Het stuk code uit het Java magazine zet je dus op het verkeerde spoor en is niet goed geprogrammeerd. De save functie zal altijd true retourneren of een exceptie gooien.

Uit bovenstaand voorbeeld blijkt dat de Java programmeer taal meerdere manieren bevat om met foutsituaties om te gaan en dat hiermee snel fouten worden gemaakt. Zelfs door ervaren programmeurs. Hoe gaat dit in andere talen?

Scala

De programmeertaal Scala kent vergelijkbare exception afhandeling als Java maar biedt daarnaast twee extra concepten aan. In de eerste plaats het Option data type. Dit data type kun je gebruiken om aan te geven dat een functie niet altijd een waarde retourneert. Aanroepende code moet beide situaties, een return value of geen return value expliciet afhandelen. In de tweede plaats is er het Either data type waarmee je aan kunt geven dat het return type verschillend kan zijn. Bijvoorbeeld een String voor een foutbericht en een Double voor de uitkomst van een berekening. Door middel van Option en Either kun je veel fout situaties afhandelen. De noodzaak om excepties te gebruiken verdwijnt op deze manier en aanroepende code weet veel beter welke situaties het moet afhandelen.

Go

De go programmeer taal (golang) bevat een vergelijkbaar principe. Go bevat namelijk een Error data type en helemaal geen excepties. NB: Een functie in Go kan meerdere return values hebben. Zie onderstaand voorbeeld:

func Open(name string) (file *File, err error)

De functie Open retourneert een file en een error object. Door te checken of het error object naar NULL verwijst kun je controleren of er een error opgetreden is.

f, err := os.Open("filename.ext") 
if err != nil {     
  log.Fatal(err) 
} 
// do something with the open *File f

Voor meer informatie zie de blog op GoLang website.

Het is goed om te zien dat zowel Scala als Golang andere mechanismen aanbieden om met fout situaties om te gaan. Go heeft een heel helder uitgangspunt, het gebruik van excepties leidt tot onnodig ingewikkelde programmeerconstructies (try-catch-finally) en onvoorziene situaties zoals een reeds geopende file moeten afgehandeld worden en zijn vaak niet exceptioneel. Scala biedt meerdere manieren aan en het is aan de programmeur om een geschikt mechanisme te kiezen.

Friday 20 February 2015

The imitation game

Sometimes it is the people no one can imagine anything of who do the things no one can imagine.” - Alan Turing

De imitation game is een film over het leven en werk van Alan Turing en is een absolute aanrader! In de film komen een hoop ethische / morele aspecten aan bod die de film erg interessant maken. De film is inmiddels bekroond met vele awards en nominaties.

Wie was Alan Turing? Alan Turing zou je kunnen zien als een van de grondleggers van machines en computers zoals we die nu kennen. Hij is geboren in 1912, was wiskundige, en heeft belangrijk werk verricht tijdens de 2e wereldoorlog. Lange tijd is dat werk verborgen gebleven omdat er een zware geheimhouding op ruste. Sinds een paar jaar is er meer over bekend geworden doordat er een boek over zijn leven en werk geschreven is. De film is geïnspireerd op het boek en is te zien op het witte doek.

In de film staat het kraken van de Enigma code centraal. De Enigma codering werd door de nazi's gebruikt om hun onderlinge militaire communicatie te beveiligen. Door middel van een codeer machine werden berichten versleuteld, en vervolgens werden de berichten verstuurd. Aan de ontvangende kant werden de versleutelde berichten door een zelfde codeermachine weer omgezet naar begrijpbare woorden. Alan Turing probeert in de film samen met groep wetenschappers de Enigma code te kraken wat ze uiteindelijk lukt door de inzet van een door hen zelf ontwikkelde machine. Vervolgens is er een dilemma omdat de Duitsers niet mogen weten dat de Enigma code is gekraakt. Er moet dus erg zorgvuldig met de verkregen informatie omgegaan worden. Er wordt door sommigen geschat dat de oorlog twee jaar korter geduurd door het werk van Turing.

In 2013 is Alan Turing postuum gratie verleend door Koningin Elizabeth. Turing werd in 1952 namelijk veroordeeld voor homoseksualiteit, in 1954 pleegde hij zelfmoord. Door de gratie heeft hij eerherstel gekregen.

Waarom een blog over deze film? In de eerste plaats omdat het een erg mooie film is maar ook vanwege de actualiteit. In hoeverre is bijvoorbeeld de berichten versleutelingen die we gebruiken op het internet (HTTPS) door anderen af te luisteren? En zijn bijvoorbeeld onze internet bankieren transacties nu of later af te luisteren? Deze week kwam computer fabrikant Lenovo nog in het nieuws omdat de software op hun laptops voorzien was van malware waardoor het HTTPS verkeer af te luisteren zou zijn. Daarnaast is er nog steeds een continue berichten stroom over het werk van de NSA. En de hack bij Diginotar kan iedereen zich ook nog goed herinneren.

Begin deze maand kwam er een grappig bericht in het nieuws. Tijdens de renovatie van het gebouw waar Alan Turing werkte tijdens de tweede wereld oorlog zijn in de dakisolatie aantekeningen gevonden van Turing. In plaats van de aantekeningen te vernietigen, gebruikte hij ze om de kou buiten te houden.

Friday 6 February 2015

Grafieken maken met AngularJS, FlotCharts en ElasticSearch

Op een dashboard nemen grafieken vaak een prominente plaats in. Een bekend voorbeeld hiervan is het Kibana dashboard. Een Kibana dashboard kan bijvoorbeeld gebruik maken van een ElasticSearch als data bron.

Recent heb ik met behulp van AngularJS en FlotCharts een document stroom gevisualiseerd. De data komt uit ElasticSearch. FlotCharts werkt met behulp van JQuery en is verassend flexibel. Zo kun je bijvoorbeeld met plugins de mogelijkheid toevoegen om in te kunnen zoomen, tooltips weer te geven en een mooie curve te maken ipv vlakke lijnen.

FlotChart1

In bovenstaande grafiek is het aantal documenten te zien per tijdseenheid. Geannoteerde documenten hebben een tooltip en d.m.v. een hover actie krijg je de tooltip te zien.

De data komt uit ElasticSearch en wordt met behulp van een datum histogram aggregatie berekend. Bij zo’n aggregatie kun je aangeven of de data per uur geaggregeerd moet worden of bijvoorbeeld per 5 min. Ook kun je subaggregaties toevoegen. In bovenstaand voorbeeld is dat gebeurd om het aantal annotaties per tijdseenheid te berekenen.

Door in te zoomen kun je meer details opvragen. Op de achtergrond wordt een nieuw data verzoek gedaan. De data is nu op een lager detail niveau geaggregeerd. In onderstaand voorbeeld is dat 1 min.

FlotChart2

De grafiek wordt elke minuut geupdate met nieuwe informatie. De AngularJS directive angular-flot zorgt ervoor dat de grafiek opnieuw gerenderd wordt. Dat wil zeggen dat de data vernieuwd wordt en de x-as en de y-as opnieuw berekend worden.

Ik ben met name te spreken over de flexibiliteit van de FlotChart library. Het optioneel weergeven van tooltips lijkt misschien lastig maar is in de praktijk erg makkelijk. Je kunt namelijk per grafiek meerdere datasets gebruiken die elk hun eigen opmaak instellingen hebben.

Thursday 13 November 2014

What's next?

Apache Flink

De Nederlandse Hadoop User Group organiseert 11 december een meeting over Apache Flink. Sinds enkele maanden heeft dit project de incubator status bij Apache. Vertaal je Flink van het Duits naar het Engels dan krijg je iets als 'nimble', 'agile' of 'speedy'. Vanuit het duits omdat het een project is dat gestart is door de TU van Berlijn.

Apache Flink is een alternatief voor Apache Spark en werkt op een vergelijkbare manier. Het idee van deze frameworks is dat je operaties definieert op datasets en dat deze operaties automatisch over een cluster verdeeld worden. Beide frameworks kunnen draaien op Hadoop maar kunnen ook standalone functioneren.

Vanmiddag bestudeerde ik samen met een collega de API van Apache Flink en de overeenkomsten tussen Apache Flink en Spark zijn erg groot. Zo groot dat je je afvraagt waarom er een nieuw project gestart is. Gelukkig zijn er wel verschillen. Apache Flink bevat namelijk een soort 'optimizer' die de applicatie code optimaliseert. Een concept dat je ook terug ziet komen in relationele databases. De programma code die de operaties en data sets definieert wordt dus eerst geoptimaliseerd voordat het uitgevoerd wordt. Een logisch gevolg is dat de executie niet altijd op een gelijke wijze plaast vindt. Ik ben erg benieuwd hoe dit in de praktijk werkt en wat voor invloed het heeft op de correctheid van applicaties.

Cinch

Ander nieuws. Afgelopen week is de eerste versie van Cinch gereleased. Cinch is een framework dat er voor zorgt dat Spring componenten binnen Apache Spark kunnen draaien. Op die manier hoeft de programmeur zich bijvoorbeeld niet druk te maken over het inlezen van property files, het aanmaken en afsluiten van allerlei connecties. Spring regelt dit en nu dus ook binnen Apache Spark. De code is beschikbaar op Github.

Thursday 6 November 2014

OpenStack en Hadoop

Een collega tipte mij afgelopen week over een interessante ontwikkeling.

De laatste OpenStack release 'juno' bevat namelijk de mogelijkheid om big data applicaties te draaien in OpenStack. Door de module Sahara wordt dit mogelijk gemaakt. Het mooie is dat de laatste release het zelfs mogelijk maakt om Spark jobs binnen OpenStack te draaien, echter nog niet via YARN of Mesos maar in standalone mode.

Het doel van het Sahara project is om op een eenvoudige manier Hadoop clusters te kunnen draaien binnen OpenStack. Door een Hadoop versie op te geven en bijvoorbeeld enkele hardware eisen wordt er een nieuw cluster uitgerold in enkele minuten. Amazon biedt al enkele tijd vergelijkbare mogelijkheden met het Amazon Elastic MapReduce.

Het mooie van deze ontwikkeling is dat er een diepe integratie ontstaat tussen Hadoop en OpenStack. Het gaat veel verder dan alleen een paar VM's met Hadoop draaien bovenop OpenStack want dat kon natuurlijk al lang. :-)

Bronnen:

http://www.zdnet.com/openstack-hook...
http://docs.openstack.org/developer...
http://docs.openstack.org/developer...
http://docs.openstack.org/developer...
http://aws.amazon.com/elasticmapred...

Friday 31 October 2014

Functioneel programmeren

Vijftien jaar geleden kreeg ik op de universiteit onderwijs over Functioneel progammeren. Dat gebeurde destijds aan de hand van de taal Miranda. We moesten daar destijds allerlei leuke opdrachten bij maken. Ik herinner mij nog opdrachten zoals het maken van een Fibonacci reeks, het boer, wolf, schaapen witlof raadsel etc. Deze reeksen en raadsels moetsen dan opgelost worden in een functioneel progamma.

De afgelopen jaren heb ik niet geprogrammeerd in een functionele taal maar met de komst van lambda expressies in Java 8 en het gebruik van Apache Storm en later Apache Spark en bovendien een collega die de Coursera cursus over Scala gevolgd heeft is het hoog tijd om mijn kennis op te frissen. Vandaar dat ik het boek gekocht heb van Paul Chiusano en Runar Bjarnson.

Gisteren heb ik het eerste hoofdstuk gelezen en ik ga zeker verder lezen. Het leuke is namelijk dat de auteurs er niet op uit zijn om je te leren programmeren in Scala maar veel meer om je te leren Functioneel te programmeren.

Functioneel programmeren wordt in hoofstuk 1 van het boek omschreven als het programmeren met 'pure' functies. Het woord pure wil zeggen dat de functies geen neven of bij effecten mogen hebben. De claim van de auteurs is dat zulke functies leiden tot modulaire programma's. Ik ben benieuwd. Ik herinner me namelijk nog dat een hele hoop dingen niet konden met Functioneel programmeren. Bijvoorbeeld user interfaces, gebruik van IO, netwerk enz. Met de komst van talen als Scala en Clojure is er waarschijnlijk een einde gekomen aan deze beperkingen.

De komende weken ga ik het boek lezen en de bijbehorende opdrachten maken en wellicht er nog een blog over schrijven. :-)