Building a serverless url shortener with Azure Functions and Java, part one

I’m a Java engineer who doesn’t really know the intricacies of cloud development as well as my ‘Cloud Developer Advocate‘ job title suggests that I should. That is why I’m such a fan of Azure Functions – it makes the concept of serverless programming a possibility for Java developers. Serverless is one of those odd marketing terms, but what it essentially boils down to, as my colleague Jeremy Likness likes to say, is that it is ‘less server’ – which sounds perfect for me! 🙂

To better understand Azure Functions, I set out to build a URL shortener app, so that I could take a long URL like http://docs.microsoft.com/en-us/java/azure/ and replace it with a short url like http://java.ms/docs. I’m not the first Microsoft Cloud Developer Advocate to do this, as it seems like one of those projects people like to do when they first encounter serverless programming 🙂 You can read Jeremy’s blog about how he built a URL shortener in C# (he’s put a lot more hours into features than me, so there is a lot of good ideas there to borrow 🙂 ).

This is a first post in a series. I’ll add links here when I publish new articles, but you can always follow me on Twitter to keep updated. The total topic list for this series includes:

Serverless Value Proposition

The main attraction to building a link shortener using serverless programming is that you only pay for the time your function is actually operating – you aren’t paying for 24/7/365 server uptime, which is pretty handy for a link shortener that only operates occasionally. You also don’t need to worry at all about concerns such as scaling your service – the cloud provider takes care of that for you. I wanted to build this as cheaply as possible (i.e. consume as few resources, and use the cheapest options) in Microsoft Azure, and I didn’t want to have to write code in any language other than Java, and I really didn’t want to have to worry about all that other cloud nonsense 🙂

In terms of actual costs, Jeremy stated in his blog post the following:

Although actual results will differ for everyone, in my experience, running the site for a week while generating around 1,000 requests per day resulted in a massive seven cent U.S.D. charge to my bill. I don’t think I’ll have any problem affording this!

He also updated his calculations for cost in a follow-up tweet:

I tend to agree – I think I can afford this serverless lifestyle! 🙂 So, off I set on my adventure… I started by buying two domain names – jogil.es and java.ms – which both seemed relevant to my interests. After that, I started writing code (and note: this project is all open source on GitHub)! 🙂 Let’s get into it…

Creating a Java Function App

Setting up a new Azure Function App is simple, especially with the Java / Maven tooling that is available. Firstly though, if you don’t have an Azure account, you can create one for free, and it comes with 1,000,000 Azure Function calls free per month forever (which is well in excess of what I need, so I don’t think I’ll even be spending 7 cents)! Once you have an account, you can follow the Azure Functions on Java tutorial to step through the software setup and creating your own function app. The approach works really smoothly – it’s all based around a few Maven commands that will auto-generate your first function, and you even use this to deploy to Azure! Because of this, I’m not going to dive any more deeply into getting started with Azure Functions with Java, and I’m just going to dive into some of the configuration details, and then into the code for building a link shortener.

Once you’ve done your first mvn clean package azure-functions:deploy, you can log in to the Azure Portal to see your function app, which will look something like this:

