So you have written this new cool service (hopefully using Mule), and you even develop an insanely great iOS app to complement your new cool service. In todays article I'm going to show you how you can make your service even more awesome with Mule Cloud Connect by allowing your service to send push notifications to your iOS app.
What is Mule Cloud Connect?
Mule Cloud Connect is a technology part of Mule ESB 3 release, and allows developers to quickly and efficiently create new connectors to different cloud services. We thought really hard here at mulesoft about how can we make our developer-base more productive, and how can we leverage the thousands of software-as-a-service (SaaS) platforms out there without breaking a sweat.
Generating the project
Mule Cloud Connect is a technology inside Mule plus a software development kit that we call “The DevKit”.
As we stated earlier we will be building a Cloud Connector for sending Apple Push Notifications. There are several Java libraries out there that accomplish this, but I have picked java-apns for no other reason but the fact that is seems to be the most maintained of them all.
Before we begin, make sure that you have downloaded and unpacked our DevKit. The latest version can be found here. The DevKit contains two scripts (one for Unix-derivatives, and one for Windows) called create-cloud-connector. The script will ask you a series of questions, answer “apple-push” for the first one, and leave everything else as default.
See the following console output as a reference:
So, now that we have our skeleton project ready is time to start coding…
As we discussed earlier all cloud connectors are at their core java POJOs. Our DevKit will parse these classes, build an AST from them and generate all the code that is necessary for them to be invoked from a Mule flow. Let's dive in:
First you will notice that our class is decorated with an @Connector annotation and within there is a parameter named namespacePrefix. This annotation will tell our DevKit that this POJO is in fact a cloud connector and code should be generated for it. The DevKit will parse this class and extract everything that contains @Property, @Operation and @Transformer.
@Property annotation is used to configure our connector and they can be placed at individual class fields.
@Operation on the other hand is applied to methods; and they let our DevKit know, that the method in question can be invoked from Mule.
As you can see from the example the DevKit already generated a sample operation for us, before we delete it and start coding our own, let's first add the configuration information to our connector.
We are not going to dive into how the Apple Push Notification Service actually works, we expect our readers to know this already. If you don't, then take 5 minutes and jump here where you can find the information you need to understand what we are going to do.
To send a notification we need a destination gateway (this includes hostname and port) and an Apple issued certificate. These three configurable pieces of information can be declared in our connector as follows:
We only need to declare the fields and set the @Property to them. Of course, we will also need to implement getters and setters for each.
Such configuration can be declared in our Mule config as follows:
So, we will implement a single operation called send. This send operation will take several parameters (most of them optional). The only mandatory parameter will be the deviceToken used to identify which iOS device this notification is for. Let's code this method:
I guess this code deserves some explanation. First of all, notice that we annotated our method with @Operation annotation. It will let our DevKit know that this method can be called from a Mule flow. Also, notice that we are using @Parameter annotation on certain methods to declare them optional. Optional parameters are supported and if the type of the parameter is not a primitive the method will receive null upon being called if a value for it is not specified. Optional parameters whose type is a primitive require a default value of course, since they cannot be null.
This is what an example call would look like. As you can see it is pretty straight forward. The operation name gets its camel case notated name split by word and each word concatenated by hyphens. Since this method is called just “send” the schema name remains the same. As an example, if the method was named “sendPushNotification” then the our DevKit will make that operation available to the flow under the name “send-push-notification”.
As you have probably guess already all parameters are mapped to XML attributes. There are exceptions to these rule of course, an one of those are collections. Our send method has a fields parameters which is a simple key/value map used to send custom information to the iOS app thru a push notification. Let's look at an example call which involves using the fields parameter:
As you can see, collections are mapped to inner elements whit in the operation. The fields element name is derived straight from the parameter name, and the item elements use a singularized form of the parameter name (in this case field).
The End Result
So here is what the end result looks like, of course that this requires a custom iPhone application to obtain the device token. This is what you see at the bottom of the first screenshot.
If you like to know more about the Mule Apple Push Connector, go to the Muleforge page. The source code for this connector is available and there is also an extra folder which contains the sample iPhone app.