Aan de slag met Java embedded – Een kijkje in de Early Access-versie van Java Micro Edition (ME) 8

Als we de laatste trends mogen geloven, dan breekt een nieuwe revolutie aan: ‘The Internet of Things’. Dit is een paraplubegrip dat appelleert aan de vergaande sociale acceptatie omtrent het gebruik van technologie in ons dagelijks leven en de nieuwe creatieve mogelijkheden die technologie ons vandaag de dag biedt. Technologie maakt reeds een integraal onderdeel uit van ons leven. Vele mensen hebben zelfs het gevoel dat ze niet meer zonder kunnen.

Hardware wordt krachtiger, kleiner en vooral goedkoper. Steeds meer apparaten hebben reeds een microprocessor en toegang tot een netwerk of het internet, zodat data gedeeld kan worden. Dit biedt vele nieuwe mogelijkheden om alledaagse zaken te automatiseren, te vereenvoudigen of om apparaten aan elkaar te koppelen en intelligenter te maken. Met intelligente apparaten worden vaak apparaten en applicaties bedoeld die complexe processen automatiseren, een bepaalde interactie aangaan met een mens of met een andere machine. Daarnaast kunnen intelligente apparaten autonoom handelen als gevolg van (sensor)input of enkel het gevoel geven aan de gebruiker dat er meegedacht wordt. ‘The Internet of Things’ is een nogal breed en allesomvattend begrip dat regelmatig uit zijn context gebruikt wordt.

Software speelt een steeds belangrijkere rol om intelligente technologie mogelijk te maken. Oracle neemt positie in deze opkomende markt met Java Micro Edition (ME) 8. De release datum staat gepland in maart 2014. Java ME 8 Early Access ondersteunt momenteel STMicro 32-F4 (ARM Cortex-M4), Raspberry Pi (ARM 11/Linux) en Windows. Een apparaat heeft minimaal 128 KB RAM en 1MB Flash/ROM nodig voor Java ME, naast een embedded kernel of operating system met een netwerk verbinding. De ‘Early Access’-versie van Java ME 8 is reeds beschikbaar op de Oracle website. In dit artikel gaan we aan de slag met deze ‘Early Access’-versie.

Features

Een belangrijk onderdeel van Java ME 8 is Connected Limited Device Configuration (CLDC) 8. Deze JSR, nummer 360, heeft als doel Java ME verder te integreren met de Standaard Edition (Java SE). Dit betekent dat features die tegenwoordig voor een SE of enterprise (EE) ontwikkelaar als vanzelfsprekend ervaren worden, nu ook in Java ME beschikbaar zijn. Je moet dan denken aan zaken zoals generic types, annotations, enumerations, auto-boxing, enhanced for loops, collections en nog veel meer. Simpel gezegd, CLDC is de JVM voor Java embedded.

Verder komt Java ME 8 met een Embedded Profile specificatie (JSR 361) die als doel heeft flexibele applicaties te bouwen. Deze specificatie wordt MEEP genoemd en bouwt verder op CLDC 8. De specificatie levert een lichtgewicht service model, shared libraries, Multi application concurrency, inter-application communicatie, een event model, applicatie management en API keuze vrijheid. Dat laatste maakt het mogelijk om keuzes te maken in de APIs die je nodig hebt om zo je applicatie verder te optimaliseren voor apparaten met een kleine memory footprint.

Het ontwikkelen van real time applicaties wordt niet ondersteund. Het is wel mogelijk een interface te maken met de embedded kernel of OS om deze functionaliteit te verkrijgen, maar daar moet je zelf in voorzien. Ik vrees dat deze tak van sport voorlopig weggelegd is voor C/C++ applicaties. 

Tooling

Voor dit artikel is Netbeans 8.0 Early Access als tooling gebruikt met een Raspberry Pi model B als ontwikkelbord. Persoonlijk werk ik voornamelijk met Eclipse, dus de eerste stap was het downloaden van Netbeans 8, de Early Access SDK en het prepareren van mijn Raspberry Pi. De documentatie is uitgebreid en goed te volgen en ik verwijs je dan ook naar deze pagina’s. Mocht Netbeans een foutmelding geven over een niet gevonden Java versie, dan moet je de parameter ‘netbeans_jdkhome’ activeren en het pad invullen naar de laatste JDK. Het configuratiebestand kan je vinden in etc/netbeans.conf van je Netbeans folder.

Eerste indruk

Een Java ME applicatie wordt een MIDlet genoemd. Een MIDlet maakt gebruik van de Mobile Information Device profile van de CLDC. Voor Java ME 8 zijn dit dus het embedded profile MEEP 8. Om gebruik te kunnen maken van MEEP moet je applicatie een implementatie hebben van de abstracte class javax.microedition.midlet.MIDlet. Het codevoorbeeld 1 komt van Oracle’s ‘Hello World’-tutorial en toont duidelijk de noodzakelijke interface met MEEP. Het voorbeeld verraadt ook dat we, wat betreft de documentatie, met een Early Access versie te maken hebben.


package imletdemo;
import javax.microedition.midlet.MIDlet;
 
public class IMletDemo extends MIDlet {
       boolean bFirst = false;
 
       public void startApp() {
           if (bFirst = false) {
              try {
                 // Perform startup operations
             } catch (Exception ex) {
                 ex.printStackTrace();
                 return;
             }
             bFirst = true;
          } else {
               System.out.println("IMlet Demo is already started...");
          }
          // Start program here
      }
 