In here you’ll see a list of your functions in the left column (my app has four functions: frontend, keepAlive, redirect, and shortcode, as well as details on the URL, subscription, etc. Today we will just discuss the redirect and shortcode functions, and address the other two functions in another blog post.

By default, to access any of your functions, you simply take the base URL (in the image above, it is https://jogiles-short-url.azurewebsites.net), add /api/, and then the function name. For example, the redirect function is at http://jogiles-short-url.azurewebsites.net/api/redirect (and, low-and-behold, if you go there with a given shortcode, it should work – try http://jogiles-short-url.azurewebsites.net/api/redirect?shortcode=docs). As noted at the beginning of this post, the final URL is http://java.ms/docs, but that is achieved using an Azure Functions Proxy, which simply redirects to the full URL shown here. We will return to proxy configuration in a later blog post, to achieve this nicer URL effect.

URL Shortening Function

The key requirement of a URL shortener is to take a URL and return a shorter URL. In terms of implementation, it’s quite simple really – take a url query parameter that we want to convert, use some algorithm to create a unique short code, and store it in some persistent storage. That is basically what you see in the code below, with one additional feature: the shortcode function also supports an optional shortcode parameter. If the user specifies a preferred shortcode (like ‘docs’ above), we simply store that mapping in the persistent storage without running the shortcode algorithm. Here’s essentially the full code listing (remember all the code is on GitHub):

As can be seen, at present there is no authentication, so anyone can create shortlinks (I might rectify this some day soon) 🙂 We simply check the url is valid, and if the user wants an auto-generated shortcode or if they want to provide their own. Based on this, we go in to one of two functions. In the auto-generated case, we iterate until we find an acceptable shortcode, and then we persist that into the data store.

In terms of data storage, I’ve written a small wrapper API around the Azure Storage APIs for Java, as I originally intended to use MySQL or SQL Server (with or without JPA), but then I realised that because Azure Functions are built on top of Azure App Service, which has built-in storage available to it. Because of this, I simply piggy-back on the table store that is already available, using the Java APIs explained in the Azure Table Storage guide. I’ve written a simple AzureTableStore class to handle the read / write access to this table:

The end result of all this code is that I have a table that shows all mappings. Here is a screenshot of the excellent (and free) Microsoft Azure Storage Explorer app, looking at my table of short codes (click the image for a larger version):

You can see I simply use the first letter of the RowKey as the PartitionKey, to have an even distribution in all partition buckets. You can also see that of the four short links I have created, two are ‘custom’ shortlinks (for docs and linkedin), and two are auto-generated (00 and zC). To generate the short links, I simply have the following code I use:

Again, it’s not the prettiest or best approach, but it’ll do for now 🙂

The end result of all this code is that a short code is generated, and a short url is returned, including the URL (that is, java.ms or jogil.es, depending on which host was called to shrink the URL in the first place). That’s great, but it is only half the story – now we need to support the user actually going to that URL and it being converted to the long URL again!

Shortcode Redirection Function

The code to convert a shortcode into a full URL is even simpler, it simply gets the shortcode query parameter, looks up the long url in the data store, and does a HTTP 302 redirect to that URL (302 is the status code for a permanent redirect, as opposed to 301 which is temporary, and will therefore put more strain on the function for people who repeatedly visit the same URL). Here’s the redirect function class in full:

The only odd code is the line where I retrieve the url by calling Util.trackDependency(..). This code is simply convenience code that allows for me to more easily track application performance using Azure Application Insights, which I will cover in more detail in another blog. However, here’s the complete function listing, to make it clear that all that really is happening is we’re calling the data store to get the long url, and we’re recording how long it takes into Application Insights:

Summary

This is the core of the URL shortener, but there is a lot more still to cover, which I will cover in follow-up posts in the coming weeks. The total topic list for this series includes:

The main point for this post is that even though I’m not super-skilled in cloud development I was able to implement a simple application that provides a useful service to me, and at an extremely low cost. As I noted at the beginning, the cost to operate this service is mere cents per month! So, if you are a Java developer looking to build web services and don’t want to get bogged down in dealing with server details, you should definitely take a look at Azure Functions today – get started with the free tier and go from there!

Build Spring Boot 2.0 apps with Azure Starters and new VS Code extensions

I’ve said it elsewhere but my new role at Microsoft often places me at the end of a very powerful firehose, and I see a lot of cool stuff going by! Today is no exception – Microsoft has announced full support for Spring Boot 2.0 in the Spring Boot Starters for Azure. In addition to this, there is an updated Spring extension for Visual Studio Code, which allows you to build production-ready apps and easily deploy them to the cloud.
For more details, you should check out the blog post by Yitao Dong.

Java Engineering at Microsoft: Interview with Reiley Yang

Today I have another post in my Java / Azure interview series, this time with Reiley Yang. I met Reiley recently as we were both visiting the Microsoft Shanghai offices at the same time, and I learned more about what he is doing in the area of remote Java debugging with Azure. So, please, enjoy! 🙂

Hi Reiley – can you please introduce yourself to everyone?
Hey, I’m Reiley Yang. I started my career 12 years ago as a C/C++ developer (working on the low level stuff, C Runtime Libraries, compilers, debuggers, etc.), and later worked on different technologies and platforms. My hobbies include working on personal IoT projects, piano playing, woodwork, yard work, and cooking.

You and I met each other recently when we were in Shanghai at the same time, but you’ve been based out of Microsoft HQ in Redmond for some time now. You said you moved from Shanghai partially because you’re a keen piano player but couldn’t easily play piano in Shanghai without annoying your neighbours. Now that you have a bit more space in Redmond, I wondered if any of your piano music was recorded and online?
I do have some recordings, more for myself when I try to see what can be improved, I never published them though. I am a big fan of Chopin and J.S. Bach’s keyboard music. I hope that one day I could play all their works 🙂

When did you start working at Microsoft?
I started in 2006, then quit and worked in a start-up company, and re-joined Microsoft in 2011.

If I recall correctly you previously worked on C++ compilers and the like, and today you find yourself working on Java debugging on Azure. That’s quite a big change! Could you talk more about what you do at Microsoft today, and how you came to be working on Java at Microsoft?
Sure! I started working on the C++ runtime libraries and compilers. Later there was a need to improve the C++ / CLI debugger, which requires knowledge and experience from compiler, so I started to work on debuggers. Since then I’m always connected with debuggers and debugging.

There has been a long history between Microsoft and Java, and Microsoft was not doing well in the Java area in the early years. Now we have put tremendous amount of effort into making Microsoft technologies available for Java developers, and we want Microsoft tools and services to stand out in terms of Java support.

Debugging services in the cloud is hard, we’re experimenting with cloud debugging support for Java, and will add other language support in the future. Here’s a diagram outlining how things go together (click to see a bigger version):

As I understand it, remote debugging is still a proof of concept and you’re still seeking community feedback. How should developers test this functionality, and how should they provide feedback?
We have documented the steps, which explains the steps to debug Java-based Azure Functions in the cloud, and we use GitHub to track issues and collect suggestions.

The scope of the work required for remote debugging is considerable – the debugger must be part of the JVM, it must be exposed through a port in the app service, there must be tooling written that can communicate with this debugger, VS Code will provide a visual interface for remote debugging, etc. It seems like your work cuts across a number of different layers – it must be difficult to line everyone up and get a shared vision of this feature. On top of this, Microsoft has engineering teams in a number of different geographies – how does working on something so complex across so many layers in many geographies work?
There is no magic 🙂

Yes there has been ongoing communications among different teams, the conversations are all based on the BI data and customer feedback. When you put the customers’ requirement in front of the table, you’re more easily to get support from your partner teams.

The VS Code team is in Zurich, Azure Application Platform and Azure Functions team are in Redmond, the Java Debugger team is in Shanghai. Some of the team members need to fight against the jetlag and travel abroad, and some need to switch their working hours so we can have conference meetings across the ocean.

[Jonathan Note: There is a blog post on using VS Code to debug Java applications that might be of interest to readers, as well as a recent article on the latest improvements].

What does a normal day look like for you? Are you able to dive deeply into coding, is there a lot of planning / communication required?
I actually spend a lot of time with customers.

One big difference in the last couple years at Microsoft is the faster release cadence. In the old days, we used to have new release every 3 years, and now it is 3 weeks. We’ve keep a close eye on the feedback from our users, the number of downloads, error reporting, etc. This gives us chance to bring new features to the market as soon as possible, and we can adjust the direction / priority based on the results.

Thanks so much for your time! Do you have any other final words that you want to share with the community?
Yes, I would love to hear how people are using Content Assist / IntelliSense while writing in Java.

What are the most annoying things and what are the features you would love to have. My team is thinking to make improvements in this area, let us know what you would love to have 🙂

We’re looking for crazy ideas that push Content Assist / IntelliSense to a new level using machine learning and AI.

Take one example – developers would spend a considerable amount of time searching for code samples and follow common patterns while using certain API, we want to see whether developers would find it helpful if the IDE could help to generate a code snippet based on the API being used.

Another example is the async feature in Java, will people feel excited if there is a tool to automatically convert sync code to async, or vice versa?

[Jonathan Note: Please leave any feedback you might have for Reiley as a comment below, or else feel free to email me and I will forward it on to Reiley].

Thanks Reiley!

Azure Cosmos DB async Java SDK now available and open sourced

There are a lot of Java SDKs being released by Microsoft these days, and here’s another: the Azure Cosmos DB folks have released version 1.0.0 of their asynchronous Java SDK, and at the same time they have open sourced the SDK repo! There is a getting started application ready for people to sink their teeth into, and the artifacts are already up in Maven Central. Finally, the team has released a benchmark tool, and they said to me that they could reach 43,000 document inserts per second (on a 16 CPU core Ubuntu VM) for documents of 1KB size in gateway mode.

For those unfamiliar with Cosmos DB, check out the Azure Cosmos DB introduction. In summary, “Azure Cosmos DB is Microsoft’s globally distributed, multi-model database. With the click of a button, Azure Cosmos DB enables you to elastically and independently scale throughput and storage across any number of Azure’s geographic regions. It offers throughput, latency, availability, and consistency guarantees with comprehensive service level agreements (SLAs), something no other database service can offer.” From there you can find quick start documentation for SQL, MongoDB, Graph, Table, and Cassandra.

Java Engineering at Microsoft: Interview with Rikki Gibson

Today I have another interview to share! Following my interview with Yoshio Terada, a Java evangelist at Microsoft, today I have an interview with Rikki Gibson, a software engineer at Microsoft, working exclusively on Java-related projects. I am quite envious of his role, as engineering and solving fun problems is always what excites me most! So, to everyone reading – enjoy this post, and I’ll work on getting more stories about Java people at Microsoft up every week or two 🙂

Hi Rikki – can you please introduce yourself to everyone?
Hi there! I’m Rikki Gibson. I come from Corvallis, Oregon and I’m a 2017 graduate from Oregon State University in Computer Science. When I was in school I worked part-time for a few years on .NET-based systems for the Oregon state government, and I have some Java background from a small foray into Android development. When I joined Microsoft in July 2017 I was brought on the Azure SDKs team within Microsoft Developer Division working on Java and .NET libraries.

Outside of working for Microsoft, do you have any hobbies, open source projects, or other things that keep you busy?
I continue to maintain a set of apps for finding out when the bus will arrive in my hometown. I’m also starting to work on writing a Game Boy emulator on the side on weekends. Certainly a solved problem, but I find exploring all the little behaviors of an embedded system like that to be pretty interesting. I’m also into PC gaming, D&D, and hiking when the weather is good 🙂

You’ve only relatively recently joined Microsoft as a Java engineer. What are your impressions of Java at Microsoft?
Yes, it’s been just 7 months, although it feels like that’s gone by fast. Java has an incredible, long-established open source community. It’s a big shift for Microsoft to try and start being a citizen of that community. Even people within Microsoft might find it surprising that unless confidential / preview Azure features are involved, my team typically does work, issue tracking, and code reviews in the open from the very first commit. I’m very happy being in that kind of a space as an engineer.

.NET has the lion’s share of usage on Azure, so it can be harder to raise awareness about our Java offerings. We also have to occasionally fight the tendency to foist .NET-isms onto Java developers. On the bright side, we have more latitude than the .NET SDK teams to make changes that we think will improve the developer experience in Java.

Working in the open can be daunting, but also very rewarding. From my experience contributing to OpenJDK for 9 or so years, you can get all kinds of people appearing to contribute. Do you have anybody from the community helping with development, and do you have any messages to people who might be on the lookout for an open source project they can contribute to (in relation to why yours might be a fun one to join)?
David Moten, who’s very knowledgeable about RxJava, has come and made some really useful bug reports recently from reading our code. Besides that, there have been several people who have showed up with bug reports or PRs to try and make something in particular work better for their use case.

If you’ve got a REST API that you want to create a Java client for, you might enjoy being bold and trying to create it using our stack 🙂 The experience of it isn’t half bad! Otherwise I’d just encourage people to take a look at the libraries they currently use in their own projects and to do a little digging about what the community for those libraries is like—many library teams like to answer people’s questions and hear their feedback. You might find small bugs or work items that you can pick up and complete. It’s very good to have open source projects on your resume.

Microsoft is a huge organization, and Azure is massive. How do all the puzzle pieces fit together between the teams?
The problem we face in delivering Azure services to developers is that we need to multiply the number of Azure services by the number of languages we wish to offer first-class support for. Completely hand-authoring the libraries for communicating with these services would be prohibitively time-consuming and difficult to keep consistent between each other.

Swagger, otherwise known as OpenAPI, is how we formally describe the endpoints available in each service. Azure service teams author these documents, and then we use the AutoRest code generator to generate code in a variety of languages. Ideally, some amount of hand-written code wraps the generated code so that we can be sure we’re presenting a coherent, pleasant experience to developers. This isn’t always the case, depending on the size of the audience for the service, the stability of the service API, or the urgency of delivering new API features. We do a significant amount of work to try and make the generated code usable out of the box, but it’s hard to reach the same level of quality that way.

Today you are a software engineer working on Java at Microsoft. What exactly are you working on?
I work on the core tools that we use to generate API clients in Java. Specifically, I’ve been working on an overhaul of our Java code generator and “runtime” library, which is referenced in our generated Java code to make network calls, authenticate, serialize/deserialize, and many other various tasks. The overall solution has to be suitable both for a user who just wants to show up and learn to make a few simple calls, and a user who wants to have a high level control over how things are done and get as much throughput as possible with minimal usage of system resources.

So your code is what all Java SDKs use to connect to Azure? That feels like a big responsibility! What kind of challenges do you have in your job?
Some of the biggest challenges are around delivering convenience features based on the needs of various teams that depend on us while continuing to function fully across such a general space. It can be a bit of a tightrope walk to implement features for one team without breaking features for another team, and we wind up supporting a lot of implicit “convenience” conversions that stay with us. We have to spend a lot of time considering finer details, like what URL escaping means for different types of URL parameters or what empty strings/collections vs. nulls should mean in various contexts.

It was particularly challenging to implement the network layer of our new Java core using Netty and RxJava. I learned a great deal about concurrency in Java by doing so. Although it’s sometimes discouraging to debug issues that only show up on a server under heavy load, it’s also very interesting and rewarding to reason about and solve problems in that kind of a setting.

I have been quite vocal about the importance of convenience APIs, and I feel like sometimes when you’re in a meeting with me that I’m unintentionally attacking your work. So, sorry if you feel ambushed! 🙂 I have a lot of respect for the challenges you face in auto-generating APIs, and feel bad for arguing the importance of hiding these APIs behind a convenience layer! The fact that you need to cover such a massive surface area, and a surface that is frequently changing, makes your work super important. I know you’re constantly working to improve the auto-generated APIs, so some of the language features in JDK 8 must have you pretty excited. Apart from that, are there libraries you’re fond of using? Reactive APIs, dependency injection, etc, or do you try to keep external dependencies to a minimum?
No worries—I don’t see criticism of the product as criticism of myself 🙂 I don’t disagree with your argument. I just hope we can find a balance that lets us ship code of respectable quality on a reasonable schedule. I pray that something like “void getMetadata()” never ships.

Regarding Java 8: I think CompletableFuture is the right answer for many of our users, and Java 8’s lambdas are already simplifying our code generator considerably. I find RxJava enables some really powerful sequencing of asynchronous tasks, but we also have to think about our users who just want to make a few calls with straightforward semantics that resemble the JDK APIs they already know. Before we made the call to standardize on Java 8 recently, it was particularly challenging, as the JDK didn’t really provide a fundamental type for composable asynchronous programming at that point.

I’m in favor of keeping a minimal dependency count, but the truth is that we have some essential dependencies that we couldn’t live without. They tend to also be the ones where we have to work through the greatest number of breaking changes when we update, and where we hear about our customers getting in trouble with version conflicts the most.

Some of the architectural decisions we made for v2 amount to us choosing to replace some of our dependencies with internal solutions that handle our use case more effectively (particularly Retrofit), and to rearchitect our API surface to hide the dependencies more effectively–particularly the abstract HttpClient/Request/Response types that are meant to allow users to adapt any HttpClient out in the world to work in our stack. I’m optimistic that moving in that kind of a direction in the long term will help our customers use our library in a wider variety of environments.

As you look ahead, what are some of the areas of focus for you and your work? Are you looking into Java 8 to simplify your APIs or Java 9 to modularize the SDK?
After quite a bit of examination of telemetry and release schedules, we’re deciding to require a Java 8 minimum for our upcoming major release later this year. I’m particularly hoping to reduce our third-party dependency burden through use of APIs that are new in Java 8.

I’ve picked up a book on Java 9 modules recently to try and figure out the best experience we can provide for Java 9 users moving forward. I don’t know a ton yet, but I want to make sure we start off on the right foot in terms of which classes are being placed in which packages so that we can properly hide our implementation details.

Microsoft isn’t historically known for its support of Java. How do you find being an engineer working with Java inside Microsoft?
I’m lucky to be on a team with a lot of Java experience and a team culture that expects participation in the open source community. It’s been good for us to be kind of an underdog in this space—we have to work to win the trust of Java developers, and that pushes us to come up with better solutions.

Thanks so much for your time! Do you have any other final words that you want to share with the community?
Thank you for having me. I’d like to say thanks to Dávid Karnok and David Moten from RxJava, and Norman Maurer and Scott Mitchell from Netty for being welcoming and helpful when I showed up with questions or bug reports.