Wednesday, January 24

Migrating from Maven to Gradle - maven-assembly-plugin

When you have maven-assembly-plugin and you need to migrate it to Gradle you will probably use copy or zip tasks.

This is the Maven code we want to convert

This is the assemblyDescriptior.xml file



This is the resulting Gradle code


Let's break it down.
In my case all the assembly plugin did was to collect files from several directories and zip them all together.

I've used the ability to Gradle to run Groovy code and created a Zip task which copy files from each of the directories specified in the assemblyDescriptor.xml file.

The real work is done in line 23-24 where we take each folder and put it inside the zip file.

Finally in line 21-37 we provide the zip file as an artifact of this project so it can be consumed by other projects. This allow us to consume it as Gradle dependency in the following way:

dependencies {
    deploymentConf project(path: ':mqm-server-root:mqm-pom:mqm-deployment-conf', configuration: 'deploymentZip')
}

Notice the configuration part at the end.

Migrating from Maven to Gradle

I've started to work on a large project, few years old, about 100 developers and millions of lines of code. The project is a web application deployed both to difference clouds and on-prem. Everything is built with Maven and take, IMHO, way to much time to build.

After a few month of working with it, we've decided to migrate the project from Maven to Gradle. It was actually easier than I thought to convince stack holders to do it, but it still takes longer than I thought it will take.

I'll post problems we've run into and how we solved them, I think it can help others who decide to migrate from Maven to Gradle.

Here are some of the things we had to deal with:

  • Migrating Java libraries
  • Migrating Maven Plugins
  • Building war projects
  • Doing war overlay
  • Building docker images
  • Building RPM files
  • Run Webpack and grunt
  • Run unit tests and integration tests
  • Migrate or adjust the CI process for Gradle
  • Migrate maven-assembly-plugin

Wednesday, February 8

i10n and Plural Forms

Have you know that some languages have more than two plural forms?
I never notice this fact and was blind to it but the creators of gettext l10n system were not.

What I thought was the general rule?

Most English speaking people are used to the fact that ordinal things are either single or plural but even in English when you count centuries you say 1st, 2nd, 3rd, 4th, 5th and so on. So even in English you sometime need to have special cases when converting pure numeric values to human readable text.

I was surprised to see that Arabic has 6 plural forms and the rules of when to use each were not plain at all.

What does this means technically?

When using gettext functions, that's include C but also PHP, Python and other languages you have the l10n function _n which accept the single form and the plural form.
Because each language can have very different rules for plurals each po file has a field name Plural-Forms that define an expression such as nplurals=2; plural=(n > 1);

This expression is built from two parts: nplurals is the number of plural forms supported by the language. plural is C like expression with input n and output of the index of the plural l10n message to use.

Checkout a list of such expressions for languages.

Conclusion

Next time you do l10n remember to use plurals and not just add S when n > 1 :)

Sunday, December 18

React on Google App Engine

I've decide to build an app using React on the client side and Python on App Engine on the server-side.
Search the web for a starter project for that configuration I found only out-of-date solutions, so I've built my own.

tl;dr

How to run React on App Engine?

I've decide to use create-react-app and I've create the required npm scripts to run it locally and deploy it to App Engine.

npm start

Use this command to run both Webpack dev-server and App Engine dev-server for development. Both of the dev-servers support hot-reload so you can use your favorite text editor to edit both React and App Engine code, save it and you have the latest code already in the browser without refresh anything.

npm run deploy

Use this command to deploy the app to App Engine. I'm reading configuration from package.json under "appEngine" to decide which app to push to.

For all the other details page see the github readme.

Friday, December 18

Replacement for Mailbox

Outlook.

I wasn't going for Outlook when I got the news that Mailbox is shutting down.
I've been using Mailbox on my iPhone4 and continue to do so when I've move to OnePlus One.
To my surprise when I search the Play Store for mail the first result was Outlook. I've not use outlook for over 10 years, and I never looked back.

The reason I'm not using Gmail nor Inbox is that they do not support multiple accounts in one view. I have both my personal and work email, both hosted by Google, and I don't want to keep switching between the two accounts.

Outlook is fast, clear and support multiple accounts in one view.

Saturday, August 22

Using MPS to Keep Several SDKs Up-To-Date

It has been very long time since my last post.
This time I'll like to introduce an idea, not a complete solution.
I'm working in a team responsible for keeping 5 SDKs in ship-shape and up-to-date. Each SDK is written in different platform and also different language. To name a few iOS with Obj-C, Android with Java, Unity with C#, Cordova with JavaScript and Adobe AIR with ActionScript3.

Maintain and develop all of those SDKs manually is never-ending work. Even if we'll scale the team and have a team per SDK it will still be hard to maintain because then fragmentation of the different SDKs will happen even more frequently than one team.

After research several directions I've decide to concentrate on using JetBrains Meta Programming System (MPS) to create one meta-language from which we will be able to generate all the different SDKs source code.

It is important to note I'm not trying to generate the entire SDK in each platform, only the parts that are not platform specific which in our case are also the parts that change frequently.

This diagram show the flow

In future posts I'll describe each of those steps:

  1. Building MPS counterpart of each language
  2. Building TextGen for each language
  3. Building X language (I haven't found a name yet)
  4. Building model-to-model transformation for each language
  5. Build scripts to combine each SDK platform-specific part with the auto-generated part
  6. Hidden parts that I'm not able to see yet (please leave a comment if you do)

Tuesday, August 5

ProtoBuf in Unity3D

Recently I needed to add two way communication to Unity3D plugin I worked on. We decide to use plain-old-sockets and use Protocol Buffers to serialize and deserialize the messages.
We already had the proto file that define the messages and the server side is already written so all I needed was ProtoBuf implementation for .NET. The main problem is that most C# libraries for ProtoBuf either use attributes and not proto files or they use reflection which is not supported in Ahead-Of-Time (AOT) environment like Unity3D on iOS.

After some research I decide to use ProtoBuf C# Code Generator project by Peter Hultqvist. The main difference between this and other ProtoBuf implementations is that this one create C# code that does not use reflection and does not depend on binary libraries. It generate 3 files:

  1. The clean messages file that contain only the properties of each message
  2. The somewhat messy serialization/deserialization counterpart of each message.
  3. Helper classes
I use this library on Mac OS X with mono and it run without a problem. It generate clean code that you can easily read.

The few minor issues I did find were quickly (2 hours) fixed by Peter.

Things to note

Api Compatibility Level

One important notice for Unity3D developers: because the current generated code uses InvalidDataException which is not part of .NET 2.0 subset. If you don't to the following change the project will fail when building iOS XCode project with error message that not explain what is wrong.
You must do the following before exporting to iOS XCode project:
  1. Open Build Settings window
  2. Select iOS
  3. Click Player Settings... button
  4. Under Optimization section change Api Compatibility Level to .NET 2.0

Reading Message

If you want to read message from a socket you will need to wrap your Socket instance with NetworkStream and then wrap that with SilentOrbit.ProtocolBuffers.StreamRead. This might be confusing because there is already StreamReader class in .NET, I point that to Peter and I'm sure he will find other name.
If you don't wrap your NetworkStream with StreamRead you'll find that the underlying code uses Position property which is off course not available in NetworkStream.