     public void pauseApp() {
          //  Pause the application
     }
 
     public void destroyApp(boolean unconditional) {
        bFirst = false;
         // Close all resources that have been opened
      }
   }

Listing 1: Voorbeeld uit Oracle documentatie

Het is tijd om een demo applicatie te bouwen met de Raspberry Pi. Het doel van de applicatie is om een aantal LEDs aan te sturen. Dit is zo’n beetje de ‘Hello World’ in de elektronica. Dit voorbeeld is al eerder besproken in Java Magazine. Voor de volledigheid staat het schema van de proefopstelling in figuur 1. Daarnaast staat de demo applicatie uitgebreid beschreven in de documentatie van Oracle. In de appendix van de Oracle documentatie staan de referenties van de Java constanten naar de GPIO pinnen. De links naar de documentatie staan in het referentiekader. Na het bouwen van de demo applicatie heb je een beetje een gevoel hoe je de GPIO kan aansturen. Je kan op eenzelfde manier andere aanwezige aansluitingen benaderen.


Figuur 1

Mocht je meerdere Java ME applicaties draaien op één apparaat, dan kan het handig zijn om LIBlets te gebruiken. Een LIBlet is een jar dat gebruikt kan worden door een of meerdere applicaties. Dit is vergelijkbaar met het concept shared libs. Door je herbruikbare code op te delen in LIBlets maak je efficiënter gebruik van de beschikbare schijfruimte op je applicatie en word je code beter onderhoudbaar.

De afhankelijkheden tussen LIBlets en MIDlets worden beschreven in het manifest van de jar of in een optionele Application Descriptor. Een Application Descriptor is een bestand met de extensie .jad. Deze bevat dan het attribuut “MIDlet-Dependency-<n>”. De <n> staat voor een positief getal. Het format van de attribuutwaarde is <type>;<level>;<name>; <vendor>;<version>.  De gekozen waarden hebben een relatie met elkaar, afhankelijk van de gekozen combinatie. Het gaat wat ver om alle verschillende combinaties te bespreken. Ik beperk me even tot enkel het <type>.

Het <type> kan een LIBlet, service, standard of proprietary zijn. Als het een LIBlet is, dan wordt de LIBlet of MIDlet gedownload vanaf de locatie die vermeldt staat bij het attribuut  <MIDlet | LIBlet>-Dependency-JAD-URL-<n>. De getallen <n> moeten overeen komen.

Met het standard type geef je aan op welke standard APIs (JSR) je een afhankelijkheid hebt. Een deel van de MEEP APIs zijn namelijk optioneel. Je hebt dus de mogelijkheid om custom profiles aan te maken om zo schijfruimte en geheugengebruik van je MIDlet te verkleinen. Mocht je een applicatie willen bouwen voor een specifiek doel, dan is het handig om je profile zó op te bouwen, dat deze zoveel mogelijk de dingen bevat die je daadwerkelijk nodig hebt. Mocht je een fout maken in de koppeling, dan krijg je een status code 906.

Java ME ondersteunt ook de ServiceLoader API. Deze API maakt het opzetten en uitwisselen van je applicatie op service niveau in verschillende modules makkelijker. Elke module, een jar of een LIBlet, heeft een configuratie map genaamd /META-INF/services. Deze services map bevat een set van tekstbestanden die dezelfde naam hebben als de interface die je voor de ServiceLoader beschikbaar wil maken. In elk tekstbestand staat de implementatie van de interface benoemd die je via de ServiceLoader kan aanroepen. De ServiceLoader API wordt wel eens vergeleken met OSGi. Dat is echter onterecht. OSGi is namelijk veel krachtiger en geavanceerder. De ServiceLoader API is desalniettemin een welkome aanvulling. Het levert een simpele vorm van dependency injection en maakt het mogelijk om delen van applicatie gemakkelijker van een upgrade te voorzien. Je moet naast het configureren van je services ook de dependencies vermelden in het manifest file of de application descriptor. Dit doe je door voor het attribuut “MIDlet-Dependency-<n>” het type service te kiezen.

Conclusie

De Java ME 8 versie ziet er zeer verzorgd uit. De documentatie is uitgebreid en goed leesbaar vanwege de heldere uitleg en vele voorbeelden. Daar mogen veel applicaties wel eens een voorbeeld aan nemen. Er is veel werk verzet om de APIs die voor SE als vanzelfsprekend ervaren worden, ook naar het embedded platform te brengen. Dit maakt het voor veel SE en EE ontwikkelaars heel herkenbaar en voor ME ontwikkelaars gaat er waarschijnlijk een nieuwe wereld open. Ik heb het nog niet gebruikt in een echt project, dus ik kan nog weinig zeggen of het echt veel verschil maakt en of de tooling zo goed is als het pretendeert te zijn. Het ziet er in ieder geval veelbelovend uit. Het spotgoedkope ontwikkelplatform in de vorm van een Raspberry Pi en de goede ondersteuning maakt Java ME interessant om eens een weekendje uit te proberen. Nu nog een goed idee voor een embedded oplossing of een hobby projectje …

Referenties

http://bit.ly/JavaME8_FAQ

http://bit.ly/JavaME8_Start

http://bit.ly/JavaME8_RaspberryPi

 

Streamer: Software speelt een steeds belangrijkere rol om intelligente technologie mogelijk te maken. Oracle neemt positie in deze opkomende markt met Java Micro Edition (ME) 8.