Azure functions Photo upload function using JAVA

We will go over a working example that uploads a photo to Azure Container as a Blob. The final codebase will run to upload a photo-based on a CURL command

curl -w "\n" http://localhost:7071/api/uploadSathishPhoto --data /Users/sathishjayapal/Downloads/DSCN4934.JPG

High level architecture


Azure CLI

Azure subscription



Maven CLI

Now let us see how to go about getting this to work with Azure functions. The reason I chose Azure functions is the free tier that you get for doing a quick app. The first million calls are free and there is a 5GB free space in the Azure storage. The API is front-ended with Azure API services. Few configurations can be done, but we will keep that in another post.
The first block we are going to look is the Function, to get this going, we will use the maven archetype for developing Azure functions.

mvn archetype:generate -DarchetypeArtifactId=azure-functions-archetype

This creates a bare Azure function that can get an Http Post call to a URL. Two files will be created from the archetype. The first one is host.json and local.settings.json. Now the other important item to look is the pom.xml file.

    <azure.functions.maven.plugin.version>1.3.4</azure.functions.maven.plugin.version>   <>1.3.0</>
    </stagingDirectory>    <functionResourceGroup>photofunctionrg</functionResourceGroup>
The function name is uploadSathishPhoto

We have to make sure the function name here matches with the Java Function API. So here is the JAVA API function

public class UploadSathishPhotoFunction {

  public static final String PHOTOPATH = "photopath";

