So here you are with your shiny BlueMind setup. You’ve heard about our grand architecture plans, extension points, p2 platform, REST API, but you find it hard to get started. Rejoice! This article has been written just for you.
You need to know some java, and be more or less familiar with maven.
Your goal: a dummy scheduled job
Let’s say your BlueMind add-on will be a scheduled job. You can view the BlueMind scheduler as an internal CRON that will execute jobs when planned, which is pretty handy to assist you in administrating your server.
This scheduled job will log some dummy stats – basically what we’ll do is just a placeholder to demonstrate how to glue the REST API bricks together. Doing something more meaningful will be left as an exercise to the reader 🙂
Your scheduled job will list all mobile devices for all users for all domains of your BlueMind server. Just because you can. We’ll call it MobileDevicesListingJob.
A word of caution
Don’t forget that when you’re using the REST API with a BlueMind server, you’re dealing with real users data and it’s pretty easy to make mistakes, since everything you can do in BlueMind can be done using the REST API. There won’t be a confirmation screen like we do in the Administration Console: when in doubt, just don’t. Or better: do your API tests on a sandbox server. We won’t be modifying data in this tutorial, so you should be safe, but you’ve been warned.
Bootstrapping a maven project
If you take a peep into BlueMind internals, it’s OSGi bundles all over the place. Since we want to build a BlueMind add-on, we depend on BlueMind target platform.
This target platform is published as a p2 repository, and you can find it at http://pkg.blue-mind.net/p2/latest/
As the URL implies, this is the latest and greatest BlueMind target platform. It will get updated every time we publish a new BlueMind release – and hopefully upgrading won’t break your work.
We’ll be using Tycho, which makes it easy to build your bundles with maven. Here is the simplest project_structure. Download it and extract it somewhere.
This project is restricted to the bare minimum. I won’t delve into the details of the configuration files since they are not BlueMind specific, but I want to emphasize two points:
- pom.xml declares where to find the BlueMind target platform
- plugin.xml declares what extension point we’ll be using, namely scheduledjob_provider, along with the name of our soon-to-be-written java class: org.example.mobiledeviceslistingjob.MobileDevicesListingJob
The rest is just boilerplate configuration.
Alternatively, you could also use our maven archetype to bootstrap your project. Or clone bluemind-samples to find an existing add-on to adapt. There are more than one way to skin a cat. Or a duck. Well…
In the project directory, you can run:
mvn install
Et voilà! You’ve built your project, but it won’t work yet: there’s no code.
Eclipse to the rescue
You may just go ahead and write the java code using your favorite editor, but here is how you’ll do with Eclipse:
- Import your maven project into your workspace
- Tell eclipse about the BlueMind target platform: go to Preferences, search for “Target Platform”, and add a new target platform definition. You need to start with an empty target definition, pick up some name (for instance “BM target platform”), then add the URL above as a new Software Site location:
Select all (the “Uncategorized” checkbox in the previous screenshot), click on Finish and you’re done. Careful, you need to select the target platform we’ve just defined before you close the Preferences window.
Setting up the dependencies
We need to declare what parts of the BlueMind target platform we’ll actually use in the MANIFEST.MF. Our REST API online documentation for will help you to cherry-pick the parts you’ll need. If you’ve installed the optional bm-docs package and given the Api docs permission to your user, this documentation should be available right in the BlueMind UI:
Icing on the cake: this inline documentation is interactive, so you can execute calls using the javascript client. Beware, the previous caution notes also apply! (the harm you’ll be able to do depends on your logged-in user’s rights)
The BlueMind source code is also be a good place to find inspiration.
Here are the dependencies we’ll need, just add these lines at the end of the MANIFEST.MF:
Require-Bundle: net.bluemind.domain.api, net.bluemind.user.api, net.bluemind.device.api, net.bluemind.scheduledjob.scheduler, net.bluemind.core.rest, net.bluemind.slf4j
- net.bluemind.*.api : the REST apis we’ll need to explore domains, users and mobile devices
- net.bluemind.scheduledjob.scheduler: to make use of the extension point
- net.bluemind.core.rest: to setup authentication to the REST API
- net.bluemind.slf4j: logging classes – since we won’t do much more than log some information at the end of the day
Have fun with the REST API
So go ahead and create the class we’ve declared in plugin.xml: org.example.mobiledeviceslistingjob.MobileDevicesListingJob. It has to implement IScheduledJob for scheduledjob_provider to be able to plug it in. Here is the complete code. I will only include here the actual business logic:
// logger will write in bm core logs (/var/log/bm/core.log) logger.info("Executing MobileDevicesListingJob"); // sched will write in the execution report, that you can send by mail in the Job setup UI sched.info(slot, "en", "Collecting mobile devices data for all users...\n"); // write header row for the data to come sched.info(slot, "en", "device; isWipe; lastSync; user; domain"); // initialize client for domain service IDomains domainService = ServerSideServiceProvider.getProvider(SecurityContext.SYSTEM) .instance(IDomains.class); // loop on all domains domainService.all().stream().forEach(domain -> { // initialize client for user service IUser userService = ServerSideServiceProvider.getProvider(SecurityContext.SYSTEM) .instance(IUser.class, domain.uid); // loop on all users userService.allUids().stream().forEach(userUID -> { // grab full details for user ItemValue<User> user = userService.getComplete(userUID); // initialize device service for each user try { IDevice deviceService = ServerSideServiceProvider.getProvider(SecurityContext.SYSTEM) .instance(IDevice.class, userUID); // loop on all devices deviceService.list().values.stream().forEach(device -> { // collect info for this device List<String> deviceInfo = new ArrayList<>(); deviceInfo.add(device.displayName); deviceInfo.add(Boolean.toString(device.value.isWipe)); deviceInfo.add(device.value.lastSync.toString()); deviceInfo.add(user.displayName); deviceInfo.add(domain.displayName); // write a line in the report sched.info(slot, "en", String.join("; ", deviceInfo)); });; } catch (ServerFault exception){ // Skipping this user since she doesn't have a "device" container } }); });
Deploy to your BlueMind server
You can compile this code with
mvn clean install
Then drop the resulting jar (target/org.example.mobiledeviceslistingjob-1.0.0-SNAPSHOT.jar) in the folder /usr/share/bm-core/extensions of your BlueMind server. Then you can restart bm-core
/etc/init.d/bm-core restart
And your job should appear among the Scheduled Jobs in the Administration console. You can then execute it, schedule it, send the report to your best friend, it’s all yours.
Caveat: if you need to recompile/redeploy your extension, you may need to delete bm-core’s cache to be sure the fresh jar is picked up:
rm -Rf /var/lib/bm-core
Talking REST from the outside world
You’ve noticed we’ve used a ServerSideServiceProvider to initialize the REST API services, but you can of course talk REST from the outside world, for instance by using our python client. You need a BlueMind API key to do so.
Share your work!
Don’t bother sharing your MobileDevicesListingJob, but once you’ve done something useful you may want to share it on BlueMind Marketplace. We’ll be looking forward to your contributions!