  public HttpResponseMessage run(
      @HttpTrigger(name = "req", methods = {HttpMethod.GET,
          HttpMethod.POST}, authLevel = AuthorizationLevel.FUNCTION) HttpRequestMessage<Optional<String>> request,
      final ExecutionContext context) {
    context.getLogger ().info ("Java HTTP trigger processed a request.");

    String photometer;
    photometer = request.getQueryParameters ().get (PHOTOPATH);
    String photograph = request.getBody ().orElse (photometer);
    if (photograph == null) {
      return request.createResponseBuilder (HttpStatus.BAD_REQUEST)
          .body ("Please pass a photo path on the query string or in the request body").build ();
    } else {
    BlobServiceClient blobClient;
    BlobContainerClient container1;
    try {
      blobClient = BlobClientProvider.getBlobClientReference ();
      context.getLogger ().info ("\nCreate container ");
        container1 = createContainer (blobClient);
      context.getLogger ().info ("\n\tUpload a file as a block blob.");
      BlobClientProvider.uploadFileBlocksAsBlockBlob (container1, photograph);
      context.getLogger ().info ("\t\tSuccessfully uploaded the blob.");
    } catch (Throwable e) {
      context.getLogger ()
          .log (Level.SEVERE, "Java HTTP trigger processed a request.", e.fillInStackTrace ());
      return request.createResponseBuilder (HttpStatus.OK).body ("Hello, " + photograph).build ();

Now the function relies on the Azure model, where there is a Need for a BlobClient to start the entire upload function. Then there is a container that holds on the blob. Finally, the blob item will be stored. In our application, we have two classes that are going to take care of the initializing a BlobClient and Container. We are going to upload all the pictures in this function to a specific container. The source code for these classes is checked into.

To run the function run the maven commands

mvn clean install
mvn azure-functions:run 

When doing the install, keep an eye on When doing the install, keep an eye on the console output to make sure there is an Azure function being built. This gives an indication to us that the function is being packaged.

[INFO] Step 1 of 7: Searching for Azure Functions entry points
[INFO] 1 Azure Functions entry point(s) found.

In order to run the application locally, the maven command is

 mvn azure-functions:run

Keep an eye on the console to make sure the function is started

uploadSathishPhoto: [GET,POST] http://localhost:7071/api/uploadSathishPhoto

Hosting environment: Production
Content root path: /Users/sathishjayapal/IdeaProjects/blob-azfunction-start/target/azure-functions/uploadSathishPhoto
Now listening on:
Application started. Press Ctrl+C to shut down.
[01/13/2020 02:47:54] Host lock lease acquired by instance ID '0000000000000000000000004DD021D9'.

To check if all works, CURL command is

curl -w "\n" http://localhost:7071/api/uploadSathishPhoto --data /Users/sathishjayapal/Downloads/DSCN4934.JPG

The JPG will get uploaded based on the param that is being passed to the CURL. To confirm let us look at the Azure portal.

The complete code for this can be found here. As well Azure has a great getting started guides. Check these following links

This entire post is based on JAVA 8 version. I got some specific errors when running in versions other than JAVA 8.

Cloudformation YAML file pass parameters

We have a simple cloud formation file in a YAML format. There are couple of parameters that need to be passed to this template. We want to make sure the parameters that are being passed are based on whether it is a PROD/Test environment.

Here is the sample simple S3 upload file template

AWSTemplateFormatVersion: 2010-09-09
    Type: String
    Default: DEVCorsRuleID
    Description: Cors ID Rule information for the s3 bucket to post
    Type: String      
    Type: 'AWS::S3::Bucket'
      BucketName: !Ref S3BucketName
      AccessControl: PublicRead
         	Id: !Ref CorsIDRuleName
          MaxAge: '3600'

Now based on the environment, we have two parameter files that have to be used. For test we will use the test-config.json file and production we will use the prod-config.json file.

Sample test-config.json

"ParameterKey": "S3BucketName",
"ParameterValue": "mynewawesomebucket20191231"
"ParameterKey": "CorsIDRuleName",
"ParameterValue": "myawesomecorsruleid"

To run the stack from cloud formation we can run the command

aws cloudformation create-stack --stack-name startmyinstance  --template-body file://template1.yaml --parameters file:///S3Uploader/test-stack-s3-configuration.json

Few take aways:

  • I was not able to pass parameters from another yaml file
  • Template can be yaml, but when parameters are to be externalized then it is had to be from a JSON file only
  • Parameter file though in JSON had to follow some specific conventions for yaml file. In our example “ParameterKey”, “ParameterValue” had to be in the format for CF/YAML config. To pick up.
  • Sample code for this is at github

Avant UI | Bootstrap UI Kit

I liked the starter template for bootstrap using the Avant UI. I think this was a quick way for RAD, and instead of figuring out a layout that might fit your needs.

Avant UI is a free Bootstrap UI Kit for web development
— Read on

They collect minimal information and if you would like can make some a quick contribution for their effort. 

Spring Boot loading static content

We will try to quickly how to go about loading and serving static content using Spring Boot 2. There was a difference in how boot 2.0.0 was loading static resources to 2.1 version now. In this article, we will take a simple web application and load the static resources that are defined in the resource folder.


Here is how the project is setup for this article.



I decoupled the pom as a parent and one for the web project. Spring by default without any config changes loads static content from the path that is defined in ResourceWebHandler. But in the article we are going to overwrite the default path.


We first over-ride the classWebMVCConfigurer. The sample snippet of override is.,


public class BootSamplerWebAppWebConfigurer implements WebMvcConfigurer{
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/pages/", "/error/","/images"));

public void addViewControllers(ViewControllerRegistry registry) {


As we can see, there are the class couple of methods that we override to tell boot where our static resources are located. I don’t like the favicon that comes from spring framework. So here is the code to serve favicon static content. Here is the code to override that.


public class BootSamplerFavIconConfiguration {
public SimpleUrlHandlerMapping customFavIconHandlerMapping() {
SimpleUrlHandlerMapping simpleUrlHandlerMapping = new SimpleUrlHandlerMapping();
simpleUrlHandlerMapping.setUrlMap(Collections.singletonMap("/favicon.ico", faviconRequestHandler()));
return simpleUrlHandlerMapping;

public ResourceHttpRequestHandler faviconRequestHandler() {
ResourceHttpRequestHandler resourceHttpRequestHandler = new ResourceHttpRequestHandler();
ClassPathResource classPathResource = new ClassPathResource("/static/images/favicon.ico");
List<Resource> locations = Arrays.asList(classPathResource);
return resourceHttpRequestHandler;


Error pages are from a static content directory, we will have to override the class ErrorrPageRegistar


public class BootSamplerWebAppErrorRegistrar implements ErrorPageRegistrar {

public void registerErrorPages(ErrorPageRegistry registry) {
registry.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND, "/error/404.html"));
registry.addErrorPages(new ErrorPage(HttpStatus.BAD_REQUEST, "/error/400.html"));


The main method to run the application has some tweaks, here is the code block for that.


@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class,
public class MainApp extends SpringBootServletInitializer {
public static void main(String[] args) {
final SpringApplication springApplication =
new SpringApplication(BootSamplerWebAppErrorRegistrar.class,
BootSamplerWebAppWebConfigurer.class, BootSamplerFavIconConfiguration.class,


When running the, we should get index.html served from the folder main . The template for this index is from the bootstrap template blackrock digital.



Finally all code for this is in github.